236 lines
5.5 KiB
Markdown
236 lines
5.5 KiB
Markdown
---
|
||
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<<END
|
||
spawn ssh $DEST_HOST "REMOTE_COMMAND"
|
||
expect {
|
||
"*yes/no*" { send "yes\r"; exp_continue }
|
||
"*assword*" { send "password\r" }
|
||
}
|
||
expect eof
|
||
END
|
||
```
|
||
|
||
## 普通用户(username)免密 sudo
|
||
```bash
|
||
echo "username ALL = (root) NOPASSWD:ALL" >> /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
|
||
```
|
||
|