如何在PHP的shell_exec中正确嵌入Shell命令以覆盖远程文件?
解决PHP中shell_exec执行SSH覆盖远程文件失败的问题
我来帮你梳理下可能的原因和对应的解决办法,毕竟bash里正常但PHP里不行,大概率是运行环境或者命令处理的差异导致的:
1. PHP运行用户的SSH权限问题
咱们在本地bash里用的是自己的用户,密钥存在这个用户的~/.ssh目录里,但PHP通常是用www-data(Apache)或者nginx这类系统用户运行的,这些用户可能根本没有访问你个人密钥的权限,甚至连自己的.ssh目录都没有。
解决办法:
- 给PHP运行用户配置独立的SSH密钥对,把公钥添加到远程服务器的
root/.ssh/authorized_keys里 - 或者把你的私钥复制到PHP用户的
.ssh目录下,记得设置正确的权限:sudo mkdir /var/www/.ssh sudo cp ~/.ssh/id_rsa /var/www/.ssh/ sudo chown -R www-data:www-data /var/www/.ssh sudo chmod 700 /var/www/.ssh sudo chmod 600 /var/www/.ssh/id_rsa
2. 变量未转义导致命令被破坏
你直接把$_GET["phone"]放到shell命令里,如果手机号里包含特殊字符(比如空格、&、|这类),会直接打乱命令结构,甚至引发安全问题。
解决办法:用escapeshellarg()对变量进行转义,确保它作为一个完整的参数传入shell:
$number = $_GET["phone"]; $safe_number = escapeshellarg($number); // 转义特殊字符
3. SSH命令未明确指定密钥路径
PHP的运行环境可能没有正确的环境变量,导致SSH找不到密钥文件。这时候可以在SSH命令里直接指定私钥路径,避免依赖环境变量:
$out = shell_exec("echo $safe_number | ssh -i /var/www/.ssh/id_rsa root@0.0.0.0 'cat > /path/to/file/number.txt'");
4. 开启错误调试,定位具体问题
shell_exec默认只返回标准输出,错误信息会被忽略,咱们可以把标准错误重定向到标准输出,这样就能看到具体的报错了:
$out = shell_exec("echo $safe_number | ssh -i /var/www/.ssh/id_rsa root@0.0.0.0 'cat > /path/to/file/number.txt' 2>&1"); var_dump($out); // 打印所有输出,包括错误
修改后的完整代码示例
$number = $_GET["phone"]; $safe_number = escapeshellarg($number); // 替换成你实际的密钥路径和远程地址 $out = shell_exec("echo $safe_number | ssh -i /var/www/.ssh/id_rsa root@0.0.0.0 'cat > /path/to/file/number.txt' 2>&1"); var_dump($out);
内容的提问来源于stack exchange,提问作者Piyumi Guruge




