Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trapping signals cleanly in Perl

I have a simple Perl script that simply prints a line of text to stdout. What I want to accomplish is that while this script runs, if I (or someone else) issues a signal to that process to stop, I want it to trap that signal and exit cleanly. The code I have looks like the following

#!/usr/bin/perl -w

$| = 1;
use sigtrap 'handler' => \&sigtrap, 'HUP', 'INT','ABRT','QUIT','TERM';
while(1){
 print "Working...\n";
 sleep(2);
}
sub sigtrap(){
 print "Caught a signal\n";
 exit(1);
}

While this works well when I actually hit ctrl-c from the command line, if I issue a

kill -9 <pid>

It just dies. How do I get it to execute something before exiting? My general idea is to use this framework to capture when this script dies on a server due to a server reboot for maintenance or failure.

Thanks much in advance

like image 694
broccoli Avatar asked Aug 02 '12 21:08

broccoli


People also ask

How do I catch a signal in Perl?

In Perl, signals can be caught and handled by using a global %SIG hash variable. This %SIG hash variable is keyed by signal numbers, and contains references to corresponding signal handlers.

What is signal in Perl?

Signals are types of messages sent by an operating system to a process such as a Perl program. Signals provide a method for communicating with a process, for example when running a command line program pressing control-c will send the interrupt signal ('SIGINT') to the program by default terminating it.

What is Perl end?

The eof() function is used to check if the End Of File (EOF) is reached. It returns 1 if EOF is reached or if the FileHandle is not open and undef in all other cases.


1 Answers

Signal #9 (SIGKILL) can not be trapped. That's how Unix is designed.

But the system does not send that signal when shutting down for maintainance. At least if your daemon behaves correctly. It will normally send the TERM signal (or more exactly what your daemon handling script in /etc/init.d does). Only processes that do not correctly shutdown after a timeout will receive SIGKILL.

So your aim should be to correctly handle the TERM signal and to write the wrapper script in /etc/init.d that will be called when the system is changing runlevel.

Update: You can use the Daemon::Control module for the init script.

like image 129
dolmen Avatar answered Oct 12 '22 04:10

dolmen