如何在timeout的bash -c命令中正确使用退出状态?
解决bash -c中获取SSH退出状态的问题
这个问题其实是两个小细节没处理到位,咱们一步步拆解修复:
问题根源
- 命令分隔错误:你把
ssh命令和response_code=$?写在同一行却没加分隔符(;),导致shell把response_code=$?当成了ssh要在远程执行的命令参数,根本没在本地子shell里执行变量赋值操作,自然response_code是空的。 - 变量提前解析:用双引号包裹
bash -c的内容时,父shell会提前解析$?,把它替换成父shell中前一个命令的退出码,而不是你期望的ssh命令的退出码。
修正后的脚本
把这两个问题修复后,脚本就能正常工作了:
# poll for SSH access timeout_threshold=60 INSTANCE_IP=199.199.199.199 timeout $timeout_threshold bash -c 'while true; do ssh -oConnectTimeout=2 -oStrictHostKeyChecking=no -q '"${INSTANCE_IP}"' exit response_code=$? if (( response_code == 0 )); then echo "Successfully connected to instance via SSH." exit else echo "Failed to connect by ssh. Trying again in 5 seconds..." sleep 5 fi done'
关键修改点
- 把
bash -c的内容改用单引号包裹,这样父shell不会解析里面的$?和$response_code,让这些变量在子shell里正常生效。 - 单独拆分
ssh命令和response_code=$?为两行(或者用;分隔在同一行),确保response_code能正确获取ssh命令的退出码。 - 因为
INSTANCE_IP是父shell里的变量,所以用'"${INSTANCE_IP}"'的方式在单引号字符串里插入父shell的变量(单引号里嵌套双引号来解析父shell变量)。
另外,也可以选择用转义的方式处理$?(把双引号里的$?改成\$?),同时给ssh命令和赋值加分隔符,但用单引号的方式更清晰,不容易出错。
内容的提问来源于stack exchange,提问作者Kristianasp
相关产品推荐
相关产品推荐

