【问题标题】:From PHP a Simple Linux Script to return "Hello World"从 PHP 一个简单的 Linux 脚本返回“Hello World”
【发布时间】:2017-04-10 11:47:35
【问题描述】:

好的,很高兴接受反对票以解决我的问题。我是 Linux 的新手,但我在 Linux 云服务器上托管了基于 PHP 的站点,需要运行 FFMPEG 脚本来转换视频。在 Windows 下,我可以运行完整的应用程序,但在 Linux 下,我似乎无法让基本脚本正常工作,并且想知道是否有人可以为我指明正确的方向。我已经阅读了无数关于此的帖子,例如Run bash Command from PHP,但这并不能帮助我深入了解它。

这是我目前所拥有的。

$old_path = getcwd();
chdir('videos/');
$new_path = getcwd();
echo('newpath '.$new_path); <-- this outputs 'old_path/videos'
$temp=  shell_exec('./testScript.sh');
echo ($temp) <-- produces nothing

测试脚本testScript.sh在video目录下,很简单

echo "hello world"

谢谢...

【问题讨论】:

  • 视频在哪里?不能chdir('../videos')吗?
  • 我认为这是网络根目录中的问题,可能不应该是。

标签: php linux bash shell


【解决方案1】:

在shell脚本中必须写和解释器。

试试这个:shell_exec('php ./testScript.sh');

编辑:使用正确的解释器(bash、sh...)更改 php

【讨论】:

  • 有趣 - 是的,它修复了它。我很好奇为什么这个解决方案没有出现在这个主题的其他帖子中。
  • 通常是用shell脚本编写的解释器。例如 #!/bin/sh (文件中的第一行)
【解决方案2】:

首先要做的是检查 PHP 是否真的允许运行一个 shell 脚本。

在命令提示符下运行以下命令

php -i | grep disable_functions

这应该回复一个看起来像这样的行

disable_functions => no value => no value

但是如果它返回一个包含shell_exec的字符串,像这样(它可能包含其他内容)

disable_functions => shell_exec => shell_exec 

那么您将无法继续。 此时的诀窍是尝试本地 php.ini 文件,看看是否可以关闭违规指令。

为此,请将 php.ini 文件复制到您正在工作的目录中。找到 disable_functions => shell_exec => shell_exec 行删除 shell_exec。

然后像这样在命令行上运行你的脚本

php -c php.ini myscript.php

然而,这在云托管环境中可能会受到很大限制,因为访问 shell 显然会造成一定程度的混乱。

您也可以使用 apache config 和 .htaccess 来做到这一点。

如果以上都OK,那么检查testScript.sh 的权限并且它被设置为可执行文件。这样做是

chmod +x testScript.sh

我敢打赌,受限制的云服务器环境会阻止你。

【讨论】:

  • 原来是没有指定解释器的问题,但感谢您对一些 PHP 内部结构的洞察力。
【解决方案3】:

文件系统权限

在您的情况下,脚本可能由于file system permissions 不足而未执行。在Linux中,如果文件为当前用户或用户组设置了可执行位,则只需写入文件路径即可执行文件,例如:

~/scripts/abc.php
./script.sh

否则,您应该将文件作为参数传递给适当的程序,例如:

php ~/scripts/abc.php
/usr/bin/php ./script.php
bash ./script.sh

您可以使用lsstat命令检查文件系统权限,例如:

$ stat --format='perm: %A | user: %U | group: %G' 1.sh
perm: -rwxr-xr-x | user: ruslan | group: users

$ ls -l 1.sh
-rwxr-xr-- 1 ruslan users 1261 Nov 26 11:47 1.sh

在上面的示例中,为用户ruslan 和组users 设置了可执行位,但未为其他人 (r--) 设置可执行位。其他人只能读取 (r) 文件,但不能执行或写入文件。

要设置可执行位,请使用chmod 命令,例如:

# For the user
chmod u+x file.sh
# For the group
chmod g+x file.sh

更好地控制命令执行

shell_exec 函数返回写入标准输出描述符的内容。如果命令不打印任何内容或失败,则返回NULL。例如:

$out = shell_exec("ls -l inexistent-file");
var_dump($out); // NULL

因此,您无法很好地控制 shell_exec 的错误情况。我建议改用prop_open

$cmd = 'ls -l 1.sh inexistent-file';

// Descriptors specification
$descriptors = [
  1 => ['pipe', 'w'], // standard output
  2 => ['pipe', 'w'], // standard error
];

// Open process for the command
$proc = proc_open($cmd, $descriptors, $pipes);
if (!is_resource($proc))
  die("failed to open process for $cmd");

if ($output = stream_get_contents($pipes[1])) {
  echo "output: $output\n";
}
fclose($pipes[1]);

if ($errors = stream_get_contents($pipes[2])) {
  fprintf(STDERR, "Errors: %s\n", $errors);
}
fclose($pipes[2]);

// Close the process
if (($status = proc_close($proc)) != 0)
  fprintf(STDERR, "The command failed with status %d\n", $status);

射帮

考虑将shebang 用于可执行脚本。例子:

#!/bin/bash -
#!/usr/bin/php

【讨论】:

  • 感谢这给了我关于 Linux 的洞察力。确实很有帮助。
  • 使用您的 proc_open 命令,我发现 ffmpeg 返回“权限被拒绝”,但是即使将所有权限/权限设置为 744 ffmpeg 仍然不会执行。
  • @TrueBlue,你能显示代码吗?否则很难猜到。顺便说一下,Bash 中的set -x 命令开启了调试模式(可以看到正在执行的命令。
  • 我怀疑是我的无能。 set -x 在告诉我找不到 ffmpeg 时很有用,所以我怀疑不允许简单地将 linux 可执行文件复制到 Web 服务器上
  • @TrueBlue,是的,您应该从存储库在服务器上安装 ffmpeg 包。例如,在 Ubuntu 上:sudo apt-get install ffmpeg;在 Fedora 上:sudo yum install ffmpeg.
猜你喜欢
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多