IT

폼이 전송된 후 백그라운드에서 PHP 스크립트를 실행하려면 어떻게 해야 합니까?

itgroup 2022. 11. 17. 21:09
반응형

폼이 전송된 후 백그라운드에서 PHP 스크립트를 실행하려면 어떻게 해야 합니까?

★★★
제출 시 기본 코드를 실행하여 제출된 정보를 처리하고 통지 웹 사이트에 표시할 수 있도록 데이터베이스에 삽입하는 양식을 가지고 있습니다.또한 이메일과 SMS 메시지로 이러한 알림을 받기 위해 등록한 사람들의 목록이 있습니다.이 리스트는 현재(약 150개만 푸시)로 매우 사소한 것이지만, 서브스크라이버 전체 테이블을 순환하여 150개 이상의 이메일을 발송하는 데 1분 이상 걸립니다(대량 이메일 정책 때문에 이메일 서버의 시스템 관리자가 요청한 대로 이메일이 개별적으로 발송됩니다).

이 시간 동안 알림을 게시한 개인은 알림이 게시된다는 긍정적인 강조 없이 양식의 마지막 페이지에 거의 1분 동안 앉아 있게 됩니다.이것은 다른 잠재적인 문제로 이어지며, 제가 이상적이지 않다고 느끼는 가능한 해결책들이 모두 있습니다.

  1. 우선, 포스터는 서버가 지연되고 있다고 생각하여 다시 [Submit]버튼을 클릭하면 스크립트가 다시 시작되거나 두 번 실행될 수 있습니다.JavaScript를 사용하여 버튼을 비활성화하고 텍스트를 'Processing...'과 같은 말로 바꿈으로써 이 문제를 해결할 수 있었지만, 사용자가 스크립트 실행 시간 동안 페이지에 계속 남아 있을 것이기 때문에 이상적이지 않습니다.(또한 JavaScript가 비활성화되어 있는 경우에도 이 문제는 존재합니다.)

  2. 둘째, 포스터가 폼을 제출한 후 탭이나 브라우저를 너무 빨리 닫을 수 있습니다.스크립트는 브라우저에 회신할 때까지 서버에서 계속 실행됩니다.단, 사용자가 도메인 내의 임의의 페이지를 참조하면(스크립트가 실행 중일 때), 브라우저는 스크립트가 종료될 때까지 페이지 로딩이 중단됩니다.(이것은 브라우저의 탭 또는 창이 닫혔을 때에만 발생합니다.브라우저 어플리케이션 전체가 닫히지 않습니다).그래도 이상적이지는 않다.

(가능)
스크립트의 "이메일" 부분을 알림이 게시된 후 호출할 수 있는 다른 파일로 분할하기로 결정했습니다.저는 원래 알림이 정상적으로 뜨면 확인 페이지에 올릴까 생각 중입니다.는 이 중임을 .「 」 、 「 」 、 「 」이 스크립트는 실패할 수 없습니다.

그러나 이 스크립트를 백그라운드프로세스로 실행할 수 있다면 어떻게 될까요?자, 제 질문은 다음과 같습니다.백그라운드 서비스로 트리거하고 사용자가 폼 수준에서 수행한 작업과 완전히 독립적으로 실행하는 PHP 스크립트를 실행하려면 어떻게 해야 합니까?

EDIT: 이것은 cron's할 수 없습니다.양식이 제출되는 즉시 실행되어야 합니다.이것들은 고우선순위 통지입니다.또한 당사의 서버를 실행하는 시스템 관리자는 cron의 실행을 5분 이상 허용하지 않습니다.

사용하여 실험을 하다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)

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);

&츠키노원래 스크립트가 종료된 경우에도 스크립트는 계속됩니다.

모든 응답 중에서 터무니없이 쉬운 fastcgi_finish_request 함수는 아무도 고려하지 않았습니다.이 함수는 호출되면 나머지 출력이 모두 브라우저로 플러시되고 Fastcgi 세션과 HTTP 연결이 닫히며 스크립트는 백그라운드에서 실행됩니다.

예를 들어:

<?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

주의: fastcgi_finish_request 뒤에 flash()를 호출하면 경고/오류 없이 flash()가 종료됩니다.

해도 됩니다.ignore_user_abort(true)하거나 연결을 flash()

$connected = true;

// Stuff...

fastcgi_finish_request();
$connected = false;

// ...
if ($connected) {
    flush();
}

또는

ignore_user_abort(true);
fastcgi_finish_request();
// Accidental flush()es won't do harm (even if they're still technically a bug)
flush();

PHPexec("php script.php")아, 아, 아, 아, 아, 아, 아, 아, 아.

매뉴얼:

이 기능을 사용하여 프로그램을 시작할 경우 백그라운드에서 계속 실행되도록 하려면 프로그램의 출력을 파일 또는 다른 출력 스트림으로 리디렉션해야 합니다.그렇지 않으면 프로그램 실행이 종료될 때까지 PHP가 중단됩니다.

따라서 출력을 로그 파일로 리다이렉트하면(어차피 좋은 방법이긴 하지만), 호출 스크립트는 중단되지 않고 이메일 스크립트는 bg 단위로 실행됩니다.

또한 스크립트에서 HTTP 요청을 생성하고 응답을 무시하지 않는 이유는 무엇입니까?

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

스크립트를 호출해야 하는 경우 웹 서버가 백그라운드에서 실행되며 스크립트가 실행 중임을 사용자에게 알리는 메시지를 표시할 수 있습니다.

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

php script.php >/dev/null &

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

이건 어때?

  1. 폼을 유지하는 PHP 스크립트는 플래그 또는 일부 값을 데이터베이스 또는 파일에 저장합니다.
  2. 두 번째 PHP 스크립트는 이 값을 정기적으로 폴링하고 설정된 경우 동기식으로 Email 스크립트를 트리거합니다.

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

이것을 간단하게 실시할 수 없는 것을 알고 있기 때문에(fork exec 등(윈도우에서 작업하지 말아 주세요)), 어프로치를 반대로 해, 브라우저가 폼을 Ajax로 투고하는 배경을 사용할 수 있기 때문에, 투고가 아직 기능하는 경우는 대기 시간이 없습니다.
이것은 당신이 오랜 시간 동안 상세하게 설명해야 할 경우에도 도움이 될 수 있다.

메일 송신에 대해서는 큐를 스풀링하는 cron을 사용하는 것보다 항상 스풀러를 사용하는 것이 좋습니다.스풀러를 사용하면 요구를 받아들여 실제 MTA에 스풀링하거나 모두 DB에 저장할 수 있습니다.
URLcron" "URL"로하는 다른 수 .

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

background cron 작업을 수행하는 것이 좋습니다.

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

$ php scriptname.php실행할 수 있습니다.

할 수 할 수 있는 php 를 할 수 단, ssh 를 사용해 를 할 ).posix「 」의 서포트입니다.fork

서버는 실제로 어떤 형식으로든 쓸 수 있으며, 파이썬으로도 쉽게 쓸 수 있습니다.

또는 가장 간단한 해결책은 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)));
}
?>

를 하고 있는는, 를 참조해 주세요.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

?>

플랫폼에서 *nix를 합니다.cronphp실행 가능.

편집:

이미 SO에서 "running php without cron"을 요청하는 질문이 꽤 있습니다.다음 중 하나:

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

즉, 위의 exec() 답변은 매우 유망하게 들립니다.

백그라운드 워커의 경우, 이 테크닉을 사용해 보는 것이 좋을 것 같습니다.모든 페이지가 동시에 독립적으로 실행되도록 원하는 만큼의 페이지를 호출하는 것이 비동기 페이지 응답을 기다리지 않고 도움이 됩니다.

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);
                }
                ?>

테스트 페이지php

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

PS: URL 파라미터를 루프로 송신하는 경우는, 다음의 회답에 따릅니다.https://stackoverflow.com/a/41225209/6295712

제 경우 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 &");

프로세스에서php 코드가 있습니다.

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

$idCurso = $argv[1];
$idDestino = $argv[2];
$mensaje = $argv[3];

이건 나한테 딱 맞는군. tyr this.

exec(“php asyn.php”.” > /dev/null 2>/dev/null &“);

작업을 병렬 및 비동기적으로 실행하려면 Amp를 사용합니다.

라이브러리 설치

composer require amphp/parallel-functions

코드샘플

<?php

require "vendor/autoload.php";

use Amp\Promise;
use Amp\ParallelFunctions;


echo 'started</br>';

$promises[1] = ParallelFunctions\parallel(function (){
    // Send Email
})();

$promises[2] = ParallelFunctions\parallel(function (){
    // Send SMS
})();


Promise\wait(Promise\all($promises));

echo 'finished';

사용 사례에 따라 다음과 같은 작업을 수행할 수 있습니다.

<?php

use function Amp\ParallelFunctions\parallelMap;
use function Amp\Promise\wait;

$responses = wait(parallelMap([
    'a@example.com',
    'b@example.com',
    'c@example.com',
], function ($to) {
    return send_mail($to);
}));

언급URL : https://stackoverflow.com/questions/4626860/how-can-i-run-a-php-script-in-the-background-after-a-form-is-submitted

반응형