복붙노트

양식을 제출 한 후 백그라운드에서 PHP 스크립트를 실행하려면 어떻게해야합니까?

PHP

양식을 제출 한 후 백그라운드에서 PHP 스크립트를 실행하려면 어떻게해야합니까?

문제 제출 된 정보를 제출하고 알림 웹 사이트에 표시하기 위해 데이터베이스에 삽입하는 기본 코드를 실행하는 양식이 있습니다. 또한 전자 메일 및 SMS 메시지를 통해 이러한 알림을 수신하도록 등록한 사람들의 목록이 있습니다. 이 목록은 그 순간과 같이 사소한 것이지만 (약 150 회만 누름) 구독자 전체 테이블을 순환하고 150 개 이상의 전자 메일을 보내려면 1 분 이상 소요됩니다. (이메일은 대량 이메일 정책 때문에 이메일 서버의 시스템 관리자가 요청한대로 개별적으로 전송됩니다.)

이 시간 동안 알림을 게시 한 개인은 알림이 게시되고 있다는 긍정적 인 강조없이 거의 1 분 동안 양식의 마지막 페이지에 앉습니다. 이로 인해 다른 잠재적 인 문제가 발생할 수 있습니다. 가능한 모든 해결책에 이상이없는 것 같습니다.

(가능한 해결책 필자는 스크립트의 "전자 메일"부분을 알림을 게시 한 후에 호출 할 수있는 별도의 파일로 분할하려고합니다. 나는 원래 통보가 성공적으로 게시 된 후에 이것을 확인 페이지에 넣을 생각이었다. 그러나 사용자는이 스크립트가 실행 중임을 알지 못하며 어떤 예외도 분명하지 않습니다. 이 스크립트는 실패 할 수 없습니다.

그러나이 스크립트를 백그라운드 프로세스로 실행할 수 있다면 어떨까요? 그래서, 내 질문은 : 백그라운드 서비스로 트리거하고 양식 수준에서 사용자가 수행 한 것과 완전히 독립적으로 실행되도록 PHP 스크립트를 실행하려면 어떻게해야합니까?

편집 :이 cron'ed 수 없습니다. 양식이 제출되는 즉시 실행해야합니다. 우선 순위가 높은 알림입니다. 또한 서버를 실행하는 시스템 관리자는 cron이 5 분 이상 실행되는 것을 허용하지 않습니다.

해결법

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

    1.exec와 shell_exec에 대한 실험을하면서 완벽하게 작동하는 솔루션을 발견했습니다! 나는 (또는하지 않는) 모든 알림 프로세스를 기록 할 수 있도록 shell_exec를 사용하기로 결정했습니다. (shell_exec은 문자열을 반환하고 exec를 사용하여 출력을 변수에 할당 한 다음 쓰기 파일을 여는 것보다 쉽습니다.)

    exec와 shell_exec에 대한 실험을하면서 완벽하게 작동하는 솔루션을 발견했습니다! 나는 (또는하지 않는) 모든 알림 프로세스를 기록 할 수 있도록 shell_exec를 사용하기로 결정했습니다. (shell_exec은 문자열을 반환하고 exec를 사용하여 출력을 변수에 할당 한 다음 쓰기 파일을 여는 것보다 쉽습니다.)

    전자 메일 스크립트를 호출하는 데 다음 줄을 사용하고 있습니다.

    shell_exec("/path/to/php /path/to/send_notifications.php '".$post_id."' 'alert' >> /path/to/alert_log/paging.log &");
    

    명령 끝 부분에 @를주의하는 것이 중요합니다 (@netcoder가 지적한대로). 이 UNIX 명령은 백그라운드에서 프로세스를 실행합니다.

    스크립트 경로 다음에 작은 따옴표로 묶인 추가 변수는 스크립트 내에서 호출 할 수있는 $ _SERVER [ 'argv'] 변수로 설정됩니다.

    그런 다음 전자 메일 스크립트는 >>를 사용하여 내 로그 파일로 출력하고 다음과 같이 출력합니다.

    [2011-01-07 11:01:26] Alert Notifications Sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 38.71 seconds)
    [2011-01-07 11:01:34] CRITICAL ERROR: Alert Notifications NOT sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 23.12 seconds)
    
  2. ==============================

    2.Linux / Unix 서버에서는 proc_open을 사용하여 백그라운드에서 작업을 실행할 수 있습니다.

    Linux / Unix 서버에서는 proc_open을 사용하여 백그라운드에서 작업을 실행할 수 있습니다.

    $descriptorspec = array(
       array('pipe', 'r'),               // stdin
       array('file', 'myfile.txt', 'a'), // stdout
       array('pipe', 'w'),               // stderr
    );
    
    $proc = proc_open('php email_script.php &', $descriptorspec, $pipes);
    

    & 여기서 중요한 비트. 원본 스크립트가 종료 된 경우에도 스크립트가 계속됩니다.

  3. ==============================

    3.PHP exec ( "php script.php")가 할 수 있습니다.

    PHP exec ( "php script.php")가 할 수 있습니다.

    매뉴얼에서 :

    따라서 출력을 로그 파일로 리디렉션하면 (어쨌든 좋은 아이디어입니다) 호출 스크립트가 중단되지 않고 전자 메일 스크립트가 bg에서 실행됩니다.

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

    4.그리고 스크립트에서 HTTP 요청을 만들고 응답을 무시하는 이유는 무엇입니까?

    그리고 스크립트에서 HTTP 요청을 만들고 응답을 무시하는 이유는 무엇입니까?

    http://php.net/manual/en/function.httprequest-send.php

    스크립트에 대한 요청을하면 웹 서버에 전화를 걸어 백그라운드에서 실행하고 스크립트가 실행 중임을 사용자에게 알리는 메시지를 (기본 스크립트에서) 표시 할 수 있습니다.

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

    5.이건 어때?

    이건 어때?

    이 두 번째 PHP 스크립트는 cron으로 실행되도록 설정해야합니다.

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

    6.내가 쉽게 당신이 이것을 할 수 없다는 것을 안다. (포크 임원 등 (윈도우에서는 작동하지 않는다)) 아약스에서 폼을 게시하는 브라우저의 배경을 사용하여 접근법을 바꿀 수있다. 기다릴 시간이 없다. 이것은 오랫동안 정교함을해야만하는 경우에도 도움이 될 수 있습니다. 메일을 보내는 것에 관해서는 항상 스풀러를 사용하는 것이 좋으며 요청을 받아들이고 실제 MTA에 스풀링하는 로컬 및 빠른 smtp 서버 일 수도 있고 큐에 스풀링하는 cron을 사용하는 것보다 DB에 모두 넣을 수도 있습니다. cron은 스풀러를 외부 URL로 호출하는 다른 시스템에있을 수 있습니다.

    내가 쉽게 당신이 이것을 할 수 없다는 것을 안다. (포크 임원 등 (윈도우에서는 작동하지 않는다)) 아약스에서 폼을 게시하는 브라우저의 배경을 사용하여 접근법을 바꿀 수있다. 기다릴 시간이 없다. 이것은 오랫동안 정교함을해야만하는 경우에도 도움이 될 수 있습니다. 메일을 보내는 것에 관해서는 항상 스풀러를 사용하는 것이 좋으며 요청을 받아들이고 실제 MTA에 스풀링하는 로컬 및 빠른 smtp 서버 일 수도 있고 큐에 스풀링하는 cron을 사용하는 것보다 DB에 모두 넣을 수도 있습니다. cron은 스풀러를 외부 URL로 호출하는 다른 시스템에있을 수 있습니다.

    * * * * * wget -O /dev/null http://www.example.com/spooler.php
    
  7. ==============================

    7.백그라운드에서 PHP 스크립트를 실행하는 더 간단한 방법은

    백그라운드에서 PHP 스크립트를 실행하는 더 간단한 방법은

    php script.php >/dev/null &
    

    스크립트는 백그라운드에서 실행되며 페이지는 작업 페이지에 더 빨리 도달합니다.

  8. ==============================

    8.백그라운드 크론 작업은 좋은 생각 인 것 같습니다.

    백그라운드 크론 작업은 좋은 생각 인 것 같습니다.

    스크립트를 cron으로 실행하려면 시스템에 ssh 액세스가 필요합니다.

    그것을 실행하기 위해 $ php scriptname.php.

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

    9.ssh를 통해 서버에 액세스 할 수 있고 자신 만의 스크립트를 실행할 수 있다면 PHP를 사용하여 간단한 FIFO 서버를 만들 수 있습니다 (포크에 대한 posix 지원을 사용하여 PHP를 다시 컴파일해야하지만).

    ssh를 통해 서버에 액세스 할 수 있고 자신 만의 스크립트를 실행할 수 있다면 PHP를 사용하여 간단한 FIFO 서버를 만들 수 있습니다 (포크에 대한 posix 지원을 사용하여 PHP를 다시 컴파일해야하지만).

    서버는 실제로 무엇이든 쓸 수 있습니다. 아마 파이썬으로 쉽게 할 수 있습니다.

    또는 가장 간단한 솔루션은 HttpRequest를 보내고 반환 데이터를 읽지 않지만 서버는 처리를 완료하기 전에 스크립트를 파괴 할 수 있습니다.

    예제 서버 :

    <?php
    define('FIFO_PATH', '/home/user/input.queue');
    define('FORK_COUNT', 10);
    
    if(file_exists(FIFO_PATH)) {
        die(FIFO_PATH . ' exists, please delete it and try again.' . "\n");
    }
    
    if(!file_exists(FIFO_PATH) && !posix_mkfifo(FIFO_PATH, 0666)){
        die('Couldn\'t create the listening fifo.' . "\n");
    }
    
    $pids = array();
    $fp = fopen(FIFO_PATH, 'r+');
    for($i = 0; $i < FORK_COUNT; ++$i) {
        $pids[$i] = pcntl_fork();
        if(!$pids[$i]) {
            echo "process(" . posix_getpid() . ", id=$i)\n";
            while(true) {
                $line = chop(fgets($fp));
                if($line == 'quit' || $line === false) break;
                echo "processing (" . posix_getpid() . ", id=$i) :: $line\n";
            //  $data = json_decode($line);
            //  processData($data);
            }
            exit();
        }
    }
    fclose($fp);
    foreach($pids as $pid){
        pcntl_waitpid($pid, $status);
    }
    unlink(FIFO_PATH);
    ?>
    

    클라이언트 예 :

    <?php
    define('FIFO_PATH', '/home/user/input.queue');
    if(!file_exists(FIFO_PATH)) {
        die(FIFO_PATH . ' doesn\'t exist, please make sure the fifo server is running.' . "\n");
    }
    
    function postToQueue($data) {
        $fp = fopen(FIFO_PATH, 'w+');
        stream_set_blocking($fp, false); //don't block
        $data = json_encode($data) . "\n";
        if(fwrite($fp, $data) != strlen($data)) {
            echo "Couldn't the server might be dead or there's a bug somewhere\n";
        }
        fclose($fp);
    }
    $i = 1000;
    while(--$i) {
        postToQueue(array('xx'=>21, 'yy' => array(1,2,3)));
    }
    ?>
    
  10. ==============================

    10.* nix 플랫폼에서 실행된다고 가정하면 cron과 PHP 실행 파일을 사용하십시오.

    * nix 플랫폼에서 실행된다고 가정하면 cron과 PHP 실행 파일을 사용하십시오.

    편집하다:

    이미 "php없이 cron"을 실행하는 것에 대해 많은 질문이 있습니다. 여기에 하나 있습니다 :

    CRON을 사용하지 않고 스크립트 예약

    즉, 위의 exec () 대답은 매우 유망한 소리입니다. :)

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

    11.Windows 사용자 인 경우 proc_open 또는 popen을 조사하십시오.

    Windows 사용자 인 경우 proc_open 또는 popen을 조사하십시오.

    그러나 cpanel을 실행하는 동일한 서버 "Linux"를 사용하는 경우 올바른 방법입니다.

    #!/usr/bin/php 
    <?php
    $pid = shell_exec("nohup nice php -f            
    'path/to/your/script.php' /dev/null 2>&1 & echo $!");
    While(exec("ps $pid"))
    { //you can also have a streamer here like fprintf,        
     // or fgets
    }
    ?>
    

    fork () 나 curl을 사용하지 마십시오. 처리 할 수 ​​없다고 의심되면 서버를 악용하는 것과 같습니다.

    마지막으로 위에서 호출 한 script.php 파일에서 다음을 기록하십시오.

    <?php
    ignore_user_abort(TRUE);
    set_time_limit(0);
    ob_start();
    // <-- really optional but this is pure php
    
    //Code to be tested on background
    
    ob_flush(); flush(); 
    //this two do the output process if you need some.        
    //then to make all the logic possible
    
    
    str_repeat(" ",1500); 
    //.for progress bars or loading images
    
    sleep(2); //standard limit
    
    ?>
    
  12. ==============================

    12.모든 대답 중에서, 누구도 브라우저에서 남아있는 모든 출력을 플러시하고 Fastcgi 세션과 HTTP 연결을 닫는 동시에 스크립트를 백그라운드에서 실행하도록하는 매우 쉬운 fastcgi_finish_request 함수를 고려하지 않았습니다.

    모든 대답 중에서, 누구도 브라우저에서 남아있는 모든 출력을 플러시하고 Fastcgi 세션과 HTTP 연결을 닫는 동시에 스크립트를 백그라운드에서 실행하도록하는 매우 쉬운 fastcgi_finish_request 함수를 고려하지 않았습니다.

    예 :

    <?php
    header('Content-Type: application/json');
    echo json_encode(['ok' => true]);
    fastcgi_finish_request(); // The user is now disconnected from the script
    
    // do stuff with received data,
    
  13. ==============================

    13.제 경우에는 3 개의 매개 변수가 있습니다. 그 중 하나는 문자열 (mensaje)입니다.

    제 경우에는 3 개의 매개 변수가 있습니다. 그 중 하나는 문자열 (mensaje)입니다.

    exec("C:\wamp\bin\php\php5.5.12\php.exe C:/test/N/trunk/api/v1/Process.php $idTest2 $idTest3 \"$mensaje\" >> c:/log.log &");
    

    내 Process.php에서 나는이 코드를 가진다 :

    if (!isset($argv[1]) || !isset($argv[2]) || !isset($argv[3]))
    {   
        die("Error.");
    } 
    
    $idCurso = $argv[1];
    $idDestino = $argv[2];
    $mensaje = $argv[3];
    
  14. ==============================

    14.배경 작업자를 위해이 기술을 사용하면 모든 페이지가 비동기로 각 페이지 응답을 기다리지 않고 한 번에 독립적으로 실행되는 것처럼 많은 페이지를 호출하는 데 도움이됩니다.

    배경 작업자를 위해이 기술을 사용하면 모든 페이지가 비동기로 각 페이지 응답을 기다리지 않고 한 번에 독립적으로 실행되는 것처럼 많은 페이지를 호출하는 데 도움이됩니다.

    form_action_page.php

         <?php
    
        post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue");
        //post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue2");
        //post_async("http://localhost/projectname/otherpage.php", "Keywordname=anyValue");
        //call as many as pages you like all pages will run at once //independently without waiting for each page response as asynchronous.
    
      //your form db insertion or other code goes here do what ever you want //above code will work as background job this line will direct hit before //above lines response     
                    ?>
                    <?php
    
                    /*
                     * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
                     *  
                     */
                    function post_async($url,$params)
                    {
    
                        $post_string = $params;
    
                        $parts=parse_url($url);
    
                        $fp = fsockopen($parts['host'],
                            isset($parts['port'])?$parts['port']:80,
                            $errno, $errstr, 30);
    
                        $out = "GET ".$parts['path']."?$post_string"." HTTP/1.1\r\n";//you can use POST instead of GET if you like
                        $out.= "Host: ".$parts['host']."\r\n";
                        $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
                        $out.= "Content-Length: ".strlen($post_string)."\r\n";
                        $out.= "Connection: Close\r\n\r\n";
                        fwrite($fp, $out);
                        fclose($fp);
                    }
                    ?>
    

    testpage.php

        <?
        echo $_REQUEST["Keywordname"];//case1 Output > testValue
    //here do your background operations it will not halt main page
        ?>
    

    추신 : 루프 매개 변수로 URL 매개 변수를 보내려면 다음 답변을 따르십시오. https : //stackoverflow.com/a/41225209/6295712

  15. ==============================

    15.이것은 나를 위해 일합니다. 이걸로

    이것은 나를 위해 일합니다. 이걸로

    exec(“php asyn.php”.” > /dev/null 2>/dev/null &“);
    
  16. from https://stackoverflow.com/questions/4626860/how-can-i-run-a-php-script-in-the-background-after-a-form-is-submitted by cc-by-sa and MIT license