我有以下内容PHP 5.6.19
上的代码Ubuntu 14.04
服务器。这段代码只是连接到一个MySQL 5.6.28
数据库,等待一分钟,启动其自身的另一个进程,然后退出。
注意:这是完整的脚本,其目的是演示问题 - 它没有做任何有用的事情。
class DatabaseConnector {
const DB_HOST = 'localhost';
const DB_NAME = 'database1';
const DB_USERNAME = 'root';
const DB_PASSWORD = 'password';
public static $db;
public static function Init() {
if (DatabaseConnector::$db === null) {
DatabaseConnector::$db = new PDO('mysql:host=' . DatabaseConnector::DB_HOST . ';dbname=' . DatabaseConnector::DB_NAME . ';charset=utf8', DatabaseConnector::DB_USERNAME, DatabaseConnector::DB_PASSWORD);
}
}
}
$startTime = time();
// ***** Script works fine if this line is removed.
DatabaseConnector::Init();
while (true) {
// Sleep for 100 ms.
usleep(100000);
if (time() - $startTime > 60) {
$filePath = __FILE__;
$cmd = "nohup php $filePath > /tmp/1.log 2>&1 &";
// ***** Script sometimes exits here without opening the process and without errors.
$p = popen($cmd, 'r');
pclose($p);
exit;
}
}
我使用以下命令启动脚本的第一个进程nohup php myscript.php > /tmp/1.log 2>&1 &
.
这个进程循环应该永远持续下去,但是......基于多次测试,在一天之内(但不是立即),服务器上的进程无缘无故地“消失”。我发现MySQL
代码导致popen
代码失败(脚本退出,没有任何错误或输出)。
这里发生了什么?
Notes
- 服务器 24/7 运行。
- 内存不是问题。
- 数据库连接正确。
- 文件路径不包含空格。
- 使用时也存在同样的问题
shell_exec
or exec
代替popen
(and pclose
).
我也知道popen
是失败的行,因为我通过在脚本中的某些点记录到文件来进行进一步的调试(上面未显示)。
fork之后父进程肯定退出吗?我以为pclose
会等孩子出去再回来。
如果它没有退出,我推测因为 mySQL 连接永远不会关闭,所以当您生成子进程树时,您最终会达到其连接限制(或其他一些限制)。
Edit 1
我只是尝试复制这个。我将你的脚本修改为每半秒而不是每分钟 fork 一次,并且能够在大约 10 分钟内杀死它。
看起来子进程的重复创建正在生成越来越多的 FD,直到最终不再有:
$ lsof | grep type=STREAM | wc -l
240
$ lsof | grep type=STREAM | wc -l
242
...
$ lsof | grep type=STREAM | wc -l
425
$ lsof | grep type=STREAM | wc -l
428
...
这是因为子进程在分叉时继承了父进程的 FD(在本例中为 mySQL 连接)。
如果之前关闭了mySQL连接popen
与(在你的情况下):
DatabaseConnector::$db = null;
问题有望消失。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)