PHP通过SSH调用bash脚本时sudo命令无法执行的权限排查
这个问题我之前帮同事排查过,核心原因就是远程执行sudo的时候没法交互式输入密码,而且默认sudo配置要求验证身份,所以script2.sh里的systemctl命令才没跑起来。给你几个靠谱的解决办法,按安全优先级排序:
解决办法
1. 配置目标服务器的sudo免密(最推荐,安全可控)
这是最稳妥的方案,只给特定用户、特定命令开放免密sudo权限,避免过度授权带来的风险:
- 登录到目标服务器(10.10.10.10),用有sudo权限的账号执行
visudo(一定要用visudo编辑,它会自动检查语法,避免写错导致sudo失效) - 在文件末尾添加一行,替换成你的实际信息:
解释一下:user ALL=(ALL) NOPASSWD: /usr/bin/systemctl start serviceuser是你SSH登录目标服务器的用户名/usr/bin/systemctl start service是要执行的完整命令(可以用which systemctl查到systemctl的绝对路径)- 如果需要授权多个命令,用逗号分隔即可,比如:
/usr/bin/systemctl start service, /usr/bin/systemctl stop service
- 保存退出后,先在本地测试一下:执行
ssh user@10.10.10.10 sudo /usr/bin/systemctl start service,确认不需要输入密码就能执行成功
2. 给SSH命令分配伪终端(解决无终端导致的sudo失败)
有些情况下,sudo需要终端环境才能触发验证流程,而远程SSH默认是非交互式无终端的,这时候可以加-t参数强制分配伪终端:
修改script.sh里的ssh命令为:
ssh -t user@10.10.10.10 path-to-script/script2.sh
如果一次-t不够,还可以用-tt强制分配(双重强制),不过这个方案最好配合免密sudo一起用,不然还是会卡在密码输入环节。
3. 用expect自动输入sudo密码(不推荐,安全性低)
如果实在没法配置免密sudo,可以用expect脚本自动输入密码,但这个方案的风险很高——密码会明文存储在脚本里,很容易泄露。如果是测试环境可以临时用:
把script.sh里的原ssh命令替换成:
expect << EOF spawn ssh user@10.10.10.10 path-to-script/script2.sh expect "password:" send "你的sudo密码\r" expect eof EOF
注意:目标服务器需要先安装expect工具(比如用apt install expect或yum install expect)。
4. 检查script2.sh的权限和命令路径
还有两个小细节容易被忽略:
- 确保script2.sh有可执行权限:在目标服务器上执行
chmod +x path-to-script/script2.sh - 在script2.sh里使用命令的绝对路径,比如写成
/usr/bin/sudo /usr/bin/systemctl start service,避免远程环境的PATH变量不全导致找不到命令
内容的提问来源于stack exchange,提问作者SameAs
相关产品推荐
相关产品推荐

