문제
PHP 스크립트를 만들려고 노력하고 있습니다. 스크립트를 완료했지만 설계된 프로세스를 완료하는 데 10 분이 걸립니다. 이것은 문제가되지 않지만,이 시간을 항상로드해야한다고 가정합니다. 프로세스를 시작한 다음 10 분 후에 돌아와서 생성 한 로그 파일 만 볼 수 있도록 가질 수 있습니까?
해결책
글쎄, 당신은 사용할 수 있습니다 "INGORE_USER_ABORT(진실)"
그래서 스크립트는 계속 작동합니다 (스크립트 지속 시간을 주시하십시오.set_time_limit(0)")
그러나 여기서 경고 :이 두 줄로 스크립트를 중지 할 수 없습니다.
ignore_user_abort(true);
set_time_limit(0);
서버에 직접 액세스하고 프로세스를 죽일 수있는 경우를 제외하고! (그곳에 있었고, 끝없는 루프를 끝내고, 계속해서 스스로를 계속 호출하고, 서버를 삐걱 거리는 정지에 올랐고, 소리를 지르고 ...)
다른 팁
대기열을 처리하기위한 대기열과 외부 스크립트가 있어야하는 것처럼 들립니다.
예를 들어, PHP 스크립트는 데이터베이스 테이블에 항목을 넣고 즉시 반환해야합니다. 그런 다음 매분마다 실행되는 크론은 대기열을 확인하고 각 작업에 대한 프로세스를 포크합니다.
여기서 장점은 아파치 스레드를 10 분 동안 잠그지 않는다는 것입니다.
Windows에서 이런 종류의 프로세스에 많은 문제가있었습니다. 내 상황은 "스크립트"의 응답에 신경 쓰지 않았다는 점에서 약간 달랐습니다. 스크립트가 시작하고 다른 페이지 요청이 바쁘게 일하는 동안 다른 페이지 요청이 진행되기를 원했습니다.
몇 가지 이유; 나는 약 60 초 후에 다른 요청을하거나 타이밍에 문제가있었습니다 (Apache와 PHP는 약 20 분 후에 시간을 초과했습니다). 또한 Firefox는 어쨌든 5 분 후에 (기본적으로) 시간이 지남에 따라 Firefox에서 설정을 변경하지 않고 브라우저를 통해 무슨 일이 일어나고 있는지 알 수 없습니다.
프로세스 열기를 사용하여 CLI 모드에서 PHP를 열기 위해 긴밀한 방법을 사용하여 다음과 같습니다.
pclose(popen("start php myscript.php", "r"));
(시작 사용) PHP 프로세스를 열고 시작 프로세스를 시작한 다음 PHP가 오랫동안 실행되는 시작 프로세스를 죽일 수 있습니다. 타임 아웃을 설정할 필요가 없었으며,이를 불리는 현재 페이지를 계속하고 더 자세한 내용을 출력 할 수 있습니다.
이것의 유일한 문제는 스크립트를 스크립트에 보내야하는 경우 다른 소스를 통해이를 수행하거나 "명령 줄"을 따라 매개 변수로 전달한다는 것입니다. 그렇게 안전하지 않습니다.
그래도 우리가 필요로하는 것에 대해 잘 작동했으며 스크립트가 항상 시작되고 중단없이 실행할 수 있도록합니다.
이것은 또한 도움이 될 수 있습니다. Php에서 비동기식 쉘 exec
shell_exec 명령이 당신이 찾고있는 것이라고 생각합니다.
그러나 안전 모드에서 비활성화됩니다.
이에 대한 PHP 매뉴얼 기사는 다음과 같습니다. http://php.net/shell_exec
여기에 대한 기사가 있습니다. http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
사용할 수있는 또 다른 옵션이 있습니다. 스크립트 CLI를 실행할 수 있습니다 ... 백그라운드에서 실행되며 원하는 경우 크론 조브로 실행할 수도 있습니다.
예를 들어
> #!/usr/bin/php -q
<?php
//process logs
?>
이것은 cronjob으로 설정 될 수 있으며 시간 제한없이 실행됩니다 ....이 예제는 UNIX 기반 운영 시스템을위한 것입니다.
참고로 나는 약간의 처리를 수행하고 지난 3 개월 동안 비 정거장에서 실행중인 무한 루프로 PHP 스크립트를 실행하고 있습니다.
당신은 사용할 수 있습니다 ignore_user_abort()
- 이렇게하면 브라우저를 닫거나 다른 페이지로 이동하더라도 스크립트가 계속 실행됩니다.
Bastiandoeen의 답변 외에도 결합 할 수 있습니다 ignore_user_abort(true);
a 컬 요청.
요청 낙태 설정을 낮게 설정하십시오 CURLOPT_TIMEOUT_MS
연결이 닫힌 후 계속 처리하십시오.
function async_curl($background_process=''){
//-------------get curl contents----------------
$ch = curl_init($background_process);
curl_setopt_array($ch, array(
CURLOPT_HEADER => 0,
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms
CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute
CURLOPT_VERBOSE => 1,
CURLOPT_HEADER => 1
));
$out = curl_exec($ch);
//-------------parse curl contents----------------
//$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
//$header = substr($out, 0, $header_size);
//$body = substr($out, $header_size);
curl_close($ch);
return true;
}
async_curl('http://example.com/background_process_1.php');
NB
1 초 이내에 Curl to 시간 초과를 원한다면 Curlopt_timeout_ms를 사용할 수 있지만 "Unix-Like Systems"에 버그/"기능"이있어 값이 오류가 발생하여 값이 <1000ms 인 경우 즉시 Libcurl이 타임 아웃을 유발하는 경우 "가 있습니다. 컬러 오류 (28) : 시간 초과에 도달했습니다. " 이 행동에 대한 설명은 다음과 같습니다.
[...]
해결책은 Curlopt_noSignal을 사용하여 신호를 비활성화하는 것입니다
프로
- 메소드를 전환 할 필요가 없습니다 (호환 Windows & Linux)
- 헤더 및 버퍼를 통해 연결 처리를 구현할 필요가 없습니다 (브라우저 및 PHP 버전에서 독립)
단점
- 컬 확장이 필요합니다
자원
ZUK.
나는 이것이 효과가있을 것이라고 확신한다 :
<?php
pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]";
?>
'&'는 중요합니다. 쉘은 프로세스가 종료 될 때까지 기다리지 말라고 지시합니다.
또한 PHP 에서이 코드를 사용할 수 있습니다 ( "Bastiandoeen"이 말한 것처럼)
ignore_user_abort(true);
set_time_limit(0);
서버 중지 명령에서 :
<?php
$output;
exec('ps aux | grep -ie /path/to/file/server.php | awk \'{print $2}\' | xargs kill -9 ', $output);
echo "Server stopped. [OK]";
?>
출력 전에 startBuffer ()를 호출하고 클라이언트가 연결을 닫으려면 EndBuffer ()를 호출하십시오. EndBuffer ()를 호출 한 후 코드는 클라이언트 연결없이 서버에서 실행됩니다.
private function StartBuffer(){ @ini_set('zlib.output_compression',0); @ini_set('implicit_flush',1); @ob_end_clean(); @set_time_limit(0); @ob_implicit_flush(1); @ob_start(); } private function EndBuffer(){ $size = ob_get_length(); header("Content-Length: $size"); header('Connection: close'); ob_flush();ob_implicit_flush(1); }