양식을 제출 한 후 백그라운드에서 PHP 스크립트를 실행하려면 어떻게해야합니까?
PHP양식을 제출 한 후 백그라운드에서 PHP 스크립트를 실행하려면 어떻게해야합니까?
문제 제출 된 정보를 제출하고 알림 웹 사이트에 표시하기 위해 데이터베이스에 삽입하는 기본 코드를 실행하는 양식이 있습니다. 또한 전자 메일 및 SMS 메시지를 통해 이러한 알림을 수신하도록 등록한 사람들의 목록이 있습니다. 이 목록은 그 순간과 같이 사소한 것이지만 (약 150 회만 누름) 구독자 전체 테이블을 순환하고 150 개 이상의 전자 메일을 보내려면 1 분 이상 소요됩니다. (이메일은 대량 이메일 정책 때문에 이메일 서버의 시스템 관리자가 요청한대로 개별적으로 전송됩니다.)
이 시간 동안 알림을 게시 한 개인은 알림이 게시되고 있다는 긍정적 인 강조없이 거의 1 분 동안 양식의 마지막 페이지에 앉습니다. 이로 인해 다른 잠재적 인 문제가 발생할 수 있습니다. 가능한 모든 해결책에 이상이없는 것 같습니다.
(가능한 해결책 필자는 스크립트의 "전자 메일"부분을 알림을 게시 한 후에 호출 할 수있는 별도의 파일로 분할하려고합니다. 나는 원래 통보가 성공적으로 게시 된 후에 이것을 확인 페이지에 넣을 생각이었다. 그러나 사용자는이 스크립트가 실행 중임을 알지 못하며 어떤 예외도 분명하지 않습니다. 이 스크립트는 실패 할 수 없습니다.
그러나이 스크립트를 백그라운드 프로세스로 실행할 수 있다면 어떨까요? 그래서, 내 질문은 : 백그라운드 서비스로 트리거하고 양식 수준에서 사용자가 수행 한 것과 완전히 독립적으로 실행되도록 PHP 스크립트를 실행하려면 어떻게해야합니까?
편집 :이 cron'ed 수 없습니다. 양식이 제출되는 즉시 실행해야합니다. 우선 순위가 높은 알림입니다. 또한 서버를 실행하는 시스템 관리자는 cron이 5 분 이상 실행되는 것을 허용하지 않습니다.
해결법
-
==============================
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.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.PHP exec ( "php script.php")가 할 수 있습니다.
PHP exec ( "php script.php")가 할 수 있습니다.
매뉴얼에서 :
따라서 출력을 로그 파일로 리디렉션하면 (어쨌든 좋은 아이디어입니다) 호출 스크립트가 중단되지 않고 전자 메일 스크립트가 bg에서 실행됩니다.
-
==============================
4.그리고 스크립트에서 HTTP 요청을 만들고 응답을 무시하는 이유는 무엇입니까?
그리고 스크립트에서 HTTP 요청을 만들고 응답을 무시하는 이유는 무엇입니까?
http://php.net/manual/en/function.httprequest-send.php
스크립트에 대한 요청을하면 웹 서버에 전화를 걸어 백그라운드에서 실행하고 스크립트가 실행 중임을 사용자에게 알리는 메시지를 (기본 스크립트에서) 표시 할 수 있습니다.
-
==============================
5.이건 어때?
이건 어때?
이 두 번째 PHP 스크립트는 cron으로 실행되도록 설정해야합니다.
-
==============================
6.내가 쉽게 당신이 이것을 할 수 없다는 것을 안다. (포크 임원 등 (윈도우에서는 작동하지 않는다)) 아약스에서 폼을 게시하는 브라우저의 배경을 사용하여 접근법을 바꿀 수있다. 기다릴 시간이 없다. 이것은 오랫동안 정교함을해야만하는 경우에도 도움이 될 수 있습니다. 메일을 보내는 것에 관해서는 항상 스풀러를 사용하는 것이 좋으며 요청을 받아들이고 실제 MTA에 스풀링하는 로컬 및 빠른 smtp 서버 일 수도 있고 큐에 스풀링하는 cron을 사용하는 것보다 DB에 모두 넣을 수도 있습니다. cron은 스풀러를 외부 URL로 호출하는 다른 시스템에있을 수 있습니다.
내가 쉽게 당신이 이것을 할 수 없다는 것을 안다. (포크 임원 등 (윈도우에서는 작동하지 않는다)) 아약스에서 폼을 게시하는 브라우저의 배경을 사용하여 접근법을 바꿀 수있다. 기다릴 시간이 없다. 이것은 오랫동안 정교함을해야만하는 경우에도 도움이 될 수 있습니다. 메일을 보내는 것에 관해서는 항상 스풀러를 사용하는 것이 좋으며 요청을 받아들이고 실제 MTA에 스풀링하는 로컬 및 빠른 smtp 서버 일 수도 있고 큐에 스풀링하는 cron을 사용하는 것보다 DB에 모두 넣을 수도 있습니다. cron은 스풀러를 외부 URL로 호출하는 다른 시스템에있을 수 있습니다.
* * * * * wget -O /dev/null http://www.example.com/spooler.php
-
==============================
7.백그라운드에서 PHP 스크립트를 실행하는 더 간단한 방법은
백그라운드에서 PHP 스크립트를 실행하는 더 간단한 방법은
php script.php >/dev/null &
스크립트는 백그라운드에서 실행되며 페이지는 작업 페이지에 더 빨리 도달합니다.
-
==============================
8.백그라운드 크론 작업은 좋은 생각 인 것 같습니다.
백그라운드 크론 작업은 좋은 생각 인 것 같습니다.
스크립트를 cron으로 실행하려면 시스템에 ssh 액세스가 필요합니다.
그것을 실행하기 위해 $ php scriptname.php.
-
==============================
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.* nix 플랫폼에서 실행된다고 가정하면 cron과 PHP 실행 파일을 사용하십시오.
* nix 플랫폼에서 실행된다고 가정하면 cron과 PHP 실행 파일을 사용하십시오.
편집하다:
이미 "php없이 cron"을 실행하는 것에 대해 많은 질문이 있습니다. 여기에 하나 있습니다 :
CRON을 사용하지 않고 스크립트 예약
즉, 위의 exec () 대답은 매우 유망한 소리입니다. :)
-
==============================
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.모든 대답 중에서, 누구도 브라우저에서 남아있는 모든 출력을 플러시하고 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.제 경우에는 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.배경 작업자를 위해이 기술을 사용하면 모든 페이지가 비동기로 각 페이지 응답을 기다리지 않고 한 번에 독립적으로 실행되는 것처럼 많은 페이지를 호출하는 데 도움이됩니다.
배경 작업자를 위해이 기술을 사용하면 모든 페이지가 비동기로 각 페이지 응답을 기다리지 않고 한 번에 독립적으로 실행되는 것처럼 많은 페이지를 호출하는 데 도움이됩니다.
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.이것은 나를 위해 일합니다. 이걸로
이것은 나를 위해 일합니다. 이걸로
exec(“php asyn.php”.” > /dev/null 2>/dev/null &“);
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
'PHP' 카테고리의 다른 글
새 줄로 PHP 문자열 분해 (0) | 2018.09.20 |
---|---|
PHP 싱글 톤 수업에 대한 우수 사례 [duplicate] (0) | 2018.09.20 |
PHP $ _SERVER [ 'HTTP_HOST'] 대 $ _SERVER [ 'SERVER_NAME'], 맨 페이지를 제대로 이해하고 있습니까? (0) | 2018.09.20 |
isset () 및 empty ()를 피하는 방법 (0) | 2018.09.20 |
PHP에서 언어 구성과 "내장"기능의 차이점은 무엇입니까? (0) | 2018.09.20 |