PHP shell_exec执行git pull SSH运行正常 浏览器访问无限挂起
问题根本原因
两种执行方式的运行身份、环境配置完全不同,是导致差异的核心原因:
- SSH执行时使用你登录服务器的个人用户身份,已完成git相关配置(凭证、安全目录、主机指纹等),也拥有仓库目录的读写权限,git命令可正常执行返回
- 网页访问时PHP以web服务运行用户身份执行(常见为
www-data、apache、nobody等),缺少对应权限和配置,git执行时触发交互提示导致进程无限阻塞。
排查步骤
- 首先确认web运行用户,在脚本开头加入以下代码,访问网页即可拿到运行用户名:
echo exec('whoami'); exit;
- 切换到对应web运行用户,手动执行git命令复现问题,查看具体阻塞原因,示例命令(假设运行用户为
www-data):sudo -u www-data git pull https://****@bitbucket.org/****/****.git 2>&1
常见阻塞原因分为以下几类:
- git安全目录限制:git 2.35.2版本后新增安全规则,禁止操作其他用户所有的目录,会抛出
directory is not safe报错 - 主机指纹确认提示:首次访问远程git仓库时会弹出是否保存主机指纹的交互提示,web环境无人输入确认就会一直挂起
- 目录权限不足:web运行用户没有仓库目录的读写权限,git pull无法写入文件
- 凭证缺失:未配置git凭证存储,触发用户名密码输入提示(你已在URL中携带凭证的话该问题概率较低)
修复方案
根据排查到的问题对应处理即可:
- 配置git安全目录:执行命令给web运行用户添加仓库目录为安全目录,示例:
git config --global --add safe.directory /你的仓库绝对路径
注意需要切换到web运行用户执行该命令,或者直接修改全局git配置文件 - 提前保存主机指纹:切换到web运行用户后手动执行一次
git ls-remote 你的仓库地址,遇到提示输入yes保存主机指纹,后续不会再弹出交互提示 - 调整目录权限:确保web运行用户对仓库目录有读写权限,示例命令:
chown -R www-data:www-data /你的仓库绝对路径
生产环境不建议直接给目录开全局读写权限,修改所有者是更安全的方案 - 代码层面禁用交互:给git命令添加
--no-interaction参数,禁止所有交互提示,避免未知阻塞点,修改后代码如下:
$output = shell_exec('git pull --no-interaction https://****@bitbucket.org/****/****.git 2>&1'); print_r($output);
内容的提问来源于stack exchange,提问作者dlofrodloh
相关产品推荐
相关产品推荐

