Programing

PHP의 비동기 셸 실행

lottogame 2020. 5. 12. 07:57
반응형

PHP의 비동기 셸 실행


쉘 스크립트를 호출해야하지만 출력에 전혀 신경 쓰지 않는 PHP 스크립트가 있습니다. 셸 스크립트는 많은 SOAP 호출을 수행하며 완료 속도가 느리므로 응답을 기다리는 동안 PHP 요청 속도를 늦추고 싶지 않습니다. 실제로 PHP 요청은 쉘 프로세스를 종료하지 않고 종료 할 수 있어야합니다.

나는 여러 가지로 검토 한 결과 exec(), shell_exec(), pcntl_fork(), 등의 기능을하지만, 그들 중 누구도 정확히 내가 원하는 것을 제공하기 위해 보이지 않는다. (또는 그들이 그렇게한다면 방법이 명확하지 않습니다.) 어떤 제안?


"출력에 신경 쓰지 않으면" &프로세스의 백그라운드로 스크립트에 대한 exec를 호출 할 수 없습니까?

편집 -@ AdamTheHut 이이 게시물에 댓글을 달았을 때이를 호출에 추가 할 수 있습니다 exec.

" > /dev/null 2>/dev/null &"

그러면 stdio(first >) 및 stderr( 2>)가 /dev/null백그라운드로 리디렉션 되어 백그라운드에서 실행됩니다.

같은 일을하는 다른 방법이 있지만 가장 읽기 쉬운 방법입니다.


위의 이중 리디렉션에 대한 대안 :

" &> /dev/null &"

실제로 독립 프로세스를 시작하기 때문에 이것을 사용 했습니다 .

<?php
    `echo "the command"|at now`;
?>

모든 Windows 사용자에게 : 비동기 PHP 스크립트를 실행하는 좋은 방법을 찾았습니다 (실제로 거의 모든 것이 작동합니다).

popen () 및 pclose () 명령을 기반으로합니다. Windows와 Unix에서 모두 잘 작동합니다.

function execInBackground($cmd) {
    if (substr(php_uname(), 0, 7) == "Windows"){
        pclose(popen("start /B ". $cmd, "r")); 
    }
    else {
        exec($cmd . " > /dev/null &");  
    }
} 

원본 코드 : http://php.net/manual/en/function.exec.php#86329


Linux에서는 다음을 수행 할 수 있습니다.

$cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);

명령 프롬프트에서 명령을 실행 한 다음 PID를 반환하면> 0을 확인하여 작동하는지 확인할 수 있습니다.

이 질문은 비슷합니다 : PHP에는 스레딩이 있습니까?


php-execute-a-background-process 에는 좋은 제안이 있습니다. 내 것이 꽤 좋다고 생각하지만 편견이 있습니다. :)


Linux에서는 명령 끝에 앰퍼샌드를 추가하여 새로운 독립 스레드에서 프로세스를 시작할 수 있습니다.

mycommand -someparam somevalue &

Windows에서는 "start"DOS 명령을 사용할 수 있습니다

start mycommand -someparam somevalue

그것을하는 올바른 방법 (!)

  1. 포크()
  2. setsid ()
  3. execve ()

포크 포크, setsid는 현재 프로세스가 마스터 프로세스 (부모 없음)가되고 호출 프로세스가 호출 된 프로세스로 대체되도록 지시합니다. 부모는 자녀에게 영향을 미치지 않고 종료 할 수 있습니다.

 $pid=pcntl_fork();
 if($pid==0)
 {
   posix_setsid();
   pcntl_exec($cmd,$args,$_ENV);
   // child becomes the standalone detached process
 }

 // parent's stuff
 exit();

나는 이것을 사용했다 ...

/** 
 * Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.  
 * Relies on the PHP_PATH config constant.
 *
 * @param string $filename  file to execute
 * @param string $options   (optional) arguments to pass to file via the command line
 */ 
function asyncInclude($filename, $options = '') {
    exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &");
}

(여기서 유사하거나 유사한 PHP_PATH정의가 있습니다 define('PHP_PATH', '/opt/bin/php5'))

It passes in arguments via the command line. To read them in PHP, see argv.


The only way that I found that truly worked for me was:

shell_exec('./myscript.php | at now & disown')

I also found Symfony Process Component useful for this.

use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
// ... run process in background
$process->start();

// ... do other things

// ... if you need to wait
$process->wait();

// ... do things after the process has finished

See how it works in its GitHub repo.


Use a named fifo.

#!/bin/sh
mkfifo trigger
while true; do
    read < trigger
    long_running_task
done

Then whenever you want to start the long running task, simply write a newline (nonblocking to the trigger file.

As long as your input is smaller than PIPE_BUF and it's a single write() operation, you can write arguments into the fifo and have them show up as $REPLY in the script.


You can also run the PHP script as daemon or cronjob: #!/usr/bin/php -q


without use queue, you can use the proc_open() like this:

    $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("pipe", "w")    //here curaengine log all the info into stderror
    );
    $command = 'ping stackoverflow.com';
    $process = proc_open($command, $descriptorspec, $pipes);

참고URL : https://stackoverflow.com/questions/222414/asynchronous-shell-exec-in-php

반응형