복붙노트

PHP의 비동기 쉘 exec

PHP

PHP의 비동기 쉘 exec

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

다양한 exec (), shell_exec (), pcntl_fork () 등의 함수를 살펴 보았지만 그 중 아무 것도 내가 원하는 것을 정확하게 제공하지 않는 것 같습니다. (또는, 그들이하는 경우, 어떻게 나에게 명확하지 않다.) 어떤 제안?

해결법

  1. ==============================

    1.

    "출력에 신경 쓰지 않는다면"프로세스를 배경으로 &로 스크립트의 exec를 호출 할 수 없습니까?

    EDIT - @AdamTheHut이이 게시물에 댓글을 달았다면, 이것을 exec에 대한 호출에 추가 할 수 있습니다.

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

    그것은 stdio (first>)와 stderr (2>) 모두를 / dev / null로 리다이렉션하고 백그라운드에서 실행합니다.

    똑같은 일을하는 다른 방법이 있지만, 이것은 읽는 것이 가장 간단합니다.

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

    " &> /dev/null &"
    
  2. ==============================

    2.

    나는 이것을 위해, 독립적 인 과정을 정말로 시작하기 때문에 이것을 사용했습니다.

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

    3.

    리눅스에서는 다음을 할 수 있습니다 :

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

    이렇게하면 명령 프롬프트에서 명령을 실행 한 다음 PID가 반환되어> 0인지 확인하여 제대로 작동하는지 확인할 수 있습니다.

    이 질문은 유사합니다 : PHP는 스레딩이 있습니까?

  4. ==============================

    4.

    모든 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

  5. ==============================

    5.

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

  6. ==============================

    6.

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

    mycommand -someparam somevalue &
    

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

    start mycommand -someparam somevalue
    
  7. ==============================

    7.

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

    fork 포크, setsid는 현재 프로세스가 마스터 프로세스가되고 부모 프로세스가 아니라는 것을 알려주고 execve는 호출 프로세스가 호출 된 프로세스로 대체되도록 지시합니다. 부모는 자녀에게 영향을주지 않고 종료 할 수 있습니다.

     $pid=pcntl_fork();
     if($pid==0)
     {
       posix_setsid();
       pcntl_exec($cmd,$args,$_ENV);
       // child becomes the standalone detached process
     }
    
     // parent's stuff
     exit();
    
  8. ==============================

    8.

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

    /** 
     * 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') 또는 그와 유사하게 정의 된 const 임)

    인수는 명령 행을 통해 전달됩니다. PHP에서 이들을 읽으려면 argv를 참조하십시오.

  9. ==============================

    9.

    내가 진정으로 나를 위해 일한다는 것을 알게 된 유일한 방법은 다음과 같습니다.

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

    10.

    Symfony Process Component도 유용합니다.

    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
    

    그것의 GitHub repo에서 어떻게 작동하는지보십시오.

  11. ==============================

    11.

    명명 된 FIFO를 사용하십시오.

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

    그런 다음 장기 실행 작업을 시작하려면 항상 개행 문자 (트리거 파일에 비 차단)를 작성하십시오.

    입력이 PIPE_BUF보다 작고 단일 write () 연산 인 경우, FIFO에 인수를 쓰고 스크립트에서 $ REPLY로 표시되게 할 수 있습니다.

  12. ==============================

    12.

    PHP 스크립트를 데몬이나 cronjob으로 실행할 수도 있습니다 : #! / usr / bin / php -q

  13. ==============================

    13.

    사용 큐를 사용하지 않고 다음과 같이 proc_open ()을 사용할 수 있습니다.

        $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);
    
  14. from https://stackoverflow.com/questions/222414/asynchronous-shell-exec-in-php by cc-by-sa and MIT lisence