PHP 7.0 exec执行shell脚本时www-data无法写入/创建文件问题
PHP 7.0 exec执行shell脚本失败的排查与解决
我之前也碰到过一模一样的问题——命令行用www-data跑脚本完全正常,一放到PHP的exec里就罢工,大概率是环境、权限或者安全限制在搞鬼,给你梳理几个实用的排查方向和解决办法:
1. 环境变量差异是重灾区
命令行下的www-data和PHP-FPM/mod_php运行的www-data,环境变量完全不是一回事!比如PATH,脚本里如果用了cp、rsync这类命令,PHP可能根本找不到它们的安装路径。
解决办法:
- 把脚本里的所有命令都改成绝对路径,比如用
/usr/bin/cp代替cp,/usr/bin/rsync代替rsync(可以在命令行用which cp查具体路径)。 - 或者在
exec调用里手动指定环境变量,比如:exec('export PATH=/usr/bin:/bin:/usr/sbin:/sbin && sh /var/www/sync.sh 2>&1', $output, $return_var);
2. 捕获错误输出才能找到根源
PHP的exec默认只抓取标准输出(stdout),脚本执行的错误信息(stderr)会直接被丢掉,你根本不知道到底哪里出问题了!
解决办法:
修改你的exec调用,把错误输出重定向到标准输出,同时捕获返回码和执行日志:
$output = []; $return_code = 0; exec('sh /var/www/sync.sh 2>&1', $output, $return_code); echo "脚本返回码: " . $return_code . "\n"; echo "执行输出:\n"; print_r($output);
返回码非0就说明脚本执行失败,输出内容会明确告诉你是权限不够、命令找不到还是路径写错了。
3. 脚本和路径的权限/路径坑
- 先确认
/var/www/sync.sh的权限:至少要给www-data执行权限,比如设置chmod 755 /var/www/sync.sh,同时确保www-data能读取这个文件。 - 脚本里的相对路径要人命!比如脚本里写
./data.log,命令行跑的时候工作目录是/tmp/data,但PHP执行时的工作目录可能是/var/www或者服务器根目录,所以一定要改成绝对路径/tmp/data/data.log。
4. PHP的安全配置限制
检查PHP的配置文件(php.ini):
- 看看
disable_functions里有没有exec,如果有就把它删掉,然后重启PHP服务。 - 看看
open_basedir设置,如果它限制了PHP能访问的目录,要确保/tmp和/var/www都在允许列表里,比如open_basedir = /var/www/:/tmp/。
5. SELinux或AppArmor的拦截
如果你的服务器开了SELinux(常见于CentOS/RHEL)或者AppArmor(常见于Ubuntu),它们可能会阻止PHP执行外部脚本或者访问/tmp目录。
排查办法:
- SELinux:执行
getenforce,如果显示Enforcing,临时关闭试试setenforce 0,再测试脚本。如果能正常运行了,就需要添加SELinux规则允许PHP访问相关资源。 - AppArmor:执行
aa-status看看有没有针对PHP的配置,临时禁用systemctl stop apparmor测试,没问题的话再调整规则。
内容的提问来源于stack exchange,提问作者user3592217
相关产品推荐
相关产品推荐

