gpt4 book ai didi

php - 在 PHP 中,exec 有时会默默地失败,当调用许多 exec 命令时,但稍后再次运行相同的命令会起作用

转载 作者:搜寻专家 更新时间:2023-10-31 22:06:10 26 4
gpt4 key购买 nike

我有一个使用 exec('command args >/log/file &') 的 PHP 脚本;在一个循环中创建多个同时运行的子脚本。基本上,父脚本从数据库中获取用户信息并创建并行运行的子脚本,然后子脚本创建一封电子邮件以发送给单个用户。这种情况大约发生 50,000 次。

为了防止创建 50,000 个同时运行的进程,我有一个数据库表来跟踪当前正在运行的进程,在创建新进程之前,父进程会检查当前的子进程数,如果当前有 25 个子进程处于事件状态,则进入休眠状态。子项在完成其任务后,删除其在表中的行,从而释放父项以创建更多子项。

问题是,大约 10% 的 exec 命令无声无息地失败了,而且似乎没有任何原因。我可以再次运行父脚本(它足够聪明,不会向同一用户发送两次电子邮件),它会再次运行,90% 的时间使用上次失败的相同 exec 命令。连续运行该脚本五六次会向所有人发送电子邮件。

通过在 exec 之后立即 sleep ,我可以将成功率提高到 95% 左右。

为什么 exec 会失败,如果相同的命令稍后会起作用?我可以一直重复脚本直到它完成,但我更愿意解决 exec 问题。

一些高度简化的示例代码:

父脚本:

do {
//get user, group, and supergroup information for users that haven't
//been emailed yet
foreach ($users as $userArray) {
$processId = insertIntoProcessQueue($userArray);
$cmd = 'sudo php -q ./childScript.php ' . cliArg($userArray) . ' ' .
cliArg($groupArray) . ' ' . cliArg($supergroupArray)
' ' . $proccessId . ' > file.log &';
exec($cmd);
do {
if (numChildren() >= 25) {
sleep(1);
$waiting = true;
}
} while ($waiting);
}
$incomplete = moreUsersToEmail() > 0 ? true : false;
} while ($incomplete);

function cliArg($array) {
return escapeshellarg(json_encode($arg));
}

子脚本:

ignore_user_abort(true);
$user = json_decode($argv[1]);
$group = json_decode($argv[2]);
$supergroup = json_decode($argv[3]);

print_r($user);

$email = createEmail($user, $group, $supergroup);

$email->sendEmail();
removeFromProcessQueue($argv[4]);
flush();
exit;

print_r 只会在脚本完成时显示在日志文件中,而且我从来没有收到任何错误,所以我无法获得有关失败原因的任何数据。除此之外,它不会对任何单个用户持续失败,并且不会一次运行单个用户失败,所以我必须通过每个人运行脚本并 try catch 45,000 个中的错误好好工作。而且,由于 parent 和 child 永远不会在 parent 启动 child 之外进行交流,所以我无法(从 parent 那里)检测到 child 何时失败(否则我可以立即尝试再次启动任何失败的 child ,而不是事后重新运行 parent ).

编辑:原来有一个包含的脚本是动态生成的,每次使用时都会被销毁并重新生成(不要问我为什么),这会在并行运行进程时造成竞争条件,导致脚本失败.

感谢大家浪费了宝贵的时间。

最佳答案

我刚刚看了the PHP docs for exec()您可以将数组作为引用传递给第二个参数,该参数将填充 exec 的输出。您可以使用它来确定 a) 命令失败的原因以及 b) 命令失败的时间并将其集成到您的代码中。

所以我会改变:

exec($cmd);

类似于:

function check_exec_results($results)
{
echo '<HR><PRE>',print_r($output,true),'</PRE><HR>'; //use this to figure out what output you're getting from the exec commands then remove when you've figured out a way to set $results_look_good below

$results_look_good = ?; //you will need to edit this yourself to actually do some kind of check

return $results_look_good;
}

$successful_exec = false;
do
{
$exec_results = array();
exec($cmd,$exec_results);
$successful_exec = check_exec_results($exec_results);
}
while (!$successful_exec);

请注意,这可能是一个无限循环,因此我还要更进一步,为每个用户设置可调用 exec() 的次数限制。

关于php - 在 PHP 中,exec 有时会默默地失败,当调用许多 exec 命令时,但稍后再次运行相同的命令会起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18236969/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com