+++ /dev/null
-#!/usr/bin/perl
-#
-# fixproc [-min n] [-max n] [-check | -kill | -restart | -exist | -fix] proc ...
-#
-# fixproc exit code:
-# 0 ok
-# 1 check failed
-# 2 cannot restart
-# 3 cannot kill
-# 4 fix failed if fix is defined as kill or restart, then
-# cannot kill or cannot restart is return instead
-# 10 fixproc error
-#
-#
-# Fixes a process named "proc" by performing the specified action. The
-# actions can be check, kill, restart, exist, or fix. The action is specified
-# on the command line or is read from a default database, which describes
-# the default action to take for each process. The database format and
-# the meaning of each action are described below.
-#
-# database format
-# ---------------
-#
-# name foo required
-# cmd /a/b/name args required
-# min number optional, defaults to 1
-# max number optional, defaults to 1
-#
-# check {null, exist, shell} optional, defaults to exist if not defined
-# [shell command shell commands needed only if check=shell
-# ...
-# shell command
-# end_shell] keyword end_shell marks end of shell commands
-# fix {kill, restart, shell} required
-# [shell command shell commands needed only if fix=shell
-# ...
-# shell command
-# end_shell] keyword end_shell marks end of shell commands
-#
-# Blank lines and lines beginning with "#" are ignored.
-#
-#
-# Example:
-#
-# name test1
-# cmd nice /home/kong/z/test1 > /dev/null &
-# max 2
-# fix shell
-# xterm&
-# nice /home/kong/z/test1 > /dev/null &
-# end_shell
-#
-#
-# actions
-# -------
-# There are 5 possible actions: kill, restart, fix, exist, check. Fix is
-# defined to be the kill action, the restart action, or a series of shell
-# commands. Check is optionally defined in the database. If check is not
-# defined, it defaults to exist.
-#
-# If the action is specified on the cmd line, it is executed regardless of
-# check. The commands executed for each action type is as follow:
-#
-# switch action:
-# kill:
-# kill process, wait 5 seconds, kill -9 if still exist
-# if still exist
-# return "cannot kill"
-# else
-# return "ok"
-#
-# restart:
-# execute kill
-# if kill returned "cannot kill"
-# return "cannot kill"
-# restart by issuing cmd to shell
-# if check defined
-# execute check
-# if check succeeds
-# return "ok"
-# else
-# return "cannot restart"
-#
-# fix:
-# if fix=kill
-# execute kill
-# else if fix=restart
-# execute restart
-# else
-# execute shell commands
-# execute check
-#
-# check:
-# if check defined as null
-# return "fixproc error"
-# else
-# execute check
-# if check succeeds
-# return (execute exist)
-# return "check failed"
-#
-# exist:
-# if proc exists in ps && (min <= num. of processes <= max)
-# return "ok"
-# else
-# return "check failed"
-#
-#
-# If the action is not specified on the cmd line, the default action is the
-# fix action defined in the database. Fix is only executed if check fails:
-#
-# if fix defined
-# if check is not defined as null
-# execute check
-# if check succeeds
-# return "ok"
-# execute action defined for fix
-# else
-# return "fixproc error"
-#
-#
-# If proc is not specified on the command line, return "fixproc error."
-# Multiple proc's can be defined on the cmd line. When an error occurs
-# when multiple proc's are specified, the first error encountered halts the
-# script.
-#
-# For check shell scripts, any non-zero exit code means the check has failed.
-#
-#
-# Timothy Kong 3/1995
-
-$database_file = '/local/etc/fixproc.conf';
-
-$debug = 0; # specify debug level using -dN
- # currently defined: -d1
-
-$no_error = 0;
-$check_failed_error = 1;
-$cannot_restart_error = 2;
-$cannot_kill_error = 3;
-$cannot_fix_error = 4;
-$fixproc_error = 10;
-
-$min = 1;
-$max = 1;
-$cmd_line_action = '';
-%min = ();
-%max = ();
-%cmd = ();
-%check = ();
-%fix = ();
-$shell_lines = ();
-@proc_list = ();
-
-$shell_header = "#!/bin/sh\n";
-$shell_end_marker = 'shell_end_marker';
-
-&read_args();
-&read_database();
-# &dump_database(); # debug only
-
-# change the default min. and max. number of processes allowed
-if ($min != 1)
- {
- for $name ( keys (%min) )
- {
- $min{$name} = $min;
- }
- }
-if ($max != 1)
- {
- for $name ( keys (%max) )
- {
- $max{$name} = $max;
- }
- }
-
-# work on one process at a time
-for $proc ( @proc_list )
- {
- $error_code = &work_on_proc ($proc);
-
-############# uncomment next line when fully working ############
-# exit $error_code if ($error_code);
-
- die "error_code = $error_code\n" if ($error_code);
- }
-
-
-# create an executable shell script file
-sub create_sh_script
-{
- local ($file) = pop (@_);
- local ($i) = pop (@_);
-
- printf (stderr "create_sh_script\n") if ($debug > 0);
-
- $! = $fixproc_error;
- open (file, ">"."$file") || die "$0: cannot open $file\n";
- while ( $shell_lines[$i] ne $shell_end_marker )
- {
- printf (file "%s", $shell_lines[$i]);
- $i++;
- }
- close (file);
- system "chmod +x $file";
- return file;
-}
-
-
-sub do_fix
-{
- local ($proc) = pop(@_);
-
- printf (stderr "do_fix\n") if ($debug > 0);
-
- if ($fix{$proc} eq '')
- {
- $! = $fixproc_error;
- die "$0: internal error 4\n";
- }
- if ($fix{$proc} eq 'kill')
- {
- return &do_kill ($proc);
- }
- elsif ($fix{$proc} eq 'restart')
- {
- return &do_restart ($proc);
- }
- else
- {
- # it must be "shell", so execute the shell script defined in database
-
- local ($tmpfile) = "/tmp/fix_$$";
-
- &create_sh_script ($fix{$proc}, $tmpfile);
-
- # return code is number divided by 256
- $error_code = (system "$tmpfile") / 256;
- system "rm $tmpfile";
- return ($fix_failed_error) if ($error_code != 0);
- # sleep needed here?
- return &do_exist ($proc);
- }
-}
-
-
-sub do_check
-{
- local ($proc) = pop(@_);
-
- printf (stderr "do_check\n") if ($debug > 0);
-
- if ($check{$proc} eq '')
- {
- $! = $fixproc_error;
- die "$0: internal error 2\n";
- }
-
- if ($check{$proc} ne 'exist')
- {
- # if not "exist", then it must be "shell", so execute the shell script
- # defined in database
-
- local ($tmpfile) = "/tmp/check_$$";
-
- &create_sh_script ($check{$proc}, $tmpfile);
-
- # return code is number divided by 256
- $error_code = (system "$tmpfile") / 256;
- system "rm $tmpfile";
- return ($check_failed_error) if ($error_code != 0);
-
- # check passed, continue
- }
- return &do_exist ($proc);
-}
-
-
-sub do_exist
-{
- local ($proc) = pop(@_);
-
- printf (stderr "do_exist\n") if ($debug > 0);
-
- # do ps, check to see if min <= no. of processes <= max
- $! = $fixproc_error;
- open (command, "/bin/ps -e | /bin/grep $proc | /bin/wc -l |")
- || die "$0: can't run ps-grep-wc command\n";
- $proc_count = <command>;
- if (($proc_count < $min{$proc}) || ($proc_count > $max{$proc}))
- {
- return $check_failed_error;
- }
- return $no_error;
-}
-
-
-sub do_kill
-{
- local ($proc) = pop(@_);
- local ($second_kill_needed);
-
- printf (stderr "do_kill\n") if ($debug > 0);
-
- # first try kill
- $! = $fixproc_error;
- open (command, "/bin/ps -e | /bin/grep $proc |")
- || die "$0: can't run ps-grep-awk command\n";
- while (<command>)
- {
- # match the first field of ps -e
- $! = $fixproc_error;
- /^\s*(\d+)\s/ || die "$0: can't match ps -e output\n";
- system "kill $1";
- }
-
- # if process still exist, try kill -9
- sleep 2;
- $! = $fixproc_error;
- open (command, "/bin/ps -e | /bin/grep $proc |")
- || die "$0: can't run ps-grep-awk command\n";
- $second_kill_needed = 0;
- while (<command>)
- {
- # match the first field of ps -e
- $! = $fixproc_error;
- /^\s*(\d+)\s/ || die "$0: can't match ps -e output\n";
- system "kill -9 $1";
- $second_kill_needed = 1;
- }
- return ($no_error) if ($second_kill_needed == 0);
-
- # see if kill -9 worked
- sleep 2;
- $! = $fixproc_error;
- open (command, "/bin/ps -e | /bin/grep $proc |")
- || die "$0: can't run ps-grep-awk command\n";
- while (<command>)
- { # a process still exist, return error
- return $cannot_kill_error;
- }
- return $no_error; # good, all dead
-}
-
-
-sub do_restart
-{
- local ($proc) = pop(@_);
- local ($error_code);
-
- printf (stderr "do_restart\n") if ($debug > 0);
-
- $error_code = &do_kill ($proc);
- return $error_code if ($error_code != $no_error);
- die "$0: internal error 3\n" if ($cmd{$proc} eq '');
- system "$cmd{$proc}";
- # sleep needed here?
- if ($check{$proc} ne 'null')
- {
- return $no_error if (&do_check($proc) == $no_error);
- return $cannot_restart_error;
- }
-}
-
-
-sub work_on_proc
-{
- local ($proc) = pop(@_);
- local ($error_code);
-
- printf (stderr "work_on_proc\n") if ($debug > 0);
-
- if ($cmd_line_action eq '')
- {
- # perform action from database
-
- if ($check{$proc} ne 'null')
- {
- $error_code = &do_check ($proc);
- if ($error_code != $check_failed_error)
- {
- return $error_code;
- }
- }
- return &do_fix ($proc);
- }
- else
- {
- # perform action from command line
-
- $error_code = $no_error;
- if ($cmd_line_action eq 'kill')
- {
- $error_code = &do_kill ($proc);
- }
- elsif ($cmd_line_action eq 'restart')
- {
- $error_code = &do_restart ($proc);
- }
- elsif ($cmd_line_action eq 'fix')
- {
- $error_code = &do_fix ($proc);
- }
- elsif ($cmd_line_action eq 'check')
- {
- if ( $check{$proc} eq 'null' )
- {
- exit $fixproc_error;
- }
- $error_code = &do_check ($proc);
- }
- elsif ($cmd_line_action eq 'exist')
- {
- $error_code = &do_exist ($proc);
- }
- else
- {
- $! = $fixproc_error;
- die "$0: internal error 1\n";
- }
- }
-}
-
-
-sub dump_database
-{
- local ($name);
-
- for $name (keys(%cmd))
- {
- printf ("name\t%s\n", $name);
- printf ("cmd\t%s\n", $cmd{$name});
- printf ("min\t%s\n", $min{$name});
- printf ("max\t%s\n", $max{$name});
- if ( $check{$name} =~ /[0-9]+/ )
- {
- printf ("check\tshell\n");
- $i = $check{$name};
- while ( $shell_lines[$i] ne $shell_end_marker )
- {
- printf ("%s", $shell_lines[$i]);
- $i++;
- }
- }
- else
- {
- printf ("check\t%s\n", $check{$name});
- }
- if ( $fix{$name} =~ /[0-9]+/ )
- {
- printf ("fix\tshell\n");
- $i = $fix{$name};
- while ( $shell_lines[$i] ne $shell_end_marker )
- {
- printf ("%s", $shell_lines[$i]);
- $i++;
- }
- }
- else
- {
- printf ("fix\t%s\n", $fix{$name});
- }
- printf ("\n");
- }
-}
-
-
-sub read_database
-{
- local ($in_check_shell_lines) = 0;
- local ($in_fix_shell_lines) = 0;
- local ($name) = '';
- local ($str1);
- local ($str2);
-
- $! = $fixproc_error;
- open (db, $database_file) || die 'cannot open database file $database_file\n';
- while (<db>)
- {
- if ((! /\S/) || (/^[ \t]*#.*$/))
- {
- # ignore blank lines or lines beginning with "#"
- }
- elsif ($in_check_shell_lines)
- {
- if ( /^\s*end_shell\s*$/ )
- {
- $in_check_shell_lines = 0;
- push (@shell_lines, $shell_end_marker);
- }
- else
- {
- push (@shell_lines, $_);
- }
- }
- elsif ($in_fix_shell_lines)
- {
- if ( /^\s*end_shell\s*$/ )
- {
- $in_fix_shell_lines = 0;
- push (@shell_lines, $shell_end_marker);
- }
- else
- {
- push (@shell_lines, $_);
- }
- }
- else
- {
- if ( ! /^\s*(\S+)\s+(\S.*)\s*$/ )
- {
- $! = $fixproc_error;
- die "$0: syntax error in database\n$_";
- }
- $str1 = $1;
- $str2 = $2;
- if ($str1 eq 'name')
- {
- &finish_db_entry($name);
- $name = $str2;
- }
- elsif ($str1 eq 'cmd')
- {
- $! = $fixproc_error;
- die "$0: cmd specified before name in database\n$_\n"
- if ($name eq '');
- die "$0: cmd specified multiple times for $name in database\n"
- if ($cmd{$name} ne '');
- $cmd{$name} = $str2;
- }
- elsif ($str1 eq 'min')
- {
- $! = $fixproc_error;
- die "$0: min specified before name in database\n$_\n"
- if ($name eq '');
- die "$0: min specified multiple times in database\n$_\n"
- if ($min{$name} ne '');
- die "$0: non-numeric min value in database\n$_\n"
- if ( ! ($str2 =~ /[0-9]+/ ));
- $min{$name} = $str2;
- }
- elsif ($str1 eq 'max')
- {
- $! = $fixproc_error;
- die "$0: max specified before name in database\n$_\n"
- if ($name eq '');
- die "$0: max specified multiple times in database\n$_\n"
- if ($max{$name} ne '');
- die "$0: non-numeric max value in database\n$_\n"
- if ( ! ($str2 =~ /[0-9]+/ ));
- $max{$name} = $str2;
- }
- elsif ($str1 eq 'check')
- {
- $! = $fixproc_error;
- die "$0: check specified before name in database\n$_\n"
- if ($name eq '');
- die "$0: check specified multiple times in database\n$_\n"
- if ($check{$name} ne '');
- if ( $str2 eq 'shell' )
- {
- # if $check{$name} is a number, it is a pointer into
- # $shell_lines[] where the shell commands are kept
- $shell_lines[$#shell_lines+1] = $shell_header;
- $check{$name} = $#shell_lines;
- $in_check_shell_lines = 1;
- }
- else
- {
- $check{$name} = $str2;
- }
- }
- elsif ($str1 eq 'fix')
- {
- $! = $fixproc_error;
- die "$0: fix specified before name in database\n$_\n"
- if ($name eq '');
- die "$0: fix specified multiple times in database\n$_\n"
- if ($fix{$name} ne '');
- if ( $str2 eq 'shell' )
- {
- # if $fix{$name} is a number, it is a pointer into
- # $shell_lines[] where the shell commands are kept
- $shell_lines[$#shell_lines+1] = $shell_header;
- $fix{$name} = $#shell_lines;
- $in_fix_shell_lines = 1;
- }
- else
- {
- $fix{$name} = $str2;
- }
- }
- }
- }
- &finish_db_entry($name);
-}
-
-
-sub finish_db_entry
-{
- local ($name) = pop(@_);
-
- if ($name ne '')
- {
- $! = $fixproc_error;
- die "$0: fix not defined for $name in database\n"
- if ($fix{$name} eq '');
- die "$0: cmd not defined for $name in database\n"
- if ($cmd{$name} eq '');
- $check{$name} = 'exist' if ($check{$name} eq '');
- $max{$name} = 1 if ($max{$name} eq '');
- $min{$name} = 1 if ($min{$name} eq '');
- }
-}
-
-
-sub read_args
-{
- local ($i) = 0;
- local ($arg);
- local ($action_arg_count) = 0;
-
- while ( $i <= $#ARGV )
- {
- $arg = $ARGV[$i];
- if (($arg eq '-min') || ($arg eq '-max'))
- {
- if (($i == $#ARGV - 1) || ($ARGV[$i+1] =~ /\D/)) # \D is non-numeric
- {
- $! = $fixproc_error;
- die "$0: numeric arg missing after -min or -max\n";
- }
- if ($arg eq '-min')
- {
- $min = $ARGV[$i+1];
- }
- else
- {
- $max = $ARGV[$i+1];
- }
- $i += 2;
- }
- elsif ($arg eq '-kill')
- {
- $cmd_line_action = 'kill';
- $action_arg_count++;
- $i++;
- }
- elsif ($arg eq '-check')
- {
- $cmd_line_action = 'check';
- $action_arg_count++;
- $i++;
- }
- elsif ($arg eq '-restart')
- {
- $cmd_line_action = 'restart';
- $action_arg_count++;
- $i++;
- }
- elsif ($arg eq '-exist')
- {
- $cmd_line_action = 'exist';
- $action_arg_count++;
- $i++;
- }
- elsif ($arg eq '-fix')
- {
- $cmd_line_action = 'fix';
- $action_arg_count++;
- $i++;
- }
- elsif ($arg =~ /-d(\d)$/)
- {
- $debug = $1;
- $i++;
- }
- elsif ($arg =~ /^-/)
- {
- $! = $fixproc_error;
- die "$0: unknown switch $arg\n";
- }
- else
- {
- push (@proc_list, $arg);
- $i++;
- }
- }
- $! = $fixproc_error;
- die "$0: no process specified\n" if ($#proc_list == -1);
- die "$0: more than one action specified\n" if ($action_arg_count > 1);
- }
-