本文重点解决两个问题:
- 获取SSH远程执行命令的返回状态
- expect执行SSH时进程中不显示密码明文
先上Shell 代码:
export IP CMD SSH_PWD
expect << 'END'
# 关闭输出
log_user 0
set timeout 30
# 从系统变量获取数据
set ip "$env(IP)"
set cmd "$env(CMD)"
set pwd "$env(SSH_PWD)"
spawn ssh root@$ip "$cmd"
expect {
"(yes/no)?" {send "yes\r";exp_continue}
# 忽略大小写
-nocase "password:" {send "$pwd\r";exp_continue}
# 登录成功,打开输出
-nocase "authentication successful" {log_user 1;exp_continue}
# 登录失败
-nocase "authentication fail" {exit 222}
-nocase "permission denied" {exit 222}
eof
}
puts $expect_out(buffer)
lassign [wait] pid spawnid os_error_flag value
# 系统错误
if {$os_error_flag == -1} {
puts "os errno: $value"
} else {
# 返回 CMD 执行结果
exit $value
}
END
exitCode=$?
if [ $exitCode -eq 222 ]; then
echo 'log error'
elif [ $exitCode -ne 0 ]; then
echo 'cmd error'
fi
获取执行结果的关键在于【wait】方法的使用:
wait [args]
delays until a spawned process (or the current process if none is named) terminates.
wait normally returns a list of four integers. The first integer is the pid of the process that was waited upon. The second integer is the corresponding spawn id. The third integer is -1 if an operating system error occurred, or 0 otherwise. If the third integer was 0, the fourth integer is the status returned by the spawned process. If the third integer was -1, the fourth integer is the value of errno set by the operating system. The global variable errorCode is also set.
【wait】:延迟直到一个spawn进程结束。返回4个数值:
- expect 进程 pid
- spawn 线程 id
- OS状态值(-1:系统错误,0:正常)
- spawn命令返回值(OS值为 -1时返回OS错误代码,为 0时返回CMD退出值)
参考:expect man、How to get the exit code of spawned process in expect shell script?
开头的两个问题都得到了解决:
- 使用 wait 获取SSH 远程执行命令的返回状态,登录失败也可以通过指定状态码(222)标识;
- 使用 env 读取外部变量到expect 变量中,从而 PS 不会显示 密码明文。