PHP shell_exec调用GitLab自动部署shell脚本部分命令失效咨询
GitLab Webhook触发shell脚本部分命令不执行故障排查与解决
核心故障原因
- 运行用户的环境变量与权限差异:终端手动执行脚本时使用的是登录用户(一般是root或个人授权用户),而XAMPP中PHP通过Apache运行,执行用户是
daemon/www-data这类低权限用户,该用户的PATH环境变量不包含git、npm、forever等命令的安装路径,系统无法定位到命令,导致执行失败;但脚本未做错误拦截,echo命令仍会正常输出,造成命令已执行的假象。 - sudo权限配置缺失:脚本中包含
sudo rm命令,低权限用户执行sudo默认需要输入密码,非交互的Web执行环境没有密码输入入口,会直接导致命令执行失败,阻断后续流程。 - 目录权限不足:
/opt/lampp/htdocs/nodejs/目录默认仅允许root或创建用户读写,低权限的Apache运行用户没有写入权限,git clone时无法创建目录、写入文件,直接执行失败。 - PHP执行时间限制:PHP默认
max_execution_time为30秒,部署流程耗时超过限制时会被PHP主动中断,导致后续命令未执行。
解决步骤
确认Apache运行用户
在gitlab.php中临时添加代码echo shell_exec('whoami');,触发webhook后获取输出的运行用户,下文假设用户为daemon。配置sudo免密执行权限
执行sudo visudo编辑sudoers配置文件,在末尾添加如下行,限制daemon用户仅能免密执行该部署脚本,兼顾安全性:
daemon ALL=(ALL) NOPASSWD: /opt/lampp/htdocs/autodeploy/deploy.sh
- 补全脚本内命令的绝对路径
在终端分别执行which git、which npm、which forever获取对应命令的绝对路径,替换deploy.sh内的相关命令,示例修改后脚本如下:
#!/bin/bash # 开启调试模式,所有执行命令会输出到日志,方便排查问题 set -x cd "/opt/lampp/htdocs/nodejs/myapp" echo "Stopping application..." /usr/local/bin/forever stop index.js cd .. sudo rm -rf myapp echo "Pulling latest code from gitlab..." /usr/bin/git clone -b "master" https://myusername%40domain.com:MyEncodedPass123@gitlab.com/myusername/myapp.git cd myapp echo "Installing dependencies..." /usr/local/bin/npm install echo "Starting application..." /usr/local/bin/forever start index.js echo "Application started on port 3000."
- 分配目录权限
给部署目标目录授予Apache运行用户读写权限:
sudo chown -R daemon:daemon /opt/lampp/htdocs/nodejs/
取消PHP执行时间限制
在gitlab.php开头添加代码set_time_limit(0);,取消脚本最大执行时间限制,避免部署过程被PHP中断。优化日志输出
将gitlab.php中shell_exec调用改为错误输出重定向,捕获所有报错信息到日志:
shell_exec("sh /opt/lampp/htdocs/autodeploy/deploy.sh 2>&1")
内容的提问来源于stack exchange,提问作者sribasu
相关产品推荐
相关产品推荐

