提问人:miken32 提问时间:8/19/2017 最后编辑:miken32 更新时间:8/23/2017 访问量:1556
无法从 Web 服务器运行节点
Can't run node from web server
问:
我试图从PHP网页运行,但它永远不会运行。我总是得到一个退出代码 127 并且没有输出。在做了一些测试后,我将问题缩小到shebang,如下所示:npm
npm
#!/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 配置中启用,并在 PHP 日志中看到了这一点:catch_workers_output
[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 服务器运行,并在 PHP 日志中看到了这一点:exec("which node")
[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
单独运行并打印输出如下所示,没有 PATH 条目:env
Array
(
[0] => USER=nginx
[1] => PWD=/var/www/html
[2] => SHLVL=1
[3] => HOME=/var/cache/nginx
[4] => _=/bin/env
)
我使用的是基于 RHEL 的发行版,禁用了 SELinux,通过 Nginx 1.12.1 的 UNIX 套接字运行 PHP-FPM 5.6.31。 是一个符号链接,具有 775 个权限。出于测试目的,nginx 用户拥有该目录及其所有后代。有什么建议吗?/usr/local/bin/node
/usr/local/nodejs/bin/node
/usr/local/nodejs
请注意,如果我从 CLI(作为 nginx 用户)运行 PHP 代码,它会按预期工作,因此这肯定与 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)
答:
您需要将 environment 设置为包含 。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');
但这是最后的手段,我不推荐它。
评论
有一件事让我好奇......为什么以 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:
我仍然会照顾特权。
/usr/local/bin/node 是指向 /usr/local/nodejs/bin/node 的符号链接,它有 775 个权限。nginx 用户拥有 /usr/local/nodejs
在树上设置特定用户是不标准的。到那时,它将成为任何用户的存储库。/usr/local
-x
/usr/local
请在不同情况下(从 CLI、FPM、ngnix、etx)运行此脚本并检查您的权限:
<?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
评论
nginx
评论
exec("which node", $output, $exit);
node
$PATH
$_SERVER["PATH"]
null
node
$path
which
_
/bin/env
exec("/bin/env node --version", $output, $exit);
/usr/bin/env