简体   繁体   English

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

[英]php freezes when executing an external sh script

I'll try to explain my problem in a time line history: 我会尝试在时间线历史中解释我的问题:

I've tried to run several external scripts from php and to return the exit code to the server with an ajax call again. 我试图从php运行几个外部脚本,并再次使用ajax调用将退出代码返回给服务器。 A single call should start or stop an service on that machine. 单个调用应该启动或停止该计算机上的服务。 That works fine on this developing machine. 这在开发的机器上运行良好。

  • OS : raspbian Os 操作系统:raspbian Os
  • Webserver : NginX 1.2.1 网络服务器:NginX 1.2.1
  • Php : 5.4.3.6 Php:5.4.3.6

However I've exported the code to a larger machine with much more power and everything seemed to work fine but one thing: A single call causes the php-fpm to freezes and never to come back. 然而,我已经将代码导出到更大功率的更大的机器上,一切似乎都运行良好但有一点:单个调用导致php-fpm冻结,永远不会回来。 By detailed examination I found out, that the call created a zombie process I can not terminate (even with sudo). 通过详细的检查,我发现,调用创建了一个僵尸进程,我无法终止(即使使用sudo)。

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

The only solution seemed to stop the php-fpm proc and than to restart it again. 唯一的解决方案似乎是停止php-fpm proc而不是重新启动它。 Then everything seems to work fine again, as long as I try to call that script again. 然后一切似乎再次正常工作,只要我再次尝试调用该脚本。

Calling php line 调用php行

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

(With all variables are normal 'strings' with no special chars) (所有变量都是正常的“字符串”,没有特殊的字符)

Start script 启动脚本

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

The service by the way started, but every time the webserver freezes and I had to restart php manually, but that is not acceptable (even for a web server). 顺便说一下,服务开始,但每次网络服务器冻结,我不得​​不手动重启PHP,但这是不可接受的(即使对于Web服务器)。 But only for that single script and only for that service (radicale) with that solemn command (start). 但只适用于那个单一的脚本,只有那个服务(radicale)才能使用那个庄严的命令(开始)。

Searching in Google brought me to the point that there is a conflict between the php commands exec() and session_start() . 在Google中搜索让我发现php命令exec()session_start()之间存在冲突。

Links: 链接:

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

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

Their conclusion was, that that bug could be worked around with such a construct: 他们的结论是,这个bug可以用这样的结构解决:

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

But that, for my opinion, was no debugging, but more a helplessly workaround, because you loose the functionality of letting the user know, that his actions have fully functioned, but more let him believe an error has occurred. 但是,对于我来说,这不是调试,而是更多无助的解决方法,因为你失去了让用户知道的功能,他的行为已经完全发挥作用,但更让他相信发生了错误。 Much more confusing is the fact, that it runs fully on the Raspberry Pi A, but not on a 64-bit machine with a much larger CPU and 8 GB RAM. 令人困惑的是,它完全在Raspberry Pi A上运行,而不是在具有更大CPU和8 GB RAM的64位机器上运行。

So is there a real solution anywhere or is this workaround the only way to solve that problem? 那么在任何地方都有真正的解决方案 ,或者这种解决方法是解决该问题的唯一方法吗? I've read a article about php having some probs with exec/shell_exec and the recognition of the return value? 我读过一篇关于php的文章,其中包含一些带有exec / shell_exec的probs以及返回值的识别? How can that be lost? 怎么会丢失? Someone's having a guess? 有人在猜?

THX for reading that long awful English, but I'm no native speaker and was no well listening student in my lessons. THX用于阅读那个长得太糟糕的英语,但我不是母语,而且在我的课程中没有很好听的学生。

It is likely the case that the new machine simply is not set up the way the Raspberry PI was setup - 可能的情况是,新机器的设置方式与Raspberry PI的设置方式不同 -

You need to do a few things in your shell before this will work on your larger machine: 你需要在shell中做一些事情,然后才能在更大的机器上运行:

1). 1)。 Allow php to use sudo. 允许php使用sudo。

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

Note that to get the username for your-php-user , you can just run a script that says: 请注意,要获取your-php-user ,您只需运行一个脚本:

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

2). 2)。 Allow that user to use sudo without a password 允许该用户在没有密码的情况下使用sudo

sudo visudo - this command will open /etc/sudoers with a failsafe to keep you from botching anything. sudo visudo - 这个命令将打开/etc/sudoers ,带有故障保护,以防止任何拙劣。

Add this line to the very end: 将此行添加到最后:

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

You can put as many scripts there, separated by commas, as you need. 您可以根据需要在逗号中放置尽可能多的脚本。 Now, your script should work just fine. 现在,您的脚本应该可以正常工作。

AGAIN, please note that you need to change your-php-user to whatever your php user is. 再次注意,您需要将your-php-user更改为您的php用户。

Hope this helps! 希望这可以帮助!

This is not a real solution, but it's a better solution than none. 这不是一个真正的解决方案,但它是一个比没有更好的解决方案。

Calling a bash script with 用。调用bash脚本

<?php
...
exec("sudo ".$script, $output, $return_var);
...
?>

ends only in this special case in a zombie Thread. 仅在僵尸线程中的这种特殊情况下结束。 As php-fpm waits in expectation for a result, it still holds the line, not giving up nor time outs for the rest of its thread still living. 由于php-fpm等待结果的预期,它仍然保持着这条线,不会放弃,也不会超时剩下的线程仍然存在。 So every other request to the php server is still in queue and will never be processed. 所以对php服务器的每个其他请求仍然在队列中,永远不会被处理。 That may be okay for some long living or working threads, but my request was done in some [ms]. 对于一些长期生活或工作线程来说,这可能没问题,但我的请求是在某些[ms]中完成的。

I did not found the cause for this. 我没有找到原因。 As far as I could do debugging, I wasn't the triggered Radicale process fault, for this on gave a any time clean and brave 0 as in return. 至于我可以做的调试,我不是触发的Radicale过程故障,因为这给了一个任何时间干净和勇敢0作为回报。 It seemed that a php process just couldn't get a return line from it and so it still waits and waits. 似乎php进程无法从它获得返回线,因此它仍然等待并等待。

No time left I changed the malfunction script from 没时间了,我改变了故障脚本

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

to

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

... so signaling every returning line to nirvana and disconnecting all subroutines. ...所以将每个返回线路发送到必杀技并断开所有子程序。 For now the server did not hung itself up and works as desired. 目前,服务器没有自行挂起并按预期工作。 But the feeling this may be a major bug in php still stays in the back of my head, with the hope, that - someday - someone may defeat that bug. 但感觉这可能是PHP中的一个主要错误仍然留在我的脑后,希望,有一天 - 有人可能会打败那个bug。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM