1 信号捕捉 trap
trap 命令可以捕捉信号,修改信号原来的功能,实现自定义功能
常用参数:
-l | 让shell打印一个命令名称和其相对应的编号的列表 |
---|---|
-p | 打印与每一个信号有关联的命令的列表 |
缺省 | 每个接收到的sigspec信号都将会被重置为它们进入shell时的值 |
-f | 阻止中断信号 |
#查看信号列表
trap -l
2) SIGINT :是Ctrl+C的按键信号
### 信号的值可以写成三种格式:
## 2(数字法表示) | SIGINT(全称) | INT(简称)
#进程收到系统发出的指定信号后,将执行自定义指令,而不会执行原操作
trap '触发指令' 信号
#忽略信号的操作
trap '' 信号
#恢复原信号的操作
trap '-' 信号
#列出自定义信号操作
trap -p
#当前脚本退出时,执行finish函数(重要)
trap finish EXIT
范例:
#!/bin/bash
#自定义指令信号
trap "echo 'Please Ctrl+C or Ctlr+\'" SIGINT SIGQUIT
trap -p
for ((i=0;i<=10;i++))
do
sleep 1
echo $i
done
#忽略原信号操作
trap '' SIGINT
trap -p
for ((i=11;i<=20;i++))
do
sleep 1
echo $i
done
#恢复原信号操作
trap '-' SIGINT
trap -p
for ((i=21;i<=30;i++))
do
sleep 1
echo $i
done
范例:当脚本正常或者异常退出时,也会执行 finish 函数
~ vim trap-exit.sh
#!/bin/bash
function finish()
{
echo finish is at `date +%F_%T` | tee -a /root/finish.log
}
#捕获退出就执行finish函数
trap finish exit
while true ;do
echo running
sleep 1
done
2 创建临时文件 mktemp
mktemp 命令用于创建并显示临时文件,可以避免冲突
格式:
mktemp [OPTIONS]... [TEMPLATE]
说明:TEMPLATE: filenameXXX,X至少要出现三个,三个以上随机字符
常用选项:
-d #创建临时目录
-p DIR或者--tmpdir=DIR #指明临时文件所存放目录位置
范例:
~ mktemp
/tmp/tmp.lOLpKJ8nrB
~ mktemp /tmp/testXXX
~ tmpdir=`mktemp -d /tmp/testdirXXX`
~ mktemp --tmpdir=tmpdir testXXXXXX
~ mktemp -d tmpdirXXX -p /usr/local/src
范例:实现文件垃圾箱功能
#方法1:脚本实现
~ vim /data/shell/mktemp-rm.sh
#!/bin/bash
DIR=$(mktemp -d /tmp/trash-$(date +%F_%T)XXX)
mv $* $DIR
echo $* is move to $DIR
~ chmod +x /data/shell/mktemp-rm.sh
~ alias rm=/data/shell/mktemp-rm.sh
~ rm finish.log
finish.log is move to /tmp/trash-2022-06-14_17:35:45jX0
#方法2:函数实现
~ function rm() { local trash=$(mktemp -d /tmp/trash-$(date +%F_%T)XXX);mv $* $trash; }
3 安装复制文件 install
install 功能相当于 cp,chmod,chown,chgrp,mkdir等相关工具的集合
install 命令格式:
Usage: install [OPTION]... [-T] SOURCE DEST
or: install [OPTION]... SOURCE... DIRECTORY
or: install [OPTION]... -t DIRECTORY SOURCE...
or: install [OPTION]... -d DIRECTORY...
选项:
-m MODE 权限,默认755
-o OWNER 用户
-g GROUP 用户组
-d DIRNAME 目录
范例:
~ install -m 700 -o wang -g admins srcfile dstfile
#-d:相当于mkdir -p
~ install -m 700 -d /testdir/installdir
~ install -m 600 -o wang -g bin reset.sh /data/set.sh
~ ls -l /data/set.sh
~ install -m 700 -o kubesphere -g daemon -d /data/testdir
~ ls -ld /data/testdir
4 交互式转换批处理工具 expect
expect是由Don Libes基于TCL ( Tool Command Language ) 语言开发的,主要应用于自动化交互式操作的场景,借助 expect 处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务懦执行相同操作的环境中,可以大大提高系统管理人员的工作效率。
范例:安装expect 及mkpasswd工具
➜ ~ yum install -y expect
➜ ~ rpm -ql expect | head
/usr/bin/autoexpect
/usr/bin/dislocate
/usr/bin/expect
/usr/bin/ftp-rfc
/usr/bin/kibitz
/usr/bin/lpunlock
/usr/bin/mkpasswd
/usr/bin/passmass
/usr/bin/rftp
/usr/bin/rlogin-cwd
➜ ~ mkpasswd
gBOlu87i<
➜ ~ mkpasswd -l 15 -d 3 -C 5
@k5FpJ9XRsPaj1i
expect 语法:
expect [选项] [ -c cmds ] [[ -[flb] ] cmdfile ] [ args ]
常见选项:
-c:从命令行执行expect脚本,默认expect是交互地执行的
-d:可以调试信息
示例:
expect -c 'expect "\n" { send "pressed enter\n" }'
expect -d ssh.exp
expect 中的相关命令
- spawn 启动新的进程
- expect 从进程接收字符串
- send 用于向进程发送字符串
- interact 允许用户交互(将权限交给用户)
- exp_continue 匹配多个字符串在执行动作后如此命令(在 expect 中多次匹配就需要用到)
- eof export 执行结束退出
- send_user 用来打印输出,相当于 shell 中的 echo
- exit 退出expect脚本
- set 定义变量
- puts 输出变量
- set timeout 设置超时时间
expect 最常用的语法:(TCL语言:模式-动作)
单一分支模式语法:
#直接执行expect则是交互式
~ expect
#一次性的。
expect1.1> expect "hi" {send "You said hi\n"}
hi
You said hi
expect1.2> expect "hi" {send "You said hi\n"}
123hihello
You said hi
匹配到 hi 后,会输出”You said hi”,并换行
多分支模式语法:
~ expect
expect1.1> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
hehe
Hehe yourself
expect1.2> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
bye
Good bye
expect1.3> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
hi
You said hi
匹配 hi,hello,bye 任意字符串时,执行相应输出。等同如下:
expect {
"hi" { send "You said hi\n" }
"hehe" { send "Hehe yourself\n" }
"bye" { send "Good bye\n" }
}
~ expect1.1> expect {
+> "hi" { send "You said hi\n" }
+> "hehe" { send "Hehe yourself\n" }
+> "bye" { send "Good bye\n" }
+> }
bye
Good bye
expect1.2>
范例1:非交互式复制文件
~ vim expect-scp
#!/usr/bin/expect
spawn scp /etc/redhat-release 10.0.0.170:/data
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
expect eof
范例2:自动登录
~ vim expect-ssh
#!/usr/bin/expect
spawn ssh 10.0.0.170
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
interact
范例3:expect 变量
~ vim expect-set-ssh
#!/usr/bin/expect
set ip 10.0.0.170
set user root
set password magedu
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
范例4:expect 位置参数
~ vim expect-arg
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
~ chmod +x expect-args
~ ./expect-args 10.0.0.170 root magedu
spawn ssh root@10.0.0.170
root@10.0.0.170's password:
Last login: Tue Jun 14 21:42:04 2022 from 10.0.0.160
[root@kubesphere-mysql57 ~]#logout
Connection to 10.0.0.170 closed.
范例5:expect 执行多条命令
~ vim expect-command
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd haha\n" }
expect "]#" { send "echo Admin@h3c | passwd --stdin haha\n"}
send "exit\n"
expect eof
~ ./expect-command 10.0.0.170 root magedu
范例6:shell 脚本调用 expect
~ vim shell-expect.sh
#!/bin/bash
#Shell ENV
ip=${1}
user=${2}
password=${3}
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd hehe\n"}
expect "]#" { send "echo Admin@h3c | passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
~ chmod +x bash-expect.sh
~ ./bash-expect.sh 10.0.0.170 root magedu
范例7:shell脚本利用循环调用 expect 在 CentOS 和Ubuntu上批量创建用户
~ vim export-ubuntu-centos-useradd.sh
#!/bin/bash
#SHELL ENV
net=10.0.0
user=root
password=magedu
IPLIST="
51
52
53
"
for ID in $IPLIST ;do
ip=$net.$ID
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\m" }
}
expect "#" { send "useradd test\n" }
expect "#" { send "exit\n" }
expect eof
EOF
done
范例:修改配置文件 SELinux
~ vim expect-selinux.sh
#!/bin/bash
#SHELL ENV
net=10.0.0
user=root
password=magedu
IPLIST="
51
52
53
"
for ID in $IPLIST ;do
ip=$net.$ID
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\m" }
}
expect "#" { send "sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config\n" }
expect "#" { send "setenforce 0\n" }
expect "#" { send "exit\n" }
expect eof
EOF
done
范例:在指定主机执行批量操作
~ vim expect-scp.sh
#!/bin/bash
net=10.0.0
user=root
password=magedu
for i in {51..53} ;do
ip=$net.$i
expect <<EOF
set timeout 20
spawn scp /etc/selinux/config $user@$ip:/data
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "root" { send "useradd kubesphere\n" }
expect "root" { send "echo Admin@h3c | passwd --stdin kubesphere\n" }
expect "root" { send "exit\n" }
expect eof
EOF
done
~ chmod +x expect-scp.sh
~ ./expect-scp.sh