当前位置: 首页 > article >正文

shell脚本实现自动化交互功能

当执行某些命令时,需要你输入内容才可进入下一步,类似这样的场景如果用脚本代码实现,怎么实现呢?下面我们以连接远程服务器,输入密码为例介绍;

sshpass

sshpass -p 123 ssh user@10.xx.xx.xx > /dev/null << EOF
cd /home/user
mkdir abc
EOF

sshpass -p 指定服务器密码;
以上代码实现了连接到远程服务器,并执行对应的操作;但是这个代码运行,会提示“Pseudo-terminal will not be allocated because stdin is not a terminal.”,为了避免这个打印,建议增加-t参数为 ssh 命令启动分配伪终端,再增加-t分配一个强制性的tty终端,加上-tt后,需要加上exit退出终端,优化后的代码如下:

sshpass -p 123 ssh -tt @10.xx.xx.xx > /dev/null << EOF
cd /home/user
mkdir abc
exit
EOF

但是我尝试运行了下,这种写法如果远程命令执行出错,又不会打印错误信息。需要通过echo $?获取执行成功或失败的状态。

echo

echo 123|ssh -tt user@10.xx.xx.xx
echo 123|sudo xxx

以上代码并不能实现密码的输入,因为ssh 和 sudo 并不从管道接收密码,而是直接提示用户输入。
但是echo能用于其它场景,比如echo p|fdisk /dev/sdb 可以支持fdisk命令中的输入;echo Y|apt install xxx 可以支持安装过程中直接输入yes;

# 这种方式可以实现输入密码的功能,-S参数stdin,用于从标准输入读取密码;
echo 123|sudo -S command

expect

好的,那我们进入本篇的核心,就是为了介绍这个expect命令,它可以实现shell不能实现的交互操作,并且可以根据匹配目标内容输入。

方式一

example.exp 文件内容:

#!/usr/bin/expect -f
set ip "[lindex $argv 0 ]"
set content "随便写一段话"
set timeout -1

spawn smbclient //$ip/nas
expect {
		"nothing" {send "pp"}
		"Password" {send "123456\n";exp_continue}
		"smb" { send "cd 研发部/mail\n" }		
}
expect "mail" {send_user "\n$content\n"}
send_user "============\n"
# send "exit\n"
# expect eof
interact
  • 执行命令 ./example.exp 10.5.23.6 ;
  • set {变量名} {变量值} 在expect脚本中定义变量,[lindex $argv 0 ]是入参的第一个参数值;
  • set timeout -1 代表expect匹配时永不超时,这里不设置默认10s;
  • spawn 用于启动一个进程;
  • expect语句有单分支和多分支两种,如果期待的内容必须出现那就走单分支,如果期待的内容可能出现,那就多分支;
    • 对于单分支,直接“expect {预期值} {action}”即可,只要能匹配上,且action执行不出错,就会接着执行下一条,无需exp_continue;
    • 如果预期值可能会出现,也可能不会出现,就用多分支,它会从上往下匹配,如果未匹配上,就会自动往下执行;如果匹配上了但末尾不定义exp_continue,那就不会接着执行;如果想接着执行,就要定义exp_continue;
  • send 是发送执行命令,注意末尾一定要加\n或\r;
  • send_user 相当于shell中 的echo,用于打印内容;
  • interact 保持远程交互;
  • expect eof 交互结束,退回原用户,但还是需要执行退出命令才会退出;

方式二

有些场景,不仅仅需要执行expect交互,前后可能还要执行其它的shell代码,那就需要这样实现。

echo "expect前的shell代码执行"

/usr/bin/expect << EOF
	set ip "[lindex $argv 0 ]"
	set content "随便写一段话"
	set timeout -1

	spawn smbclient //192.xx.xx.x/nas
	
	expect {
		"nothing" {send "pp"}
		"Password" {send "123456\n";exp_continue}
		"smb" { send "cd 研发部/mail\n" }		
}
	
	expect "mail" {send_user "\n$content\n"}
	send_user "============\n"

	send "exit\n"
	expect eof

EOF

echo "expect后的shell代码执行"
  • 执行命令 ./example.exp 10.5.23.6 ;
  • 以上代码存在2个问题点,我至今也不明白,欢迎评论区交流~
    • 这种实现$ip $content变量值都无法获取;
    • 如果末尾写的是 interact ,运行时也会退出远程机器;

http://www.kler.cn/a/411321.html

相关文章:

  • vue的理解
  • 为什么DDoS防御很贵?
  • 第八篇:CamX RawHdr Feature Enable
  • CentOS 7安装SSHFS 实现远程主机目录 挂载为本地目录
  • 利用开源图床的技巧与实践
  • 如何在 Eclipse 中调试ABAP程序
  • java大视频分片上传
  • 【Conda 】Conda 配置文件详解:优化你的包管理与环境设置
  • 【Nginx】核心概念与安装配置解释
  • Docker login 报证书存储错误的解决办法
  • (完整版Word原件)智慧产业园区能源管控系统解决方案,能源管理系统解决方案-能源数字化监控解决方案,工业能源管理系统解决方案,园区能源管理
  • 探索Python网页解析新纪元:requests-html库揭秘
  • [C++]深入剖析list类中迭代器的封装
  • HOW - React 状态模块化管理和按需加载(一) - react-redux
  • 【Python中while循环】
  • Spring Boot 整合 ELK 全面指南:实现日志采集、分析与可视化
  • java——利用 Tomcat 自定义的类加载器实现热加载
  • 最长回文子串&多/虚继承
  • 网络安全原理与技术思考题/简答题
  • 1126刷题
  • 堆的实现(完全注释版本)
  • pikachu文件上传漏洞通关详解
  • 利用 Vue 组合式 API 与 requestAnimationFrame 优化大量元素渲染
  • Paddle Inference部署推理(一)
  • QT-installEventFilter
  • GaussDB高智能--库内AI引擎:模型管理数据集管理