--- title: "Shell 笔记" date: 2019-10-30T11:29:31+08:00 lastmod: 2019-10-30T11:29:31+08:00 tags: ["shell"] categories: ["shell"] --- ## BASH 脚本的 $ 参数 - $$ #shell 本身 PID - $! #shell 最后执行的后台PID - $? #shell 结束代码 - $\* #参数列表 "$1 $2 ... $n" - $@ #参数列表 "$1" "$2" ... "$n" - $# #参数个数 - $0 #shell 脚本名 - $1...$n #shell 位置参数 ## BASH 字符串处理 ```bash # 字符串 str 长度 ${#str} expr length "$str" # 子串 substr 出现位置,找不到返回 0 expr index "$str" "$substr" # 子串 substr 开头匹配,找不到返回 0 expr match "$str" "$substr" # 字符串 str 抽取左起位置 pos 后 长度 len 的子串 ${str:$pos} ${str:$pos:$len} expr substr "$str" $pos $len # 字符串 str 抽取右起位置 pos 前的子串 ${str: -pos} ${str:(pos)} # 正则 pat 抽取字符串 str 开头子串 expr match "$str" "\($pat\)" expr "$str" : "\($pat\)" # 正则 pat 抽取字符串 str 结尾子串 expr match "$str" ".*\($pat\)" expr "$str" : ".*\($pat\)" # 删除字符串 str 开头的最短子串 sub ${str#$sub} # 删除字符串 str 开头的最长子串 sub ${str##$sub} # 删除字符串 str 结尾的最短子串 sub ${str%$sub} # 删除字符串 str 结尾的最长子串 sub ${str%%$sub} # 替换字符串 str 第一个子串 sub 为字符串 rep ${str/"$sub"/"$rep"} # 替换字符串 str 所有子串 sub 为字符串 rep ${str//"$sub"/"$rep"} # 替换字符串 str 开头的子串 sub 为字符串 rep ${str/#"$sub"/"$rep"} # 替换字符串 str 结尾的子串 sub 为字符串 rep ${str/%"$sub"/"$rep"} # var为空或没有设置,代入word,否则代入var值 ${var:-word} # 如果var已经被设置且不为空,则代入它的值,否则代入word,并且在后面var始终为word的值。位置参量不能用这种方式赋值。 ${variable:=word} # 如果变量var已被设置且值为非空,代入word值,否则什么也不代入 ${variable:+word} # 如果变量var已被设置值且为非空,就代入它的值,否则输出word并从shell中退出,如果有省略了word,就会显示信息:parameter null or not set. ${var:?word} ``` ## BASH 数组 ```bash # 定义数组,有三种方式 declare -a array array=() array[0]='value0' # 打印数组第一个元素 echo ${array[0]} # 打印数组所有元素,有两种方式 echo ${array[@]} echo ${array[*]} # 打印数组所有索引,有两种方式 echo ${!array[@]} echo ${!array[*]} # 打印数组的元素个数,有两种方式 echo ${#array[@]} echo ${#array[*]} # 移除数组中索引为2的元素 unset array[2] # 添加id为3的元素 array[3]="" ``` ## BASH 字典 ```bash # 定义字典 declare -A dict # 新增或修改键 k1 的值 dict['k1']='v1' # 打印对应键的值 echo $['k1'] # 打印字典所有元素,有两种方式 echo ${dict[@]} echo ${dict[*]} # 打印字典所有键,有两种方式 echo ${!dict[@]} echo ${!dict[*]} # 打印字典的元素个数,有两种方式 echo ${#dict[@]} echo ${#dict[*]} # 移除键 k1 unset dict['k1'] ``` ## 终端环境变量 PS1 参数 - \d 日期,格式为weekday month date,例如:"Mon Aug 1" - \H 完整的主机名称 - \h 仅取主机的第一个名字 - \t 显示时间为24小时格式,如 HH:MM:SS - \T 显示时间为12小时格式 - \A 显示时间为24小时格式 HH:MM - \u 当前用户的账号名称 - \v BASH的版本信息 - \w 完整的工作目录名称 - \W 利用basename取得工作目录名称,所以只会列出最后一个目录 - \# 下达的第几个命令 - \$ 提示字符,root 下提示符是 #,普通用户是 $ - \\[\e[i;j;km\\] \\[\e[0m\\] 建议PS1使用这种颜色控制字符 ## 终端颜色 \033[F;Bm 控制编码 - F30 B40 黑色 - F31 B41 红色 - F32 B42 绿色 - F33 B43 黄色 - F34 B44 蓝色 - F35 B45 紫红色 - F36 B46 青蓝色 - F37 B47 白色 ## 终端光标位置 - \033[K 清除从光标到行尾的内容 - \033[s 保存光标位置 - \033[u 恢复光标位置 - \033[0m 关闭所有属性 - \033[1m 设置高亮度 - \033[4m 下划线 - \033[5m 闪烁 - \033[7m 反显 - \033[8m 消隐 - \033[nA 光标上移n行 - \033[nB 光标下移n行 - \033[nC 光标右移n行 - \033[nD 光标左移n行 - \033[2J 清屏 - \033[?25l 隐藏光标 - \033[?25h 显示光标 - \033[y;xH 设置光标位置 ## 解析迅雷链接 - echo 迅雷专用地址(去掉头 thunder://)|base64 -d - 去掉头部 AA 和尾部 ZZ ## expect 自动输入密码 ```bash expect<> /etc/sudoers # 或 echo "cephdeploy ALL = (root) NOPASSWD:ALL" > /etc/sudoers.d/username chmod 0400 /etc/sudoers.d/username ``` ## 用户登陆操作记录 - 创建日志共存目录 ```bash mkdir /var/log/user_history -p chmod 0777 /var/log/user_history -R ``` - 配置 history 历史文件 /etc/profile.d/history.sh ```bash #!/bin/bash export HISTSIZE=10000 export HISTTIMEFORMAT="[%F %T] " LOG_DIR=/var/log/user_history mkdir -p $LOG_DIR/$USER if [ 0 -eq $? ]; then SRC_IP="$(who -u am i 2>/dev/null | awk '{print $NF}' | sed 's/[()]//g')" [ -z "$SRC_IP" ] && SRC_IP='127.0.0.1' hist_file="$USER/${SRC_IP}_$(date +%Y%m%d-%H%M%S)" export HISTFILE="$LOG_DIR/$hist_file" else echo "本次登陆没有监管,10秒后自动断开!" export TMOUT=10 fi ```