#!/usr/bin/perl # This script runs as a daemon to detect and kill perl processes that # have been started by TWiki and hung. # This is a (rather ugly) workaround for a problem in TWiki that I # can't correct (see http://twiki.org/cgi-bin/view/Support/TimeOutSavingTWikiPreferences) # This script will need permissions to kill Apache processes, so it will need to run # as root use strict; use POSIX qw(setsid); # "daemonize" the program &daemonize; my $interval = 2; # The time interval between polls. Don't set this too # short or processes might be killed off prematurely my @suspect_pids; # Array of suspect PIDs while(1) { sleep($interval); # Find suspect processes run by user "apache", but make sure it doesn't find this ps command! # This logic adapted from http://accad.osu.edu/~mlewis/Class/Perl/perl.html my @lines = `ps -ef | grep apache | grep template=oopsauth | grep -v grep`; if(@lines) { my @new_pids; # Each suspect process should have its own $line. foreach my $line (@lines) { $line =~ /^\s*(\w+)\s+(\d+)/; # Find the user and pid for this line my $pid = $2; # Add this to our list of PIDs push (@new_pids, $pid); } my $timestamp = `date +"%d-%m-%y %T"`; chop($timestamp); print("$timestamp: Caught suspect process(es) under pid(s) @new_pids\n"); # Check through the list of previously-found suspect PIDs foreach my $suspect_pid (@suspect_pids) { foreach my $new_pid (@new_pids) { if ($new_pid == $suspect_pid) { my $timestamp = `date +"%d-%m-%y %T"`; chop($timestamp); # Try to kill the process my $numkilled = kill 9, $new_pid; if ($numkilled == 1) { print("$timestamp: Killed process $new_pid\n"); } else { print("$timestamp: Couldn't kill process $new_pid\n"); } } } # look at next new PID } # look at next suspect PID @suspect_pids = @new_pids; } } # Subroutine to "daemonize" the program # (see http://www.webreference.com/perl/tutorial/9/index.html) sub daemonize { my $stdout_log = "/path/to/kill_rogue_twiki_processes_daemon.log"; chdir '/' or die "Can't chdir to /: $!"; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, ">>$stdout_log" or die "Can't write to $stdout_log: $!"; open STDERR, '/dev/null' or die "Can't read /dev/null: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; umask 0; }