programing

php는 백그라운드 프로세스를 실행합니다.

prostudy 2022. 9. 12. 11:04
반응형

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 등)로 프로세스를 서버측 스크립트로 작성하여 php 스크립트의 프로세스 제어 함수에서 호출합니다.

함수는 표준 io가 출력 스트림으로 사용되는지 여부를 감지하고, 표준 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에서 이 기능을 테스트하기 위한 간단한 예를 추가하고 싶습니다.

다음의 2개의 파일을 작성해, Web 디렉토리에 보존합니다.

포그라운드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>";
?>

배경.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\에 대한 IUSR 권한 부여시스템32\cmd실행

포그라운드를 치다.웹 브라우저의 php

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

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

테스트 출력이 표시됩니다.php는 위의 파일과 동일한 디렉토리에 저장되었으며, 비어 있어야 합니다.

테스트 프로세스가 표시됩니다.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의 예입니다.

예로서 백그라운드코드(file 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

음, 나는 조금 더 빠르고 사용하기 쉬운 버전을 찾았다.

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

그리고 그것은 동작한다.

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:에서는, 「1:」을 사용하지 ./B파라미터를 지정합니다. 명령어를 사용하면 에서 ""와 이 강제로 됩니다.start그 결과 프로세스가 동기화되어 처리됩니다.스레드로(하려면 (비동기적으로) 사용하지 ./B.

2: 【2】뒤의 빈start ""명령어가 따옴표로 둘러싸인 경로인 경우 필수입니다. start명령어는 첫 번째 따옴표로 묶인 파라미터를 창 제목으로 해석합니다.

별도의 프로세스를 수행하여 백그라운드에서 복사본을 실행할 수 있습니까?오랜만에 PHP를 했는데 pcntl-fork 함수가 유망해 보입니다.

프로그램을 백그라운드에서 실행하려면 이 기능을 사용합니다.크로스 플랫폼 및 완전 커스터마이즈 가능.

<?php
function startBackgroundProcess(
    $command,
    $stdin = null,
    $redirectStdout = null,
    $redirectStderr = null,
    $cwd = null,
    $env = null,
    $other_options = null
) {
    $descriptorspec = array(
        1 => is_string($redirectStdout) ? array('file', $redirectStdout, 'w') : array('pipe', 'w'),
        2 => is_string($redirectStderr) ? array('file', $redirectStderr, 'w') : array('pipe', 'w'),
    );
    if (is_string($stdin)) {
        $descriptorspec[0] = array('pipe', 'r');
    }
    $proc = proc_open($command, $descriptorspec, $pipes, $cwd, $env, $other_options);
    if (!is_resource($proc)) {
        throw new \Exception("Failed to start background process by command: $command");
    }
    if (is_string($stdin)) {
        fwrite($pipes[0], $stdin);
        fclose($pipes[0]);
    }
    if (!is_string($redirectStdout)) {
        fclose($pipes[1]);
    }
    if (!is_string($redirectStderr)) {
        fclose($pipes[2]);
    }
    return $proc;
}

명령어 시작 후 기본적으로 이 함수는 실행 중인 프로세스의 stdin 및 stdout을 닫습니다.$redirectStdout 인수 및 $redirectStderr 인수를 사용하여 프로세스 출력을 일부 파일로 리디렉션할 수 있습니다.

Windows の windows windows windows :
은 stdout/stderr로 리다이렉트 할 수 .nul하다

startBackgroundProcess('ping yandex.com', null, 'nul', 'nul');

단, 다음과 같이 할 수 있습니다.

startBackgroundProcess('ping yandex.com >nul 2>&1');

*nix 사용자용 주의사항:

1) 실제 PID를 취득하려면 exec shell 명령을 사용합니다.

$proc = startBackgroundProcess('exec ping yandex.com -c 15', null, '/dev/null', '/dev/null');
print_r(proc_get_status($proc));

2) 프로그램 입력에 데이터를 전달하려면 $stdin 인수를 사용합니다.

startBackgroundProcess('cat > input.txt', "Hello world!\n");

Resque와 같은 큐잉 시스템을 시도할 수 있습니다.그런 다음 "처리" 이미지를 사용하여 정보를 처리하고 매우 빠르게 반환하는 작업을 생성할 수 있습니다.이 방법으로는 언제 끝날지 알 수 없습니다.

이 솔루션은 사용자의 요구를 처리할 수 있도록 프론트 머신이 무거운 작업을 수행하지 않도록 하는 대규모 애플리케이션을 대상으로 합니다.따라서 파일이나 폴더와 같은 물리적 데이터와 함께 작동하거나 작동하지 않을 수 있지만, 보다 복잡한 논리 또는 기타 비동기 작업(즉, 새로운 등록 메일)을 처리하기 위해서는 매우 편리하고 확장성이 뛰어납니다.

Windows 와 Linux 의 양쪽 모두에 유효한 솔루션.자세한 내용은 My github 페이지를 참조하십시오.

function run_process($cmd,$outputFile = '/dev/null', $append = false){
                    $pid=0;
                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
                        $cmd = 'wmic process call create "'.$cmd.'" | find "ProcessId"';
                        $handle = popen("start /B ". $cmd, "r");
                        $read = fread($handle, 200); //Read the output 
                        $pid=substr($read,strpos($read,'=')+1);
                        $pid=substr($pid,0,strpos($pid,';') );
                        $pid = (int)$pid;
                        pclose($handle); //Close
                }else{
                    $pid = (int)shell_exec(sprintf('%s %s %s 2>&1 & echo $!', $cmd, ($append) ? '>>' : '>', $outputFile));
                }
                    return $pid;
            }
            function is_process_running($pid){
                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
                        //tasklist /FI "PID eq 6480"
                    $result = shell_exec('tasklist /FI "PID eq '.$pid.'"' );
                    if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
                        return true;
                    }
                }else{
                    $result = shell_exec(sprintf('ps %d 2>&1', $pid));
                    if (count(preg_split("/\n/", $result)) > 2 && !preg_match('/ERROR: Process ID out of range/', $result)) {
                        return true;
                    }
                }
                return false;
            }
            function stop_process($pid){
                    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
                            $result = shell_exec('taskkill /PID '.$pid );
                        if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
                            return true;
                        }
                    }else{
                            $result = shell_exec(sprintf('kill %d 2>&1', $pid));
                        if (!preg_match('/No such process/', $result)) {
                            return true;
                        }
                    }
            }

답변 덕분에 백그라운드 프로세스를 실행하기 위한 완벽한 도구는 Symfony Process Component가 될 수 있습니다.Symfony Process Component는 다음과 같습니다.Symfony Process Component는 다음과 같습니다.proc_*기능은 있지만 훨씬 사용하기 편합니다.상세한 것에 대하여는, 메뉴얼을 참조해 주세요.

백그라운드 프로세스를 시작하는 대신 트리거 파일을 만들고 cron이나 autosys와 같은 스케줄러에서 트리거 파일을 검색하고 실행하는 스크립트를 정기적으로 실행하도록 하는 것은 어떨까요?트리거에는 명령이나 raw 명령어가 포함될 수 있습니다(단, 셸 스크립트로 하는 것이 좋습니다).

PHP 를 사용하고 있는 경우는, pcntl_fork 를 사용해 보다 간단하게 실시할 수 있습니다.

http://www.php.net/manual/en/function.pcntl-fork.php

많이 사용하고 있습니다.fast_cgi_finish_request()

closure 및 register_shutdown_function()과 조합하여 사용합니다.

$message ='job executed';
$backgroundJob = function() use ($message) {
     //do some work here
    echo $message;
}

그런 다음 종료 전에 실행할 이 폐쇄를 등록합니다.

register_shutdown_function($backgroundJob);

마지막으로 응답이 클라이언트에 전송되면 클라이언트에 대한 연결을 닫고 PHP 프로세스 작업을 계속할 수 있습니다.

fast_cgi_finish_request();

종료는 fast_cgi_finish_request 후에 실행됩니다.

$message는 언제든지 표시되지 않습니다.또한 원하는 만큼 클로징을 등록할 수 있지만 스크립트 실행 시간에 유의하십시오.이것은 PHP가 Fast CGI 모듈로 동작하고 있는 경우에만 동작합니다(맞습니까?).

PHP를 통해 백그라운드 프로세스를 실행하는 경우 명령어의 출력을 다음 주소로 파이핑합니다./dev/null추가하다&명령어의 마지막까지를 클릭합니다.

exec("bg_process > /dev/null &");

이 기능을 사용할 수 없는 것에 주의해 주십시오.$output파라미터exec()그렇지 않으면 PHP가 중단됩니다(아마 프로세스가 완료될 때까지).

PHP 스크립팅은 언어를 개발하는 다른 데스크톱 애플리케이션과 다릅니다.데스크톱 애플리케이션 언어에서는 백그라운드 프로세스를 실행하도록 데몬 스레드를 설정할 수 있지만 PHP에서는 사용자가 페이지를 요청할 때 프로세스가 발생합니다.그러나 php 스크립트가 실행되는 서버의 cron 작업 기능을 사용하여 백그라운드 작업을 설정할 수 있습니다.

Windows 를 사용하고 있는 유저의 경우는, 다음을 봐 주세요.

참고 자료: http://php.net/manual/en/function.exec.php#43917

저도 스크립트를 계속 실행하는 동안 Windows 백그라운드에서 실행할 프로그램을 얻는 데 어려움을 겪었습니다.다른 솔루션과 달리 이 방법을 사용하면 최소화, 최대화 또는 창 없이 모든 프로그램을 시작할 수 있습니다. llbra@phpbrasil의 솔루션은 작동하지만 작업을 숨기고 싶을 때 원하지 않는 창을 바탕화면에 만들 수 있습니다.

메모장을 기동합니다.백그라운드에서 exe 최소화:

<?php 
$WshShell = new COM("WScript.Shell"); 
$oExec = $WshShell->Run("notepad.exe", 7, false); 
?> 

백그라운드에서 보이지 않는 셸 명령어를 시작합니다.

<?php 
$WshShell = new COM("WScript.Shell"); 
$oExec = $WshShell->Run("cmd /C dir /S %windir%", 0, false); 
?> 

스크립트를 계속하기 전에 MSPaint를 최대화하고 닫을 때까지 기다립니다.

<?php 
$WshShell = new COM("WScript.Shell"); 
$oExec = $WshShell->Run("mspaint.exe", 3, true); 
?> 

Run() 메서드의 자세한 내용은http://http://msdn.microsoft.com/library/en-us/script56/html/wsMthRun.asp 를 참조해 주세요.

편집된 URL:

위의 링크는 존재하지 않으므로 대신 https://technet.microsoft.com/en-us/library/ee156605.aspx으로 이동합니다.

오래된 질문에 대한 새로운 대답입니다.라이브러리를 사용하면 다음 코드는 백그라운드 작업을 수행하기 위해 비동기/병렬 PHPThread를 생성합니다.

  • pcntl, posix 및 소켓 확장이 필요합니다.
  • CLI 모드용으로 설계/테스트 완료.

EZ 코드 샘플:

 function threadproc($thread, $param) {
 
    echo "\tI'm a PHPThread.  In this example, I was given only one parameter: \"". print_r($param, true) ."\" to work with, but I can accept as many as you'd like!\n";
 
    for ($i = 0; $i < 10; $i++) {
        usleep(1000000);
        echo "\tPHPThread working, very busy...\n";
    }
 
    return "I'm a return value!";
}
 

$thread_id = phpthread_create($thread, array(), "threadproc", null, array("123456"));
 
echo "I'm the main thread doing very important work!\n";
 
for ($n = 0; $n < 5; $n++) {
    usleep(1000000);
    echo "Main thread...working!\n";
}
 
echo "\nMain thread done working.  Waiting on our PHPThread...\n";
 
phpthread_join($thread_id, $retval);
 
echo "\n\nOur PHPThread returned: " . print_r($retval, true) . "!\n";

PHP 공식 문서(php.net)에서 확인

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

100년 된 게시물인 건 알지만, 어쨌든 누군가에게 도움이 될 것 같아서요.다음과 같이 백그라운드에서 실행할 필요가 있는 URL을 가리키는 보이지 않는 이미지를 페이지 어딘가에 배치할 수 있습니다.

<img src="run-in-background.php" border="0" alt="" width="1" height="1" />

언급URL : https://stackoverflow.com/questions/45953/php-execute-a-background-process

반응형