与手动执行相比,通过 PhP 执行 bash 脚本会给出不同的结果

Executing bash script via PhP gives a different result compared to executing manually

正如标题所说,当我尝试通过双击并通过终端按执行来手动执行脚本时。它工作正常

但是,当我 运行 我的 php 脚本或在终端中输入 php 时 window

/usr/bin/php start_cam.php

它锁定了(命令没有以“$”结束,“$”没有在终端中显示window表明它已经结束了任务并且它不能正常工作

下面是我的php脚本

<?php
        $command =escapeshellcmd("/bin/bash cmd_start_cam.sh");
        $output = shell_exec($command);
        echo $output;
        echo  "php_startcam2";

?>

下面是我的bash脚本(cmd_start_cam.sh)

!/bin/bash

echo 'running start camera script' 
cd
sudo chmod 755 /etc/rc.local
cd 
cd RPi_Cam_Web_Interface 
sudo chmod u+x RPi_Cam_Web_Interface_Installer.sh

sudo ./RPi_Cam_Web_Interface_Installer.sh stop 
sudo ./RPi_Cam_Web_Interface_Installer.sh start
echo 'complete start camera script' 

注意:我使用 cd 来确保 im 位于我的根目录中,因为文件所在的位置。由于它是通过手动执行工作的,所以不认为存在路径问题吗? 任何帮助是极大的赞赏。谢谢

更新:这是我遇到的终端命令输出的错误window:

我想在我的 bash 脚本命令 echo 'complete start camera script'

之后我遇到了管道损坏的问题

终端 window 输出 cmd_start_cam.sh: line 12: echo: write error: Broken Pipe 并且不会像正常执行时那样以 $ 结尾

顺便说一句,这是 运行宁 raspberry pi 2

Update Solved/Solution:

感谢@ikra 对检查 apache 日志文件的洞察力,这使我发现根本原因是权限访问。 www-data 需要添加到 sudoers 文件中。

  1. 关于备份和编辑 sudoers 文件的说明:http://raspbypi.com/enabling-the-sudo-command-for-a-new-user/
  2. sudo visudo
  3. 在文件末尾添加这个 www-data ALL=(ALL) NOPASSWD: ALL
  4. 按 CTRL+X 并按是
  5. 登录和注销以确保现在已设置权限。
  6. 如果您的 sudoer 文件损坏:在终端 window 中输入此命令以修复您输入错误的任何文本 pkexec visudo。(来源:https://askubuntu.com/questions/73864/how-to-modify-a-invalid-etc-sudoers-file-it-throws-out-an-error-and-not-allowi

您应该检查:

  • SUID 您的 shell-脚本,它们是 运行 和 sudo
  • 并确保您的 PHP 脚本的当前目录(和 PATH)一切正常。

尝试将您的脚本与 php-cli 一起使用,并将此行放在开头以查看发生了什么。

#!/usr/bin/php -ddisplay_errors=E_ALL

chmod 700 myscript.php

和运行这样

$ ./myscript.php

如果你想运行它在你的apache服务器下,只需在开始php标签后插入这个函数:

error_reporting(E_ALL);

也会这样做。

要将密码传递给 sudo 命令,请在脚本 shell 中使用 sudo -S *command* < <(echo -e "*pass*\n")。但是,这是个坏主意,因为每个可以访问您的脚本的人都可以获得您的密码。

我猜你的脚本启动了你的摄像头,如果 sudo ./RPi_Cam_Web_Interface_Installer.sh start 是流资源,那么问题是 shell_exec(./myscript.sh) 的缓冲区值有限,因此它无法处理你的响应脚本 shell.

尝试使用 popen() 而不是 shell_exec()

我发现了一个有趣的 link,它解决了一个与您的问题有些相似的问题

感谢@ikra 对检查 apache 日志文件的洞察力,这使我发现根本原因是权限访问。需要将 www-data 添加到 sudoers 文件中。

  1. 关于备份和编辑 sudoers 文件的说明:http://raspbypi.com/enabling-the-sudo-command-for-a-new-user/
  2. sudo visudo
  3. 在文件末尾添加这个 www-data ALL=(ALL) NOPASSWD: ALL
  4. 按 CTRL+X 并按是
  5. 登录和注销以确保现在已设置权限。
  6. 如果您的 sudoer 文件损坏:在终端 window 中输入此命令以修复您输入错误的任何文本 pkexec visudo。(来源:https://askubuntu.com/questions/73864/how-to-modify-a-invalid-etc-sudoers-file-it-throws-out-an-error-and-not-allowi

我最近发布了一个项目,允许 PHP 获取真实的 Bash shell 并与之交互(如果需要,作为 root),它解决了 exec() 和shell_exec()。在这里获取:https://github.com/merlinthemagic/MTS

下载后您只需使用以下代码:

$shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1  = $shell->exeCmd('php start_cam.php');
//the return will be a string containing the return of the command
echo $return1;

您可以维护 bash 脚本并像我的示例一样简单地触发它。然而看到脚本只是一堆bash命令,为什么不直接将它们触发到shell,这样你就可以处理return和任何异常。

就安全性而言,这比 运行 apache 作为 root 或您在解决方案更新中列出的广泛开放的 sudo 权限要好得多。但是让 PHP 靠近 root 的任何地方总是很棘手。

我构建的项目通过以下两种方式之一获得根 bash shell:

1) 您允许 apache sudo python.

2) 每次需要具有根设置的 shell 时,您都将根凭据传递给对象。

选择你的毒药。 :) 阅读文档。