无法从Web服务器运行节点

时间:2017-08-18 19:06:59

标签: php bash shell npm path

我试图从PHP网页运行npm,但它永远不会运行。我的退出代码总是127,没有输出。在做了一些测试后,我把问题缩小到npm中的shebang,看起来像这样:

#!/usr/bin/env node

非常标准,但我做了一些测试代码:

<?php
$result = exec("/usr/bin/env node --version", $output, $exit);
var_dump($result);
var_dump($exit);
$result = exec("node --version", $output, $exit);
var_dump($result);
var_dump($exit);
$result = exec("/usr/bin/env gzip --version", $output, $exit);
var_dump($result);
var_dump($exit);

在我的浏览器中输出了这个输出:

string(0) ""
int(127)
string(6) "v8.4.0"
int(0)
string(28) "Written by Jean-loup Gailly."
int(0)

我在PHP-FPM配置中启用了catch_workers_output,并在PHP日志中看到了这一点:

[18-Aug-2017 15:15:35] WARNING: [pool web] child 27872 said into stderr: "/usr/bin/env: "
[18-Aug-2017 15:15:35] WARNING: [pool web] child 27872 said into stderr: "node"
[18-Aug-2017 15:15:35] WARNING: [pool web] child 27872 said into stderr: ": No such file or directory"
[18-Aug-2017 15:15:35] WARNING: [pool web] child 27872 said into stderr: ""

我也尝试从Web服务器运行exec("which node"),并在PHP日志中看到了这一点:

[18-Aug-2017 15:31:12] WARNING: [pool web] child 27873 said into stderr: "which: no node in ((null))"

我尝试运行var_dump(exec('echo $PATH'))并获得此输出:

string(28) "/usr/local/bin:/bin:/usr/bin"

这似乎与env命令如何处理路径有关。我尝试使用fastcgi_param PATH中的nginx.conf指令手动设置它,但它没有对上面的输出进行任何更改。

单独运行env并打印输出如下所示,没有PATH条目:

Array
(
    [0] => USER=nginx
    [1] => PWD=/var/www/html
    [2] => SHLVL=1
    [3] => HOME=/var/cache/nginx
    [4] => _=/bin/env
)

我正在使用基于RHEL的发行版,禁用SELinux,通过UNIX插槽从Nginx 1.12.1运行PHP-FPM 5.6.31。 /usr/local/bin/node/usr/local/nodejs/bin/node的符号链接,拥有775个权限。为了测试目的,nginx用户拥有/usr/local/nodejs目录及其所有后代。有什么建议吗?

请注意,如果我从CLI运行PHP代码(作为nginx用户),它会按预期工作,因此这肯定与CGI / FPM环境有关。

$ su -s "/bin/sh" -c "/var/www/html/test.php" nginx
string(6) "v8.4.0"
int(0)
string(6) "v8.4.0"
int(0)
string(28) "Written by Jean-loup Gailly."
int(0)

2 个答案:

答案 0 :(得分:3)

您需要在PATH中设置/etc/php5/fpm/pool.d/www.conf个环境,以包含/usr/local/bin/node

在ubuntu发行版中,它被注释掉了:

;env[PATH] = /usr/local/bin:/usr/bin:/bin 

所以

env[PATH] = /usr/local/bin/node 

应该做的工作。 RHEL不应该是非常不同的,但即使不存在该行,您也可以随时添加它。

别忘了重启php-fpm。

如果无效,您可以在致电npm时明确设置路径:

exec('PATH=$PATH:/usr/local/bin/node npm');

但这是最后的手段,我不推荐它。

答案 1 :(得分:0)

有一件事让我好奇......为什么在ngnix用户运行脚本的时候呢?

实际上,ngnix要求php-fpm进程,而PHP-FPM正在执行你的脚本。因此,可能PHP-FPM服务是一个,它缺少/usr/bin/env node的权限。

保持简单,ngnix需要权限将虚拟手放在PHP-FPM上。但是PHP-FPM需要权限来处理文件。

为了保持解决方案的简单,可以通过将PHP-FPM用户(www-data?)添加到组中来解决,该节点二进制文件已经存在且ngnix用户已经在。

或者更好地遵循以下建议:https://serverfault.com/a/52703

编辑#1:

我仍然会照顾privelages。

  

/ usr / local / bin / node是/ usr / local / nodejs / bin / node的符号链接,具有775个权限。 nginx用户拥有/ usr / local / nodejs

使用/usr/local-x树上设置特定用户有点不标准。当/usr/local成为任何用户的存储库时。

请在不同情况下(从CLI,FPM,ngnix,etx)运行此脚本并检查您的privelages:

<?php

$myuid = getmyuid();
$mygid = getmygid();

// you should change to check /usr/local/nodejs/bin/node
$path = '/usr/local/n/versions/node/7.2.0/bin/node'; 

$patharray = array_filter(explode('/', $path));

$dump = "%s \t %s \t %s%s%s \t %s" . PHP_EOL;

$fileOrFolder = __FILE__;
printf("uid \t gid \t rwx \t file" . PHP_EOL);
printf($dump, $myuid, $mygid, (is_readable($fileOrFolder) ? 'r' : '-'), (is_writable($fileOrFolder) ? 'w' : '-'), (is_executable($fileOrFolder) ? 'x' : '-'), $fileOrFolder);

$fileOrFolder = '';
while(count($patharray) > 0) {
    $fileOrFolder .= ('/' .  array_shift($patharray));

    $myuid = posix_getpwuid(fileowner($fileOrFolder));
    $mygid = posix_getgrgid(filegroup($fileOrFolder));

    printf($dump, $myuid['name'], $mygid['name'], (is_readable($fileOrFolder) ? 'r' : '-'), (is_writable($fileOrFolder) ? 'w' : '-'), (is_executable($fileOrFolder) ? 'x' : '-'), $fileOrFolder);

    if (is_dir($fileOrFolder) && !is_executable($fileOrFolder)) {
        echo PHP_EOL . "Ouh, cant go further cause of privelages" . PHP_EOL;
        break;
    }
}

排雷输出样张,即使是不同的用户,PHP也可以一直向下看目标文件:

@riddick:~/temp$ php phpowner.php
uid      gid     rwx     file
1000     1000    rw-     /home/yergo/temp/phpowner.php
root     root    r-x     /usr
root     root    r-x     /usr/local
root     root    r-x     /usr/local/n
root     root    r-x     /usr/local/n/versions
root     root    r-x     /usr/local/n/versions/node
root     root    r-x     /usr/local/n/versions/node/7.2.0
                 r-x     /usr/local/n/versions/node/7.2.0/bin
                 r-x     /usr/local/n/versions/node/7.2.0/bin/node