我会尝试在时间线历史中解释我的问题:
我尝试从php运行多个外部脚本,并再次使用ajax调用将退出代码返回给服务器。 单个调用应该启动或停止该计算机上的服务。这在这台开发机上运行良好。
然而,我已经将代码导出到更大功率的更大机器上,而且一切似乎都运行正常但有一点: 一次调用导致php-fpm冻结,永远不会回来。通过详细的检查,我发现,调用创建了一个僵尸进程,我无法终止(即使使用sudo)。
唯一的解决方案似乎是停止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用于阅读那个长得太糟糕的英语,但我没有以母语为母语,在我的课程中没有很好的听力学生。
答案 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。