Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute code after script abort on CLI

I try to execute some final code after my script got aborted in PHP. So let's say I have this PHP script:

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

if I execute the script with $ php script.php it run's till the given execution time.

Now I like to execute some final code after the script has been aborted. So if I

  • hit Ctrl+C
  • the execution time is over

Is there even a possibility to do some clean up in those cases?

I tried it with pcntl_signal but with no luck. Also with register_shutdown_function but this get only called if the script ends successfully.

UPDATE

I found out (thx to rch's link) that I somehow can "catch" the events with:

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

But if I extend my code with

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

pcntl_signal(SIGINT, $cleanUp);

the script keeps executing but does not respect the code in $cleanUp closure if I hit Ctrl+C.

like image 752
TiMESPLiNTER Avatar asked Jun 19 '15 07:06

TiMESPLiNTER


1 Answers

The function pcntl_signal() is the answer for the situation when the script is interrupted using Ctrl-C (and by other signals). You have to pay attention to the documentation. It says:

You must use the declare() statement to specify the locations in your program where callbacks are allowed to occur for the signal handler to function properly.

The declare() statement, amongst other things, installs a callback function that handles the dispatching of the signals received since its last call, by calling the function pcntl_signal_dispatch() which in turn calls the signal handlers you installed.

Alternatively, you can call the function pcntl_signal_dispatch() yourself when you consider it's appropriate for the flow of your code (and don't use declare(ticks=1) at all).

This is an example program that uses 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);
}
like image 99
axiac Avatar answered Nov 01 '22 11:11

axiac