2015-06-19 2 views
2

Я пытаюсь выполнить какой-то окончательный код после того, как мой скрипт был прерван в PHP. Так скажем, у меня есть этот скрипт:Выполнить код после сценария abort на CLI

while(true) { 
    echo 'loop'; 
    sleep(1); 
} 

, если я выполнить скрипт с $ php script.php его запуска до ухода заданного времени выполнения.

Теперь мне нравится выполнять какой-то окончательный код после того, как сценарий был прерван. Так что, если я

  • ударил Ctrl+C
  • время выполнения является более

Есть даже возможность сделать некоторые очистки в этих случаях?

Я попробовал его с pcntl_signal, но не повезло. Также с register_shutdown_function, но это вызывается только при успешном завершении сценария.

UPDATE

Я узнал (ТНХ на ссылку RCH), что я как-то можно "поймать" события с:

pcntl_signal(SIGTERM, $restartMyself); // kill 
pcntl_signal(SIGHUP, $restartMyself); // kill -s HUP or kill -1 
pcntl_signal(SIGINT, $restartMyself); // Ctrl-C 

Но если я расширяю свой код с

$cleanUp = function() { 
    echo 'clean up'; 
    exit; 
}; 

pcntl_signal(SIGINT, $cleanUp); 

сценарий продолжает выполнение, но не соблюдает код в $cleanUp закрытии, если я ударил Ctrl+C.

ответ

3

Функция pcntl_signal() является ответом на ситуацию, когда сценарий находится в перегружены с использованием Ctrl-C (и другими сигналами). Вы должны обратить внимание на документацию. Он говорит:

Вы должны использовать declare() заявление, чтобы указать места в программе, где обратные вызовы разрешено иметь место для обработчика сигнала, чтобы функционировать должным образом.

declare() заявление, помимо прочего, устанавливает функцию обратного вызова, которая обрабатывает диспетчеризацию сигналов, полученных с момента его последнего вызова, вызывая функцию pcntl_signal_dispatch(), которая в свою очередь, вызывает обработчики сигналов вы установлены.

В качестве альтернативы вы можете вызвать функцию pcntl_signal_dispatch() самостоятельно, если считаете, что это подходит для потока вашего кода (и вообще не использовать declare(ticks=1)).

Это пример программы, которая использует declare(ticks=1):

declare(ticks=1); 

// Install the signal handlers 
pcntl_signal(SIGHUP, 'handleSigHup'); 
pcntl_signal(SIGINT, 'handleSigInt'); 
pcntl_signal(SIGTERM, 'handleSigTerm'); 


while(true) { 
    echo 'loop'; 
    sleep(1); 
} 

// Reset the signal handlers 
pcntl_signal(SIGHUP, SIG_DFL); 
pcntl_signal(SIGINT, SIG_DFL); 
pcntl_signal(SIGTERM, SIG_DFL); 



/** 
* SIGHUP: the controlling pseudo or virtual terminal has been closed 
*/ 
function handleSigHup() 
{ 
    echo("Caught SIGHUP, terminating.\n"); 
    exit(1); 
} 

/** 
* SIGINT: the user wishes to interrupt the process; this is typically initiated by pressing Control-C 
* 
* It should be noted that SIGINT is nearly identical to SIGTERM. 
*/ 
function handleSigInt() 
{ 
    echo("Caught SIGINT, terminating.\n"); 
    exit(1); 
} 

/** 
* SIGTERM: request process termination 
* 
* The SIGTERM signal is a generic signal used to cause program termination. 
* It is the normal way to politely ask a program to terminate. 
* The shell command kill generates SIGTERM by default. 
*/ 
function handleSigTerm() 
{ 
    echo("Caught SIGTERM, terminating.\n"); 
    exit(1); 
} 
+0

Thx! Работает как шарм. Можете ли вы сказать мне, почему именно мне нужно сбросить обработчики сигналов? Я думаю, что это то, чего я пропустил в своем подходе с pcntl_signal вместе с 'ticks = 1' ... – TiMESPLiNTER

+1

Не знаю, выполняет ли сброс обработчики сигналов. Я поместил их там по привычке, это хорошая практика кодирования, чтобы закрыть открытые файлы, разрушить построенные объекты, освободить выделенные ресурсы a.s.o. Если вы не хотите 'exit()' немедленно, но хотите выполнить дополнительную обработку, рекомендуется установить флаг в обработчике сигнала и проверить его в главном программном цикле и продолжить соответственно (или использовать 'pcntl_signal_dispatch()' вместо 'declare (ticks = 1)'. Вы можете узнать больше о [сигналах окончания] (http://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html). – axiac

+0

Thx снова для ответа и интересная ссылка.Так что, если мне нравится использовать 'pcntl_signal_dispatch' вместо' ticks = 1', где я должен его называть? Где-то в моем цикле? Тогда скрипты выполняются до отправляемого вызова, который я предполагаю, а затем вызывает обратный вызов, определяемый функцией 'pcntl_signal'. right? – TiMESPLiNTER

0

У этого может быть какая-то действительно полезная информация, похоже, они используют те же вещи, которые вы пытались, но, по-видимому, с положительными результатами? Возможно, что-то здесь вы не пытались или не пропустили.

Automatically Restart PHP Script on Exit

Смежные вопросы