source

PHP의 비동기 셸 Exec

lovecheck 2023. 1. 2. 22:41
반응형

PHP의 비동기 셸 Exec

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

여러 가지를 조사해 봤는데exec(),shell_exec(),pcntl_fork()기능 등은 있지만, 어느 것도 내가 원하는 것을 제공하지 않는 것 같습니다.(혹은, 만약 제공한다면, 어떻게 해야 할지 알 수 없습니다.)좋은 의견이라도 있나?

「출력에 개의치 않는다」라고 하는 경우는, 스크립트에의 execute를 호출할 수 없는가.&프로세스 배경에 대해 설명하겠습니다.

편집 - @AdamThe를 통합Hut이 이 투고에 코멘트를 달았습니다.이것을 콜에 추가할 수 있습니다.exec:

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

그러면 둘 다 리다이렉트 됩니다.stdio(처음>)와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

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

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

그러면 명령 프롬프트에서 명령어가 실행된 후 PID가 반환됩니다.PID는 0보다 큰 것을 체크하여 동작하고 있는지 확인할 수 있습니다.

이 질문도 비슷합니다.PHP에는 스레드 기능이 있습니까?

php-param-a-background-process에는 몇 가지 좋은 제안이 있습니다.제 것은 꽤 괜찮은 것 같습니다만, 저는 편견이 있습니다.

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

mycommand -someparam somevalue &

Windows 에서는, 「start」DOS 커맨드를 사용할 수 있습니다.

start mycommand -someparam somevalue

하는 것이 옳다

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

fork forks, 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();

이거 썼는데...

/** 
 * 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')★★★★★★★★★★★★★★★★★★」

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

Symfony 프로세스 구성 요소도 이 작업에 유용했습니다.

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에서 어떻게 동작하는지 확인하세요.

그게 나한테 정말 효과가 있다는 걸 알게 된 유일한 방법이었어

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

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

명명된 fifo를 사용합니다.

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

그런 다음 장시간 실행 작업을 시작할 때마다 새 행(트리거 파일에 비차단)을 작성하기만 하면 됩니다.

이 력음보다 .PIPE_BUF 싱글입니다.write()하고 fifo로 할 수 .$REPLY본에있있 있있있다다

큐를 사용하지 않으면 다음과 같이 사용할 수 있습니다.

    $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

반응형