문제

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() - 이렇게하면 브라우저를 닫거나 다른 페이지로 이동하더라도 스크립트가 계속 실행됩니다.

생각하십시오 기어맨

Gearman은 여러 기계 나 프로세스에 대한 작업을 농업하기위한 일반적인 응용 프로그램 프레임 워크입니다. 응용 프로그램이 병렬로 작업을 완료하고 균형 처리를로드하고 언어 간 기능을 호출 할 수 있습니다. 이 프레임 워크는 고 가용성 웹 사이트에서 데이터베이스 복제 이벤트 전송에 이르기까지 다양한 응용 프로그램에서 사용할 수 있습니다.

이 확장은 Gearman 고객 및 근로자를 작성하기위한 수업을 제공합니다. - 소스 PHP 매뉴얼

외부 웹 사이트 기어맨

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top