Linux树莓派expect脚本sudo pkill mysql命令执行异常排查
问题原因
- 核心错误:
expect '$*' {send 'sudo pkill mysql'}语句的send内容末尾缺少回车符\r。对比你后面能正常执行的mkdir命令,send内容末尾带了\r,这是expect里模拟手动敲完命令按回车的必要标识,没加的话远端shell只会收到命令字符串,不会触发执行。你在终端看到命令被打印出来只是输入回显,不是命令执行的状态。 - 语法不规范:expect基于Tcl语言实现,单引号没有特殊语义,会被当做普通字符解析,你用单引号包裹匹配规则、发送内容,很容易出现匹配失效、内容发送异常的问题。
- 匹配逻辑不稳定:你写的
'$*'/"$*"不是匹配shell提示符的标准写法,不同shell、不同操作场景下的提示符可能带当前路径、主机名、特殊颜色字符,很容易出现匹配提前、匹配超时的问题。 - 缺失交互处理:如果远端服务器的sudo规则要求输入密码,你发送sudo命令后没有做密码输入的匹配处理,就算加了回车也会卡在密码输入环节,导致命令执行失败。
修复方案
直接用调整后的完整脚本,替换你原来的内容即可:
#!/usr/bin/expect # 替换为你实际的连接参数 set port 22 set username 你的登录用户名 set ip 远端服务器IP set login_pass 你的登录密码 set sudo_pass 你的sudo密码 set timeout 10 spawn ssh -p$port $username@$ip expect { "*yes/no" { send "yes\r" exp_continue } "*password:" { send "$login_pass\r" } } # 用正则匹配shell提示符,兼容普通用户($)和root用户(#)场景 expect -re {\$|# $} # 执行pkill杀mysql进程,末尾必须加\r触发执行 send "sudo pkill mysql\r" # 自动处理sudo密码提示 expect { "*password for*" { send "$sudo_pass\r" exp_continue } -re {\$|# $} } # 执行创建test目录操作 send "sudo mkdir test\r" expect { "*password for*" { send "$sudo_pass\r" exp_continue } -re {\$|# $} } # 不需要保持交互的话,把下面interact替换为下面两行,执行完自动退出 # send "exit\r" # expect eof interact
额外注意事项
- 所有通过send发送的待执行命令,末尾必须加
\r,否则不会被远端执行。 - 如果你的账号已经配置了sudo免密,脚本里的sudo密码处理逻辑不会影响正常执行,不需要删除。
- 要验证pkill是否生效,可以在pkill命令执行逻辑后加一行
send "pgrep mysql\r",匹配返回结果,如果没有输出进程号就说明进程已经被成功终止。 - 不要在expect脚本里随意用单引号包裹匹配规则和发送内容,统一用双引号即可,避免Tcl解析异常。
内容的提问来源于stack exchange,提问作者chen wen
相关产品推荐
相关产品推荐

