[php] PHP는 백그라운드 프로세스를 실행

사용자 조치에 따라 디렉토리 사본을 실행해야하지만 디렉토리가 상당히 크기 때문에 사용자가 사본을 완료하는 데 걸리는 시간을 인식하지 않고 그러한 조치를 수행 할 수 있기를 원합니다.

어떤 제안이라도 대단히 감사하겠습니다.



답변

이것이 Linux 컴퓨터에서 실행되고 있다고 가정하면 항상 다음과 같이 처리했습니다.

exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile));

명령을 실행하고 명령 $cmd출력을로 리디렉션 $outputfile하고 프로세스 ID를에 기록합니다 $pidfile.

이를 통해 프로세스가 수행중인 작업과 여전히 실행 중인지를 쉽게 모니터링 할 수 있습니다.

function isRunning($pid){
    try{
        $result = shell_exec(sprintf("ps %d", $pid));
        if( count(preg_split("/\n/", $result)) > 2){
            return true;
        }
    }catch(Exception $e){}

    return false;
}


답변

프로세스를 편리한 언어 (php / bash / perl / etc)로 서버 측 스크립트로 작성한 다음 PHP 스크립트의 프로세스 제어 기능에서 호출하십시오.

이 함수는 표준 io가 출력 스트림으로 사용되는지 여부를 감지하고 그렇다면 해당 반환 값을 설정합니다.

proc_close( proc_open( "./command --foo=1 &", array(), $foo ) );

“sleep 25s”를 명령으로 사용하여 명령 줄에서이를 빠르게 테스트했으며 매력처럼 작동했습니다.

( 답변은 여기에 있습니다 )


답변

이것을 명령에 추가하려고 할 수 있습니다

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

예.

shell_exec('service named reload >/dev/null 2>/dev/null &');


답변

Windows 에서이 기능을 테스트하기위한 매우 간단한 예를 추가하고 싶습니다.

다음 두 파일을 작성하여 웹 디렉토리에 저장하십시오.

foreground.php :

<?php

ini_set("display_errors",1);
error_reporting(E_ALL);

echo "<pre>loading page</pre>";

function run_background_process()
{
    file_put_contents("testprocesses.php","foreground start time = " . time() . "\n");
    echo "<pre>  foreground start time = " . time() . "</pre>";

    // output from the command must be redirected to a file or another output stream 
    // http://ca.php.net/manual/en/function.exec.php

    exec("php background.php > testoutput.php 2>&1 & echo $!", $output);

    echo "<pre>  foreground end time = " . time() . "</pre>";
    file_put_contents("testprocesses.php","foreground end time = " . time() . "\n", FILE_APPEND);
    return $output;
}

echo "<pre>calling run_background_process</pre>";

$output = run_background_process();

echo "<pre>output = "; print_r($output); echo "</pre>";
echo "<pre>end of page</pre>";
?>

background.php :

<?
file_put_contents("testprocesses.php","background start time = " . time() . "\n", FILE_APPEND);
sleep(10);
file_put_contents("testprocesses.php","background end time = " . time() . "\n", FILE_APPEND);
?>

위 파일을 작성한 디렉토리에 쓸 수있는 권한을 IUSR에 부여하십시오.

읽기 및 실행 C : \ Windows \ System32 \ cmd.exe에 IUSR 권한 부여

웹 브라우저에서 foreground.php를 누르십시오

출력 배열의 현재 타임 스탬프 및 로컬 리소스 번호를 사용하여 브라우저에 다음을 렌더링해야합니다.

loading page
calling run_background_process
  foreground start time = 1266003600
  foreground end time = 1266003600
output = Array
(
    [0] => 15010
)
end of page

위의 파일이 저장된 동일한 디렉토리에 testoutput.php가 표시되고 비어 있어야합니다.

위의 파일이 저장된 디렉토리와 동일한 디렉토리에 testprocesses.php가 표시되고 현재 타임 스탬프가 포함 된 다음 텍스트가 포함되어야합니다.

foreground start time = 1266003600
foreground end time = 1266003600
background start time = 1266003600
background end time = 1266003610


답변

PHP 페이지가 완료되기를 기다리지 않고 백그라운드에서 무언가를 수행해야하는 경우 wget 명령으로 “호출 된”다른 (백그라운드) PHP 스크립트를 사용할 수 있습니다. 이 배경 PHP 스크립트는 물론 시스템의 다른 PHP 스크립트와 마찬가지로 권한으로 실행됩니다.

다음은 gnuwin32 패키지의 wget을 사용하는 Windows의 예입니다.

훌륭한 배경 코드 (파일 test-proc-bg.php) …

sleep(5);   // some delay
file_put_contents('test.txt', date('Y-m-d/H:i:s.u')); // writes time in a file

포 그라운드 스크립트, 하나는 호출 …

$proc_command = "wget.exe http://localhost/test-proc-bg.php -q -O - -b";
$proc = popen($proc_command, "r");
pclose($proc);

이 기능이 제대로 작동하려면 popen / pclose를 사용해야합니다.

wget 옵션 :

-q    keeps wget quiet.
-O -  outputs to stdout.
-b    works on background


답변

다음은 PHP에서 백그라운드 프로세스를 시작하는 함수입니다. 마지막으로 다른 접근 방식과 매개 변수를 많이 읽고 테스트 한 후에 실제로 Windows에서도 작동하는 것을 만들었습니다.

function LaunchBackgroundProcess($command){
  // Run command Asynchroniously (in a separate thread)
  if(PHP_OS=='WINNT' || PHP_OS=='WIN32' || PHP_OS=='Windows'){
    // Windows
    $command = 'start "" '. $command;
  } else {
    // Linux/UNIX
    $command = $command .' /dev/null &';
  }
  $handle = popen($command, 'r');
  if($handle!==false){
    pclose($handle);
    return true;
  } else {
    return false;
  }
}

참고 1 : Windows에서는 /B다른 곳에서 제안한대로 매개 변수를 사용하지 마십시오 . 프로세스가 start명령 자체 와 동일한 콘솔 창을 실행하도록 하여 프로세스가 동 기적으로 처리되도록합니다. 별도의 스레드에서 프로세스를 비동기식으로 실행하려면을 사용하지 마십시오 /B.

참고 2 : start ""명령이 인용 된 경로 인 경우 뒤에 빈 큰 따옴표 가 필요합니다. start명령은 처음 인용 된 매개 변수를 창 제목으로 해석합니다.


답변

글쎄, 나는 조금 더 빠르고 사용하기 쉬운 버전을 발견했다.

shell_exec('screen -dmS $name_of_screen $command'); 

작동합니다.