在后台运行PHP脚本(不使用Cron)

在后台运行PHP脚本(不使用Cron),php,notifications,apple-push-notifications,background-process,Php,Notifications,Apple Push Notifications,Background Process,我想在某些情况下在后台运行以下代码: 文件A: // ------------------- Some Code Before Following ----------------------- // send notification to given device token $notification = new Notification(); $notification->sendNotification($token,$count);

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

文件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);
        }
    }
}


?>
//这里我向给定的设备令牌发送通知(APNS推送通知)
当该类的
执行
完成
后,
将返回到文件A
,并在发送通知后继续执行。

但在这里,发送通知需要时间(大约3-5-7秒),而在这段时间内,用户必须等待,这不是一个好主意

所以我想做的是
在后台进程中而不是在主线程中发送通知
,这样用户就不必不必要地等待了

请注意,我不想使用Cron。

我发现
exec/shell\u exec/passthru命令可以帮助我。但是在这种情况下,在这三个命令中,我使用了哪个命令


请在这方面指导我。任何帮助都将不胜感激。

这里有几个选项:

  • 您可以使用pcntl_fork()派生一个单独的PHP进程
  • 您可以使用cronjob来检查您不想要的未发送的修改(您没有提到原因,这就是我提到它的原因)
  • 您可以使用作业队列系统。到目前为止,这是最好的解决方案,但需要一些时间才能开始。Gearman是一个我有经验的人,它很有魅力

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

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

passthru("/usr/bin/php /path/to/yourFile.php >> /path/to/log_file.log 2>&1 &");
这里有几件事很重要

首先:将完整路径放在php二进制文件中,因为此命令将在apache用户下运行,并且您可能不会在该用户中设置类似php的命令别名


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

我不想使用Cron,因为我想在不等待的情况下立即发送通知。看,这就是问题所在。您不想使用cronjob,因为您不知道如何让它满足您的需求。通过创建一个cronjob,在每次检查新消息之间休眠X秒/millseconds,然后在下一个cronjob启动脚本之前将其杀死,可以很容易地解决您的目标。有人可能会说守护进程会更好,但这通常会带来很多额外的陷阱,对于您的用例来说,就像设置适当的作业队列一样复杂,只是稳定性和可扩展性较差。请看,在我的应用程序(iOS)中,我正在(从数据库)查找新的匹配项对于当前用户,在某些情况下,希望立即向新的匹配项发送通知。因此,如果我将使用Cron(如果Cron将每5分钟运行一次),那么我将不得不等待5分钟来发送通知。对于应用程序的条件来说,这是不可行的。您可以每5分钟运行一次脚本,然后在循环中休眠(1),并每秒检查一次。谢谢。但你所说的穿越是什么意思?是否要编写exec()?passthru()是一个PHP函数,但它的目的是从命令返回二进制数据,因此没有适合您的用例。@Clarence:为什么我不能使用exec()?因为我看到只有当o/p是二进制数据时才使用passthru。对吗?@Clarence:请尽快回答我的问题。因为我急需它。谢谢。你可以使用exec()和结尾处的&在后台运行该命令。不过,您无法控制生成了多少进程。谢谢。但我如何才能在shell_exec命令(即我的问题中的$token、$count)中将参数作为参数传递?这在手册中有介绍,以前已经回答过很多次,例如: