I had the need to have a timer running while I waited for a process to stop running.
The Code:
FORK:
{
if ($pid=fork)
{
#Parent
print "Parent PID: $$\n";
print "Child PID: $pid\n";
print "\e[K($$) Attempting to stop Tomcat.\n";
`/etc/init.d/tomcat5 stop`;
$PROCPID = `/sbin/pidof java`;
chomp($PROCPID);
if ( $PROCPID )
{
print "\e[K($$) Tomcat COULD NOT be stopped.\n";
}
else
{
print "\e[K($$) Tomcat should be stopped.\n";
}
print "\e[K($$) Exiting.\n";
}
elsif ( defined($pid) )
{
#Child
until ($stopped == 1)
{
$cnt++;
sleep 1;
$PROCPID = `/sbin/pidof java`;
chomp($PROCPID);
if ( $PROCPID )
{
print "\e[K($$) Been waiting $cnt seconds for Tomcat to exit.\r";
}
else
{
print "\e[K($$) Had to wait $cnt seconds for Tomcat to exit.\n";
print "\e[K($$) Tomcat SHOULD be stopped.\n";
$stopped = 1;
}
}
print "\e[K($$) Exiting.\n";
exit;
}
elsif ( $! == EAGAIN )
{
# EAGAIN is the supposedly recoverable fork error
sleep 5;
redo FORK;
}
else
{
die "Can't fork: $!\n";
}
}
waitpid($pid, 0);
Sample output:
The timer counts from 1 second till the last second when the process is determined to be stopped.
Parent PID: 7048
Child PID: 7049
(7048) Attempting to stop Tomcat.
(7048) Tomcat should be stopped.
(7048) Exiting.
(7049) Had to wait 32 seconds for Tomcat to exit.
(7049) Tomcat SHOULD be stopped.
(7049) Exiting.
Here is the code explained.
This is just a label so we can easily use the redo function.
FORK:
If we successfully fork then save the PID of the child to $pid.
if ($pid=fork)
Test if the process is running. If it is not running then $PROCPID will not result in a test of TRUE.
$PROCPID = `/sbin/pidof java`;
chomp($PROCPID);
if ( $PROCPID )
Everywhere you see \e[K it means to issue a Control + K. In other words on a Linux command line that will clear the line where the cursor is.
print "\e[K($$) Tomcat COULD NOT be stopped.\n";
If a child PID does exist then give the child instructions for what you want it to do.
elsif ( defined($pid) )
Here we are going to loop through until the $PROCPID has returned FALSE. This then means the process is is no longer running.
until ($stopped == 1)
{
$cnt++;
sleep 1;
$PROCPID = `/sbin/pidof java`;
chomp($PROCPID);
if ( $PROCPID )
{
print "\e[K($$) Been waiting $cnt seconds for Tomcat to exit.\r";
}
else
{
print "\e[K($$) Had to wait $cnt seconds for Tomcat to exit.\n";
print "\e[K($$) Tomcat SHOULD be stopped.\n";
$stopped = 1;
}
print "\e[K($$) Exiting.\n";
exit;
This simply means do not exist the script until all children have returned.
waitpid($pid, 0);
Usable Sample Script
Sample Code as a subroutine, using strict, and variable declaration that support start or stop options.
use strict;
sub frk
{
my $proc = shift;
my $psw = shift;
my $action = shift;
FORK:
{
if (my $pid=fork)
{
#Parent
print "Parent PID: $$\n";
print "Child PID: $pid\n";
print "\e[K($$) Attempting to $action $proc.\n";
`$psw $action`;
my $PROCPID = `/sbin/pidof $proc`;
chomp($PROCPID);
if ( $PROCPID )
{
print "\e[K($$) $proc COULD NOT $action.\n" if ( $action eq 'stop' );
print "\e[K($$) $proc should be $action.\n" if ( $action eq 'start' );
}
else
{
print "\e[K($$) $proc should be $action.\n" if ( $action eq 'stop' );
print "\e[K($$) $proc COULD NOT $action.\n" if ( $action eq 'start' );
}
print "\e[K($$) Exiting.\n";
return $pid;
}
elsif ( defined($pid) )
{
#Child
my $leaveloop = 0;
my $cnt = 0;
until ($leaveloop == 1)
{
$cnt++;
sleep 1;
my $PROCPID = `/sbin/pidof $proc`;
chomp($PROCPID);
if ( $PROCPID )
{
print "\e[K($$) Been waiting $cnt seconds for $proc to $action.\r" if ( $action eq 'stop' );
print "\e[K($$) Had to wait $cnt seconds for $proc to $action.\n" if ( $action eq 'start' );
print "\e[K($$) $proc SHOULD be $action.\n" if ( $action eq 'start' );
$leaveloop = 1 if ( $action eq 'start' );
}
else
{
print "\e[K($$) Had to wait $cnt seconds for $proc to $action.\n" if ( $action eq 'stop' );
print "\e[K($$) $proc SHOULD be $action.\n" if ( $action eq 'stop' );
$leaveloop = 1 if ( $action eq 'stop' );
print "\e[K($$) Been waiting $cnt seconds for $proc to $action.\r" if ( $action eq 'start' );
}
}
print "\e[K($$) Exiting.\n";
exit;
}
elsif ( $! == 'EAGAIN' )
{
# EAGAIN is the supposedly recoverable fork error
sleep 5;
redo FORK;
}
else
{
die "Can't fork: $!\n";
}
}
}
my $pid;
my $proc = 'java';
my $psw = '/etc/init.d/tomcat5';
my $action = $ARGV[0];
chomp($action);
$pid = frk($proc,$psw,$action);
waitpid($pid, 0);
Sample output for start
Parent PID: 11595
Child PID: 11596
(11595) Attempting to start java.
(11595) java should be start.
(11595) Exiting.
(11596) Had to wait 1 seconds for java to start.
(11596) java SHOULD be start.
(11596) Exiting.
Sample output for stop
Parent PID: 12167
Child PID: 12168
(12167) Attempting to stop java.
(12167) java should be stop.
(12167) Exiting.
(12168) Had to wait 32 seconds for java to stop.
(12168) java SHOULD be stop.
(12168) Exiting.