使用Expect自动化SSH登录时传递带颜色的printf命令报错排查
使用Expect自动化SSH登录时传递带颜色的printf命令报错排查
我来帮你排查这个问题,你遇到的报错核心是SSH远程命令的传递方式不对,加上Expect脚本里的引号嵌套和转义没处理好,咱们一步步来解决:
问题根源分析
你当前的命令里有两个关键错误:
- SSH远程命令的格式错误:你用
{printf [\33[01;32m...]; bash}作为SSH的参数,bash会把{printf当成一个完整的命令名(因为大括号和printf没有空格),这就是为什么会报bash: {printf: command not found——它根本没识别出这是一个命令组。 - Expect脚本的转义和引号嵌套错误:你在单引号包裹的Expect脚本里,使用了
\33转义序列,同时错误地用[]包裹了printf的内容,而且\n在Expect的单引号环境里不会被解析为换行符,反而会被当成普通字符传递给远程bash。
修正后的解决方案
我们需要调整远程命令的包裹方式、修正转义序列,同时处理好Expect里的引号嵌套:
完整修正后的命令
expect -c 'spawn ssh -t MYHOST@MYSERVER "printf '\''\033[01;32m A MESSAGE TO BE SHOWN \033[01;37m\n'\''; bash"; expect "Password:"; send "MY PASSWORD\r"; interact'
关键修正点拆解
- SSH远程命令的正确传递:把原来的命令组改成用双引号包裹的完整命令
"printf ...; bash",这样SSH会把整个字符串作为一个参数传递给远程bash,确保它被解析为一个命令组执行。 - 转义序列的标准化:把
\33改成标准的八进制转义\033(也可以用十六进制\x1b),保证所有bash环境都能识别颜色控制码。 - Expect的引号嵌套处理:在Expect的单引号脚本里,要输出单引号需要用
'\''来转义(逻辑是:结束当前单引号环境 → 输出一个单引号 → 重新开启单引号环境),这样远程的printf命令能正确拿到带单引号的格式字符串。 - 密码提交的回车符:在
send "MY PASSWORD"后面加\r,模拟回车键提交密码,否则远程SSH可能不会处理你发送的密码内容。 - 移除多余的[]:printf的格式字符串里不需要用
[]包裹内容,直接输出颜色转义序列+消息即可。
验证效果
执行修正后的命令后,Expect会自动启动SSH连接,输入密码后登录到远程服务器,你会立刻看到绿色的提示消息,然后进入bash交互环境,和手动登录体验一致。
备注:内容来源于stack exchange,提问作者Ilgar
相关产品推荐
相关产品推荐

