[php] 양식을 제출 한 후 백그라운드에서 PHP 스크립트를 어떻게 실행할 수 있습니까?

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

이 시간 동안 알림을 게시 한 개인은 알림이 게시되고 있다는 긍정적 인 보강없이 거의 1 분 동안 양식의 마지막 페이지에 앉아있을 것입니다. 이것은 내가 이상적이지 않다고 생각하는 가능한 해결책을 가진 다른 잠재적 인 문제로 이어집니다.

  1. 첫째, 포스터는 서버가 지연되고 있다고 생각하고 ‘제출’버튼을 다시 클릭하면 스크립트가 다시 시작되거나 두 번 실행됩니다. JavaScript를 사용하여 버튼을 비활성화하고 텍스트를 ‘Processing …’과 같은 텍스트로 바꾸면이 문제를 해결할 수 있지만 사용자가 스크립트 실행 시간 동안 페이지에 계속 머물러 있기 때문에 이상적이지 않습니다. (또한 JavaScript가 비활성화 된 경우에도이 문제가 여전히 존재합니다.)

  2. 둘째, 포스터는 양식을 제출 한 후 탭이나 브라우저를 너무 일찍 닫을 수 있습니다. 스크립트는 브라우저에 다시 쓰기를 시도 할 때까지 서버에서 계속 실행되지만 사용자가 도메인 내의 페이지를 탐색하면 (스크립트가 아직 실행중인 동안) 브라우저는 스크립트가 종료 될 때까지 페이지로드를 중단합니다. . (이것은 브라우저의 탭이나 창이 전체 브라우저 응용 프로그램이 아닌 닫혀있을 때만 발생합니다.) 그래도 이상적이지 않습니다.

(가능) 해결 방법
스크립트의 “이메일”부분을 알림이 게시 된 후 호출 할 수있는 별도의 파일로 나누고 싶습니다. 처음에는 알림이 성공적으로 게시 된 후 확인 페이지에 게시 할 생각이었습니다. 그러나 사용자는이 스크립트가 실행되고 있다는 것을 알지 못하며 어떤 이상 현상도 눈에 띄지 않습니다. 이 스크립트는 실패 할 수 없습니다.

하지만이 스크립트를 백그라운드 프로세스로 실행할 수 있다면 어떨까요? 제 질문은 이것이다 : PHP 스크립트를 어떻게 실행하여 백그라운드 서비스로 트리거하고 사용자가 양식 수준에서 수행 한 작업과 완전히 독립적으로 실행할 수 있습니까?

편집 : 이것은 cron’ed 수 없습니다 . 양식이 제출되는 즉시 실행되어야합니다. 우선 순위가 높은 알림입니다. 또한 서버를 실행하는 시스템 관리자는 크론이 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 세션과 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,


답변

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

로부터 수동 :

프로그램이이 함수로 시작된 경우 백그라운드에서 계속 실행하려면 프로그램의 출력을 파일 또는 다른 출력 스트림으로 리디렉션해야합니다. 그렇게하지 않으면 프로그램 실행이 끝날 때까지 PHP가 중단됩니다.

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


답변

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

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

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


답변

이건 어때요?

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

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


답변

쉬운 방법으로 이것을 할 수 없다는 것을 알고 있기 때문에 (fork exec 등 (창에서 작동하지 않음) 참조) 접근 방식을 되돌릴 수 있으며 브라우저의 배경을 사용하여 ajax로 양식을 게시하므로 게시물이 여전히 당신은 대기 시간이 없습니다.
이것은 긴 정교함을해야하는 경우에도 도움이 될 수 있습니다.

메일 보내기에 관해서는 항상 스풀러를 사용하는 것이 좋습니다. 큐를 스풀링하는 크론을 사용하는 것보다 요청을 수락하고이를 실제 MTA에 스풀링하거나 모두 DB에 넣는 로컬 및 빠른 smtp 서버 일 수 있습니다.
크론은 스풀러를 외부 URL로 호출하는 다른 시스템에있을 수 있습니다.

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