【问题标题】:Run PHP Script in Background(Without Using Cron)在后台运行 PHP 脚本(不使用 Cron)
【发布时间】:2023-03-12 18:20:01
【问题描述】:

我想在某些情况下在后台运行以下代码:

文件 A:

// ------------------- Some Code Before Following -----------------------

// send notification to given device token
$notification = new Notification();                    
$notification->sendNotification($token,$count);

// ------------------- Some Code After Above ------------------------

这将调用以下类:

// Here I am sending notification to given device token (APNS Push Notification) 
<?php

class Notification
{
    public function sendNotification($token,$count)
    {
        if(strlen($token)%16 == 0)
        {
            // set Device token
            $deviceToken = $token;
            $passphrase = 'xxxxx';
            $badge = $count;

            // Displays alert message here:
            $message = 'Hello! There.';

            $ctx = stream_context_create();
            stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
            stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

            // Open a connection to the APNS server
            $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
            if (!$fp)
                exit("Failed to connect: $err $errstr" . PHP_EOL);

            echo("Connected to APNS.");

            // Create the payload body
            $body['aps'] = array(
                                 'alert' => $message,
                                 'badge' => $badge,
                                 'sound' => 'default'
                                 );

            // Encode the payload as JSON
            $payload = json_encode($body);

            // Build the binary notification
            $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

            // Send it to the server
            $result = fwrite($fp, $msg, strlen($msg));

            if (!$result)
                echo("\n\nMessage not delivered.\n\n");
            else
                echo("\n\nMessage successfully delivered.\n\n");

            // Close the connection to the server
            fclose($fp);
        }
    }
}


?>

当这个类的Execution 将是completed 然后it will go back to file A 它将是continue execution after sending notification.

但在这里它会take time to send notification (around 3-5-7 seconds) 和当时user has to wait which is not a good idea

所以我想做的是send notification in Background process instead of main thread。所以用户不必等待。

Please note that I don't want to use Cron.

我发现exec/shell_exec/passthru command 可以帮助我。但是在这种情况下我使用了哪个命令out of these three commands

请指导我。任何帮助将不胜感激。

【问题讨论】:

    标签: php notifications apple-push-notifications background-process


    【解决方案1】:
    passthru("/usr/bin/php /path/to/yourFile.php >> /path/to/log_file.log 2>&1 &");
    

    这里有几件事很重要。

    首先:输入php二进制文件的完整路径,因为这个命令将在apache用户下运行,你可能不会在那个用户中设置像php这样的命令别名。

    第二点:注意命令字符串末尾的两件事:2&gt;&amp;1&amp;2&gt;&amp;1 用于将错误重定向到标准 IO。而最重要的是命令字符串末尾的&amp;,它告诉终端不要等待响应。

    【讨论】:

    • 谢谢。但是你说的 passthru 是什么意思?你想写 exec() 吗?
    • passthru() 是一个 PHP 函数,但它的存在理由是从命令中返回二进制数据,因此不适合您的用例。
    • @Clarence:为什么我不能使用 exec()?因为我看到只有在o/p是二进制数据的时候才使用passthru,对吗?
    • @Clarence : 请尽快回答我的问题。因为我急需。谢谢。
    • 您也可以使用 exec() 和末尾的 & 在后台运行命令。但是,您将无法控制产生了多少进程。
    【解决方案2】:

    这里有几个选项:

    • 您可以使用 pcntl_fork (http://php.net/manual/en/function.pcntl-fork.php) fork 一个单独的 PHP 进程
    • 您可以使用 cronjob 来检查您不想要的未发送修改(您没有提到 WHY,这就是我提到它的原因)
    • 您可以为此使用作业队列系统。迄今为止最好的解决方案,但需要一些时间才能开始。 Gearman 是我有经验的人,它就像一个魅力。

    【讨论】:

    • 我不想使用 Cron,因为我想立即发送通知而无需等待。
    • 看,有问题。您不想使用 cronjob,因为您不知道如何使其满足您的需求。您可以通过创建一个 cronjob 轻松解决您的目标,该 cronjob 在每次检查新消息之间休眠 X 秒/毫秒,然后在下一个 cronjob 启动脚本之前被杀死。有人可能会争辩说,守护进程会更好,但这通常会带来很多额外的陷阱,并且对于您的用例而言,就像设置适当的作业队列一样复杂,只是不太稳定和可扩展。
    • 请看,在我的应用程序(iOS)中,我正在为当前用户在某些情况下找到新的匹配项(来自数据库),并希望立即向新匹配项发送通知。因此,如果我要使用 Cron(如果 Cron 将在每 5 分钟后运行一次),那么我将不得不等待 5 分钟才能发送通知。这对于应用程序的标准来说是不可行的。
    • 您可以每 5 分钟运行一次脚本并在循环中 sleep(1) 并每秒检查一次..
    【解决方案3】:

    按照此处的说明在后台运行 PHP 脚本:

    php execute a background process

    它需要使用 shell_exec 从文件 A 调用脚本,因此您必须创建一个新文件来调用该代码。它还假设您使用的是 linux

    【讨论】:

    • 谢谢。但是如何在 shell_exec 命令中将参数作为参数传递(即我的问题中的$token,$count)?
    • 手册里有,之前已经回答过很多次了,例如:stackoverflow.com/questions/6763997/…
    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多