php在执行外部sh脚本时冻结

时间:2015-02-19 17:05:52

标签: php session exec freeze radicale

我会尝试在时间线历史中解释我的问题:

我尝试从php运行多个外部脚本,并再次使用ajax调用将退出代码返回给服务器。 单个调用应该启动或停止该计算机上的服务。这在这台开发机上运行良好。

  • OS:raspbian Os
  • 网络服务器:NginX 1.2.1
  • Php:5.4.3.6

然而,我已经将代码导出到更大功率的更大机器上,而且一切似乎都运行正常但有一点: 一次调用导致php-fpm冻结,永远不会回来。通过详细的检查,我发现,调用创建了一个僵尸进程,我无法终止(即使使用sudo)。

  • 操作系统:Ubuntu
  • 网络服务器:NginX 1.6.2
  • Php:5.5.9

唯一的解决方案似乎是停止php-fpm proc而不是重新启动它。然后一切似乎再次正常工作,只要我再次尝试调用该脚本。

调用php行

exec("sudo ".$script, $output, $return_var);

(所有变量都是正常的'字符串'没有特殊的字符)

启动脚本

#!/bin/sh
service radicale start 2>&1

顺便开始服务,但每次网络服务器冻结,我不得​​不手动重启php,但这是不可接受的(即使对于Web服务器)。 但仅限于那个单一的脚本,只有那个服务(radicale)才能使用那个庄严的命令(开始)。

在Google中搜索让我发现php命令 exec() session_start()之间存在冲突。

链接:

https://bugs.php.net/bug.php?id=44942

https://bugs.php.net/bug.php?id=44994

他们的结论是,这个bug可以用这样的结构解决:

...
session_write_close();
exec("sudo ".$script, $output, $return_var);
session_start();
...

但是,对于我来说,这不是调试,而是更多无助的解决方法,因为你失去了让用户知道的功能,他的行为已经完全发挥作用,但更让他相信发生了错误。令人困惑的是,它完全在Raspberry Pi A上运行,而不是在具有更大CPU和8 GB RAM的64位机器上运行。

那么在任何地方都有真正的解决方案,或者这种解决方法是解决该问题的唯一方法吗?我读过一篇关于php的文章,其中包含一些带有exec / shell_exec的probs以及返回值的识别?怎么会丢失?有人在猜?

THX用于阅读那个长得太糟糕的英语,但我没有以母语为母语,在我的课程中没有很好的听力学生。

2 个答案:

答案 0 :(得分:1)

可能的情况是,新机器的设置方式与Raspberry PI的设置方式不同 -

你需要在shell中做一些事情,然后才能在更大的机器上运行:

1)。允许php使用sudo。

sudo usermod -G sudo -a your-php-user

请注意,要获取your-php-user的用户名,您只需运行一个说明以下内容的脚本:

<?php echo get_current_user(); ?> - 或者: <?php echo exec('whoami'); ?> -

2)。允许该用户在没有密码的情况下使用sudo

sudo visudo - 此命令将打开/etc/sudoers并附带故障保护,以防止任何操作。

将此行添加到最后:

your-php-user ALL=(ALL) NOPASSWD: /path/to/your/script,/path/to/other/script

您可以根据需要在逗号中放置尽可能多的脚本。 现在,您的脚本应该可以正常工作。

再次注意,您需要将your-php-user更改为您的php用户。

希望这有帮助!

答案 1 :(得分:-1)

这不是一个真正的解决方案,但它比没有解决方案更好。

使用

调用bash脚本
<?php
...
exec("sudo ".$script, $output, $return_var);
...
?>

仅在僵尸线程的这种特殊情况下结束。由于php-fpm等待结果的预期,它仍然保持着这条线,不会放弃,也不会超时剩下的线程仍然存在。所以对php服务器的每个其他请求仍然在队列中,永远不会被处理。对于一些长期生活或工作线程来说,这可能没问题,但我的请求是在某些[ms]中完成的。

我没有找到原因。至于我可以做的调试,我不是触发的Radicale过程故障,因为这给了一个任何时间干净和勇敢0作为回报。似乎php进程无法从它获得返回线,因此它仍然等待并等待。

没时间了我从

更改了故障脚本
#!/bin/sh
service radicale start 2>&1

#!/bin/sh
service radicale start > /dev/null 2>&1 &

...所以将每个返回的行发送到必杀技并断开所有子程序。目前,服务器没有自行挂起并按预期工作。但感觉这可能是php中的一个主要错误仍然留在我的脑后,希望,有一天 - 有人可能会打败那个bug。