Linux 脚本自动交互
今天学习 Linux 脚本自动交互。需要完成 IP 归属地数据文件的维护,而 gmaker 工具里面有交互命令,现在想用脚本替代手动输入。
在我们日常的 Linux 指令中,有很多命令提供交互式操作,例如 sudo、ssh、ftp 等,如何使用脚本完成自动交互呢?
1,使用重定向
重定向是将标准输入输出进行重定向操作,例如将标准输入输出重定向到文件。用重定向标准输入到文件的前提,是命令支持有参数指定输入方式,如 ftp 就有-i 参数来指定使用标准输入来输入密码。
shell 使用重定向标准输入的方法有:
command < file 将输入重定向到file
命令交互式重定向
command << delimiter
document
delimiter
shell 会将分界符 delimiter 之间的内容作为输入。
例如,我们来使用 ftp 实现自动登录并运行 ls 的脚本,其中用户名为 test,密码为 123456。
ftp -i -n 192.168.1.10 <<EOF
user test 123456
ls
EOF
2,使用管道
管道命令使用|这个符号,它会将前一个命令的输出作为下个命令的输入。它也需要命令支持。
例如,实现 sudo 自动输入密码的脚本:
echo '123456' | sudo -S cp file1 /backup/file1
其中,123456 是密码。
3,使用 expect 工具
expect 是用来做交互,基本任何交互的场合都能使用。在像 ssh 命令没有指定输入的参数,就很适合这种方式。
需要先安装 expect,安装命令如下:
yum install expect
例如:我们使用 ssh 远程登录某台服务器的脚本
#!/usr/bin/expect
set timeout 30
spawn ssh -l root 192.168.1.10
expect "password*"
send "123456\r"
interact
其中, 第一行是脚本执行引擎,第二行设置超时 30 秒,第三行执行 ssh 登录,spawn 是 expect 内部命令,意思是启动一个新的交互进程后面跟命令或者指定程序,第四行匹配 password 关键字,如果匹配到往下继续执行,只有 spawn 执行的命令结果会被 expect 捕捉到。如果捕获到立即返回,否则等待超时后返回,超时时间在第二行设置了。expect "#*" 或"]#"代表匹配任何内容。第五行发送密码,相当于手动输入密码。send 是 expect 内部命令,会将密码输入到 spawn 启动的进程中,第六行进入交互模式,留在远程控制台,如果没有这句就返回本地控制台。
附上 expect 常用命令
命令 | 说明 |
---|---|
spawn | 启动新的交互进程后面跟命令或者指定程序 |
expect | 从进程接收消息,如果匹配成功,就执行 expect 后的动作 |
send | 向进程发送字符串 |
send exp_send | 用于发送指定的字符串信息 |
exp_continue | 在 expect 中多次匹配就需要用到 |
send_user | 用来打印输出 |
interact | 允许用户交互 |
exit | 退出 expect 脚本 |
eof | expect 执行结束,退出 |
set | 定义变量 |
puts | 输出变量 |
set timeout | 设置超时时间 |
下面,我们来实现我们的脚本,用来自动更新我们的 IP 源。
#!/bin/bash
change_num=`wc -l ipchange.txt|awk '{print $1}'`
if [ $change_num == 0 ]
then
echo "file is empty"
exit
fi
expect <<EOF
set timeout 10
spawn gmaker edit --src=ip.merge.txt
expect "editor*" {send "put_file ipchange.txt\n"}
expect "editor*" {send "save\n"}
expect "editor*" {send "quit\n"}
expect "#*" {send "exit\n"} expect eof
EOF
sleep 1
cat /dev/null>ipchange.txt
gmaker gen --src=ip.merge.txt --dst=ip2region.xdb
经实测,可用。