【问题标题】:Symfony execution of long running scriptSymfony 执行长时间运行的脚本
【发布时间】:2015-04-20 13:38:09
【问题描述】:

我正在使用 Symfony2,我想运行一个用 C++ 编写的长脚本(例如 60 分钟)。

现在我通过shell_exec()

$pid = shell_exec('nohup my/program/written/in/c++.out some arguments > /dev/null 2>/dev/null & echo $!');

如果我不断刷新页面,脚本运行良好,但如果我去 AFK,脚本将被 PHP 服务器进程 (/usr/bin/php-cgi) 终止。

有没有办法将 C++ 程序与 PHP 服务器进程隔离开来?使用 nohup 进程的 ppid = 1,所以它应该被隔离,但事实并非如此。

【问题讨论】:

标签: php c++ symfony process symfony-process


【解决方案1】:

您可以查看 Symfony 进程组件:http://symfony.com/doc/current/components/process.html

$process = new Process('nohup my/program/written/in/c++.out some arguments');
$process->run();

您将能够运行您的流程。

【讨论】:

  • 但这要等到过程完成。我对吗?它不适合长时间运行的进程。
  • @H.W.您可以使用$process->start(); 在后台运行,但是如果脚本结束(或者更准确地说,如果$process destructor is called),那么进程将被终止。如果您的脚本肯定必须在进程完成之前退出,请使用nohup <your command>(在 linux 上)之类的东西。您仍然必须确保$process 没有被垃圾收集,因此请将其安全地存放在某个地方。 ;)
【解决方案2】:

您可以创建 symfony2 控制台命令“myapp:my-command-name”来运行您的 c++ 命令

class MyStandaloneCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this->setName('myapp:my-command-name')
            ->setDescription('Will run standalone c++')
            ->addArgument('arg1', InputArgument::REQUIRED, 'Some arg');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {   
        $arg1 = $input->getArgument('arg1');
        $result = shell_exec('nohup my/program/written/in/c++.out '.$arg1.' 2>&1');

        $output->writeln('My cool command is started');

        return true;
    }

}

然后使用JMSJobBundle
http://jmsyst.com/bundles/JMSJobQueueBundle/master/installation

您可以在其中创建控制台命令队列,例如:

class HomeController ... {
 // inject service here
 private $cronJobHelper;
 // inject EM here
 private $em;
public function indexAction(){

 $job = $this->cronJobHelper->createConsoleJob('myapp:my-command-name', $event->getId(), 10);
        $this->em->persist($job);
 $this->em->persist($job);
$this->em->flush();
}


use JMS\JobQueueBundle\Entity\Job;

class CronJobHelper{

    public function createConsoleJob($consoleFunction, $params, $delayToRunInSeconds, $priority = Job::PRIORITY_DEFAULT, $queue = Job::DEFAULT_QUEUE){
        if(!is_array($params)){
            $params = [$params];
        }

        $job = new Job($consoleFunction, $params, 1, $queue, $priority);
        $date = $job->getExecuteAfter();
        $date = new \DateTime('now');
        $date->setTimezone(new \DateTimeZone('UTC')); //just in case
        $date->add(new \DateInterval('PT'.$delayToRunInSeconds.'S')); 
        $job->setExecuteAfter($date);

        return $job;
    }
}

【讨论】:

  • 很酷,但使用symfony/process 而不是shell_exec() 会更酷。 ;) 该函数的一个已知“特性”是执行程序的 STDOUT 和 STDERR 被重定向到拥有的 PHP 进程,这是大多数人不想要的。
猜你喜欢
  • 1970-01-01
  • 2019-02-12
  • 1970-01-01
  • 1970-01-01
  • 2018-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-02
相关资源
最近更新 更多