Shell脚本常见应用
# Shell命令延时执行
- 通过sleep命令阻塞Shell进程即可。
sleep [秒]
- 延迟n秒后再继续执行,默认单位为秒。- 例如:
sleep 5
# 长命令续行
在命令行过长影响阅读时,我们可以使用续行符
/
表示这一行还没有结束,声明下一行还是属于同一条命令行。echo -e \ "ddddddddddddddddd"
1
2
# 取随机数
- 使用
$((RANDOM % [指定范围数] + 1))
- 余数不会超过或等于[指定范围数],可以加1防止取到0。
# 脚本判断是否正确输入参数
if [ ! $# -eq 2 ];then echo “请输入2个参数” fi
1
2
3
# 判断当前用户
[ $USER == "root" ] && echo "当前用户为root"
1
# 判断变量是否为数字或英文
# 变量必须开头到结尾全是整数 [[ $Num =~ ^[0-9]+$ ]];echo $? # 变量必须开头到结尾全是英文字母 [[ $Num =~ ^[a-Z]+$ ]];echo $?
1
2
3
4
5
# 标准输入长文本到脚本
可以使用
<<
标准输入重定向符号。另外需要注意shell中使用<<重定向符需要加上"-"符号。cat <<-EOF ... ... EOF
1
2
3
4
# 判断服务是否启动
read -p "Please input name of service:" service systemctl status $service &> /dev/null if [ $? -eq 0 ];then echo "$service正在运行" && exit 0 else echo "$service没有运行" && exit 1 fi
1
2
3
4
5
6
7
8我们也可以先判断服务是否启动,再判断服务端口是否存在,最后判断服务进程是否存在。
systemctl is-active sshd
- 通过命令执行字符串,判断是否启动netstat -an | grep ":22"
- 通过是否监听端口,判断是否启动ps -aux | grep sshd | egrep -v "grep|@"
- 通过是否有进程,判断是否启动
# 美观的显示操作结果
action "[文本内容]" /bin/[ true | false ]
- 输出有色彩且美观的操作结果。要先调用
/etc/init.d/functions
函数库才能使用action命令。#!/bin/bash . /etc/init.d/functions action "Web is OK." /bin/true action "Web is Fail." /bin/false # 会输出 Web is OK. [ OK ] Web is Fail. [FAILED]
1
2
3
4
5
6
7
8
# 在PS命令时排除自身
ps aux | grep [n]ginx
ps aux|grep nginx|grep -v grep|grep -v $$
# 防止脚本重复运行
通过加锁,判断锁文件来防止脚本重复运行,同时还可以配合trap和exit在正常退出脚本时清理锁文件。
例如:
# 脚本开始时判断是否有锁文件,如果有则表示已经有运行的脚本了 if [ -e /tmp/test.pid ];then echo "process is already runing." exit 1 fi # 如果没有则创建锁文件,再运行脚本 echo $$ > /tmp/test.pid # 设置收到exit信号时要做的操作 trap "rm -f /tmp/test.pid; echo Bye~" EXIT
1
2
3
4
5
6
7
8
9
10
11
# 跳板机设计思路
- 执行脚本后,会显示一个能管理的主机菜单,供使用者选择来进行连接。而如果要使用多级菜单,则可以使用多个函数,每个函数都执行清屏,需要时直接调用菜单即可。
- 需要死循环,不让用户退出。
- 控制Ctrl+C信号,禁止使用Ctrl+C退出,防止用户退出跳板机进程。
trap "" HUP INT TSTP
- 设为一连接Shell就执行。执行命令添加到/etc/bashrc或/etc/profile文件里即可。
- 可以加个后门密码用于退出,以防特殊情况无法退出 (不写在菜单上)。
- 如果要写的主机过多,可以将主机和菜单的IP设为变量,然后借助sed或者awk工具将变量名与命令这条字符串使用序列生成,然后在开头一个一个写IP就行了。
# 文本创建用户思路
- 判断是否是root用户执行。
- 文本中写入 [用户名]:[密码]。
- 使用for循环将其一行一行读入。
- 在循环体中使用awk取出用户名和密码并赋值给变量。
- 然后判断用户名是否存在。
- 然后使用useradd和passwd命令进行创建,同时输出结果。
# 自动创建用户思路
- 判断是否是root用户执行。
- 提示输入用户名前缀、创建个数、用户名后缀。
- 判断输入的内容是否符合要求。
- 符合要求则以随机密码开始创建。
- 第一种方式(数字与小写字母组合):
echo $((RANDOM)) | md5sum | cut -c 2-10
- 第二种方式(数字与大写字母或_组合):
cat /dev/urandom | tr -dc '_A-Za-z0-9'|head -c10
- 第三种方式:expect软件包的mkpasswd。
- 第一种方式(数字与小写字母组合):
- 将用户名和随机密码保存到某文件中。
# 统计Nginx访问日志
awk方式统计
awk '{ips[$1]+=$10 iptimes[$1]++} END{for (i in ips) print i"的总流量是"ips[i]/1024"KB 请求总 次数是"iptimes[i] }' access.log
shell数组方式统计
declare -A ip_bytes declare -A ip_times while read line;do ip=$(echo $line|awk '{print $1}') ip_byt=$(echo $line|awk '{print $10}') let ip_times[$ip]++ ip_bytes[$ip]=$((${ip_bytes[$ip]} + ${ip_byt})) done <access.log for i in ${!ip_times[@]};do echo "${i}的访问次数是${ip_times[$i]} 访问大小是$((${ip_bytes[$i]}))Bytes" done
1
2
3
4
5
6
7
8
9
10
11
# 按频率排序
- 按单词频率排序
- sort排序方法:
cat test.txt | sed 's#[,.]##g'| xargs -n1 | sort | uniq -c | sort -nr
- awk排序方法:
cat test.txt | sed 's#[,.]##g'| xargs -n1 |awk '{word[$1]++} END{for(i in word)print word[i],i}' | sort -nr
- sort排序方法:
- 按字母频率排序
- sort排序方法:
cat test.txt | sed 's#[,.]##g'| grep -o [a-zA-Z] | sort | uniq -c | sort -nr
- awk排序方法:
cat test.txt | sed 's#[,.]##g' | grep -o "[a-zA-Z]" | awk '{word[$1]++} END{for(i in word)print word[i],i}' | sort -nr
- sort排序方法:
# 发送邮件方法
通过postfix邮箱服务即可。
发送方法
在邮箱网站中
- 关闭 POP3/SMTP 服务
- 勾选 IMAP/SMTP 服务
- 记录企业邮箱的SMTP服务器地址
- 开启生成客户端授权密码并进行记录
编写 /etc/mail.rc 文件
set from=邮箱账号 smtp=smtp地址 set smtp-auth-user=邮箱账号 smtp-auth-password=邮箱授权密码 smtp-auth=login
1
2重启邮件服务
systemctl restart postfix
发送邮件
echo "内容" | mail -s "标题" [目标邮箱]
mail -s "[标题]" [目标邮箱] < 重定向或者管道符输入内容
# MD5处理命令
- md5sum命令可以生成或校验md5指纹文件,验证数据完整性等。
md5sum [参数] [目标文件]
md5sum [文件]
- 生成文件的校验信息md5sum -c [文件]
- 验证文本内容中的校验信息
# 数据备份
例如有一个备份web服务器文件到备份服务器的需求,首先要确认好备份周期、需要备份的文件、web服务器和备份服务器的备份文件保留时长,例如:每天备份一次,web服务器保留7天内数据,备份服务器保留每周一的所有数据副本,其它要保留6个月的数据副本。
然后根据需求先在命令行测试确认要执行的操作:
# 0) 环境检查 # 各服务器IP、主机名等配置好 # 备份服务器的Rsync守护进程搭建配置好,可以正常收发数据 # 备份服务器邮件服务配置好(postfix服务),可以正常收发邮件 # 其他服务器的Rsync密码文件配置好 # 1) 所有服务器的备份目录为/backup/[主机地址],创建传输后用户存放的目录 mkdir -p /backup/[主机地址] # 2) 要备份的配置文件进行打包压缩备份 # 如果因为绝对路径会报错可以cd到根目录,再以相对路径进行压缩 # tar压缩时加上h参数可压缩软链接的源文件 cd / tar -czhf /backup/[主机地址]/config_$FILE_TAIL ./var/spool/cron/root ./etc/rc.local ./server/scripts ./etc/sysconfig/iptables # 压缩之后进行解压文件进行检查 ll /backup/[主机地址]/ # 3) web服务器将网站文件进行打包压缩备份 # 两个较大的目录可以分开进行压缩,防止解压时过于耗时 cd / tar -czhf /backup/[主机地址]/www_$FILE_TAIL ./var/html/www tar -czhf /backup/[主机地址]/www_log_$FILE_TAIL ./app/logs # 4) Web服务器仅保留打包后的7天的备份数据 # 防止备份数据太多磁盘占满,通过搜索备份目录修改时间(创建时间)大于七天的文件并进行删除 find /backup/ -type f -mtime +7 -delete # 5)备份服务器上,保留每周一的所有数据副本,其它要保留6个月的数据副本 # 在数据名称信息上加上周的信息,然后find搜索时通过!排除周一 date "+%F_week%w" --- %A 或 %w find /backup/ -type f -mtime +180 ! -name "*week1.tar.gz" -delete # 6)web服务器生成校验信息,然后发送备份文件到备份服务器 find /backup/ -type f -mtime -0.5 ! -name "finger*" | xargs md5sum > $BACKUP_DIR/$IP_ADDR/finger.txt rsync -a /backup/ rsync_backup@10.0.0.41::backup/ --password-file=/etc/rsync.passwd # 7)备份服务器校验传输前后数据,把备份的成功或失败结果信息发给系统管理员邮箱中 find /backup/ -type f -mtime -0.5 -name "finger*" | xargs md5sum -c | mail -s "`date '+%F'` - 数据备份情况" cecilies@qq.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37再将操作编写为脚本:
客户端
#!/bin/bash #define variables Backup_dir='/backup' IP_addr=$(hostname -i | awk '{print $NF}') Tar_tail=$(date '+%F-week%w' -d "-1day").tar.gz #make directory mkdir -p $Backup_dir/$IP_addr \ #tar data cd / tar -czhf $Backup_dir/$IP_addr/config_$Tar_tail ./var/spool/cron/root ./etc/rc.local ./server/scripts ./ etc/sysconfig/iptables \ #delete 7 day ago find /backup/ -type f -mtime +7 -delete #generate the finger file find /backup/ -type f -mtime -0.5 ! -name "finger*" | xargs md5sum > $Backup_dir/$IP_addr/finger.txt \ #backup push data rsync -a /backup/ rsync_backup@10.0.0.41::backup/ --password-file=/etc/rsync.passwd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23服务端
#!/bin/bash #delete 6 month ago data and leave monday data find /backup/ -type f -mtime +180 ! -name "*week1.tar.gz" -delete #check the md5 of data and send to e-mail find /backup/ -type f -mtime -0.5 -name "finger*" | xargs md5sum -c | mail -s "`date '+%F'` - 数据备份情况" cecilies@qq.com
1
2
3
4
5
6
7为了提高通用性,使用变量代替一些可能会变动的东西,能够从系统中取出的信息就从系统中提取。
添加定时任务:
客户端
# backup data 0 0 * * * /usr/bin/sh /scripts/backup.sh &> /dev/null
1
2服务端
- 时间要比客户端晚些,保证运维人员上班时能收到邮件即可。
# backup check 0 5 * * * /usr/bin/sh /scripts/check_backup.sh &> /dev/null
1
2
全部做完后全部检查一遍,思考还有没有完善的余地即可。