首页 > 解决方案 > PHP shell_exec() 无法运行部分 shell 脚本

问题描述

我遇到了一个奇怪的问题。我创建了一个 gitlab 自定义 webhook。webhook 服务是用 php (gitlab.php) 编写的。当使用适当的有效负载调用 php 脚本时,应该会开始自动部署。部署脚本基本上是一个 shell 脚本(deploy.sh)

gitlab.php 代码

<?php
$json = file_get_contents('php://input');
// Converts it into a PHP object
$data = json_decode($json, true);
$secret = "";
foreach (getallheaders() as $name => $value) { 
    if($name=='X-Gitlab-Token') {
        $secret = $value;
    }
}

if($secret=="mysecretcode" && $data['object_kind']=="push") {
    file_put_contents("/opt/lampp/htdocs/autodeploy/autodeploy.log", "Webhook auto deployment started at ". date("Y-m-d H:i:s") . "\n". shell_exec("sh /opt/lampp/htdocs/autodeploy/deploy.sh")."\n**********************************************\n\n", FILE_APPEND);
    die("Deployment success");
}
else {
 die("Auth token invalid or no triggerable event found");
}
?>

deploy.sh 的代码

#!/bin/bash
cd "/opt/lampp/htdocs/nodejs/myapp"
echo "Stopping application..."
forever stop index.js
cd ..
sudo rm -rf myapp
echo "Pulling latest code from gitlab..."
git clone -b "master" https://myusername%40domain.com:MyEncodedPass123@gitlab.com/myusername/myapp.git
cd myapp
echo "Installing dependencies..."
npm install
echo "Starting application..."
forever start index.js
echo "Application started on port 3000."

当我将代码推送到 gitlab 时,它会触发 webhook 并启动部署过程,我看到我的 webhook 文件 gitlab.php 向 Gitlab 返回了成功响应,并在 autodeploy.log 文件中写入了以下输出

Webhook auto deployment started at 2021-10-03 13:32:07
Stopping application...
Pulling latest code from gitlab...
Installing dependencies...
Starting application...
Application started on port 3000.

**********************************************

但是,部署实际上从未发生过。它只是运行echo语句(也可能是cdrm等等),其余的 shell 命令被忽略或不执行。它肯定不会运行该git clone命令,因为我没有看到 gitlab 在我的服务器上刷新了最新代码。不确定npmandforever命令会发生什么。

顺便说一下,这是一个 Ubuntu VPS 服务器,安装了最新的 ApacheFriends XAMPP 服务器,php v8。上面提到的所有三个文件都位于同一路径/opt/lampp/htdocs/autodeploy,即我的 deploy.sh 脚本尝试在/opt/lampp/htdocs/nodejs/myapp文件夹中部署一个单独的 nodejs 应用程序。奇怪的是,当我直接从终端运行 deploy.sh 时,它会成功部署最新的代码。这意味着,脚本中的所有语句都按预期执行。它仅在使用 shell_exec() 函数从 php 脚本执行时才会失败。

任何线索可能是什么原因?

标签: phpbashgitwebhooksshell-exec

解决方案


文档shell_exec没有清楚地说明它,但很可能你只得到stdout你的命令,而不是它stderr-第一条评论当然似乎表明,它也将匹配“它与反引号相同”的描述。
如果是这种情况,您的输出中根本没有错误消息。

尝试运行:

shell_exec("sh .../deploy.sh 2>&1")

我还支持@phd 的建议(在对您问题的评论中):打开set -e,至少当您遇到错误时您的脚本会停止。
您当前的脚本可能会在第一行失败:cd "/opt/lampp/htdocs/nodejs/myapp"

我也强烈建议放弃sudo.sudo rm -rf ...


推荐阅读