sshpass登录后执行多命令异常:ServletController命令未找到求助
看起来你遇到的核心问题是切换到servlet用户后,环境变量没有正确加载,导致系统找不到ServletController命令——毕竟whoami能正常返回servlet,说明用户切换是成功的,只是命令的路径没在当前PATH里。
下面给你几个可行的解决办法,按优先级排序:
1. 直接用ServletController的绝对路径执行(最稳妥)
先手动登录到目标主机,切换到servlet用户,执行which ServletController或者whereis ServletController,拿到这个命令的绝对路径(比如/opt/servlet/bin/ServletController),然后把命令里的ServletController换成绝对路径:
sshpass -p "${Passw}" ssh -tt -o StrictHostKeyChecking=no root@"${Hostname}" su - servlet -c 'whoami && /opt/servlet/bin/ServletController -log -b prod_"${Cust_name}" status -type web |grep running'
这种方式完全不受环境变量影响,是最可靠的。
2. 强制加载servlet用户的shell配置文件
如果不想用绝对路径,可以在执行命令前先加载servlet用户的登录配置文件(比如.bash_profile,如果是bash的话),确保环境变量(尤其是PATH)被正确加载:
sshpass -p "${Passw}" ssh -tt -o StrictHostKeyChecking=no root@"${Hostname}" su - servlet -c 'source ~/.bash_profile && whoami && ServletController -log -b prod_"${Cust_name}" status -type web |grep running'
如果你的servlet用户用的是.bashrc而不是.bash_profile,就把source ~/.bash_profile换成source ~/.bashrc。
3. 用登录shell执行命令
有时候su -虽然理论上会加载登录环境,但在-c参数下可能有异常,这时候可以强制用bash -l(登录shell)来执行命令:
sshpass -p "${Passw}" ssh -tt -o StrictHostKeyChecking=no root@"${Hostname}" su - servlet -c 'bash -l -c "whoami && ServletController -log -b prod_${Cust_name} status -type web |grep running"'
这里把内层命令用双引号包裹,确保${Cust_name}能被远程shell正确解析(如果这个变量是在远程主机上的话);如果Cust_name是本地脚本的变量,你需要调整引号,让本地先替换变量:
# 本地替换${Cust_name}的写法 sshpass -p "${Passw}" ssh -tt -o StrictHostKeyChecking=no root@"${Hostname}" su - servlet -c 'whoami && ServletController -log -b prod_'"${Cust_name}"' status -type web |grep running'
4. 先排查环境变量问题(用于调试)
如果还是不确定问题在哪,可以先在命令里加echo $PATH和which ServletController来排查:
sshpass -p "${Passw}" ssh -tt -o StrictHostKeyChecking=no root@"${Hostname}" su - servlet -c 'whoami && echo $PATH && which ServletController'
这样你就能看到当前的PATH里有没有包含ServletController所在的目录,以及这个命令是否真的存在于servlet用户的环境中。
内容的提问来源于stack exchange,提问作者SachinKumar

