pslist-1.3/000755 001750 000000 00000000000 11210741236 012757 5ustar00roamwheel000000 000000 pslist-1.3/CHANGES000644 001750 000000 00000002263 11210741132 013750 0ustar00roamwheel000000 000000 This is the changelog for pslist. 1.3 2009/06/01 - Improve the documentation (in the README file, the manual page and the pslist usage message) as suggested by Ben Finney: - shorten the single-line description - the plural of "ID" is "IDs", not "ID's" - Correct the manual page - pslist does not output "numbers" :) - Fix the spacing in the pslist help text. - Add two more missing mentions of rrenice in the README file. 1.2 2009/05/25 - Correct the help and usage messages. - Add a simple manual page. 1.2pre1 2009/05/22 - Really honor DESTDIR. - Remove the Debian package files - their place is definitely not in the upstream distribution. - Add "renice" information to the README file. - Reformat this changelog. - Add a to-do list. 1.1 2005/01/03 - Slap a two-clause BSD license on the source and build files. - Change my e-mail address to . - Add Debian package files. - Let the user specify DESTDIR for installation. 1.1pre1 2000/12/09 - Add renice functionality when invoked with a name ending in 'nice'. 1.0 2000/10/27 - Initial release of version 1.0. Peter Pentchev $Ringlet: CHANGES 3735 2009-06-01 11:58:18Z roam $ pslist-1.3/Makefile000644 001750 000000 00000004724 11206470740 014432 0ustar00roamwheel000000 000000 # Copyright (c) 2000, 2005, 2009 Peter Pentchev # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $Ringlet: Makefile 3631 2009-05-25 10:24:32Z roam $ # install recipe INSTALL ?= install INSTALL_COPY ?= -c INSTALL_OWN ?= -o root INSTALL_MODE_S ?= -m 555 INSTALL_MODE_D ?= -m 644 INSTALL_SCRIPT ?= ${INSTALL} ${INSTALL_COPY} ${INSTALL_OWN} ${INSTALL_MODE_S} INSTALL_DATA ?= ${INSTALL} ${INSTALL_COPY} ${INSTALL_OWN} ${INSTALL_MODE_D} # where to install PREFIX ?= /usr/local BINDIR ?= ${PREFIX}/bin MANDIR ?= ${PREFIX}/man/man MAN1DIR ?= ${MANDIR}1 # some other useful programs ECHO ?= echo FALSE ?= false GZIP ?= gzip -c9 LN ?= ln MKDIR ?= mkdir -p RM ?= rm -f PROG = pslist RKILL = rkill RRENICE = rrenice MAN1 = ${PROG}.1 MAN1GZ = ${PROG}.1.gz all: ${MAN1GZ} install: ${MKDIR} ${DESTDIR}${BINDIR} ${INSTALL_SCRIPT} ${PROG} ${DESTDIR}${BINDIR} ${LN} -s ${PROG} ${DESTDIR}${BINDIR}/${RKILL} ${LN} -s ${PROG} ${DESTDIR}${BINDIR}/${RRENICE} ${MKDIR} ${DESTDIR}${MAN1DIR} ${INSTALL_DATA} ${MAN1GZ} ${DESTDIR}${MAN1DIR} ${LN} -s ${MAN1GZ} ${DESTDIR}${MAN1DIR}/${RKILL}.1.gz ${LN} -s ${MAN1GZ} ${DESTDIR}${MAN1DIR}/${RRENICE}.1.gz ${MAN1GZ}: ${MAN1} ${GZIP} ${GZIP_ARGS} ${MAN1} > ${MAN1GZ} || (${RM} ${MAN1GZ}; ${FALSE}) clean: ${RM} ${MAN1GZ} pslist-1.3/README000644 001750 000000 00000006061 11210741062 013637 0ustar00roamwheel000000 000000 This is the README for pslist version 1.3. 1. What it is. pslist is a simple utility to list the process IDs of a process and all its children, and its children's children, and so on. If invoked with a command name which ends in 'kill', it sends a signal to a selected group of processes. If invoked with a command name which ends in 'nice', it renices the selected group of processes to a specified value. 2. Compile/install No compilation is needed - this is a Perl script :) Installation is as simple as copying pslist into an appropriate directory, and possibly making a symlink to it with a name ending in 'kill' or 'renice' to make use of the recursive kill or renice functionality. The provided Makefile installs pslist into /usr/local/bin and symlinks it to /usr/local/bin/rkill and /usr/local/bin/rrenice. All you have to do is type 'make install'. 3. Usage If invoked as anything not ending in 'kill', pslist shall display a list of processes' info. Each process having at least one child is shown on a single line listing its process ID, its name, and all its children's PIDs. pslist may be invoked with one or more arguments, which are interpreted as either PIDs if numeric, or as process names. In this case, pslist only displays information about the specified processes. If invoked with a command name ending in 'kill' (like the rkill in the default install), pslist shall attempt to send a signal to all the specified processes and all their children. A signal number or name may be given before the process list on the command line, using the same format as with kill(1). 4. License (standard two-clause BSD) Copyright (c) 2000, 2005, 2009 Peter Pentchev All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5. That's all, folks! Hope you like it; if you don't, well, it's a free world (mostly). Peter Pentchev $Ringlet: README 3733 2009-06-01 11:57:38Z roam $ pslist-1.3/pslist.1000644 001750 000000 00000005163 11210740423 014361 0ustar00roamwheel000000 000000 .\" Copyright (c) 2009 Peter Pentchev .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $Ringlet: pslist.1 3730 2009-06-01 11:52:51Z roam $ .\" .Dd June 1, 2009 .Dt PSLIST 1 .Os .Sh NAME .Nm pslist .Nd control processes and their descendants .Sh SYNOPSIS .Nm .Op Ar pid/name... .Nm .Ar -h | --help .Nm .Ar -v | --version .Pp .Nm rkill .Op Fl SIG .Ar pid/name... .Pp .Nm rrenice .Ar [+/-]pri .Ar pid/name... .Sh DESCRIPTION The .Nm utility examines the list of current processes to find a specified process and all its descendants. A process may be specified either by name or by process ID. If no arguments are given, .Nm displays a list of the whole process tree. For each process specified on the command line, .Nm outputs a line containing the process ID, the command name, and the PIDs of all the descendants (and their descendants, etc.). .Pp When invoked as .Nm rkill , this utility does not display information about the processes, but sends them all a signal instead. If not specified on the command line, a terminate (SIGTERM) signal is sent. .Pp When invoked as .Nm rrenice , this utility does not display information about the processes, but attempts to set their nice value instead. .Sh RETURN VALUES .Ex -std .Sh SEE ALSO .Xr pgrep 1 , .Xr pkill 1 .Sh HISTORY The .Nm utility was written by .An Peter Pentchev in 2000. .Sh AUTHORS .An Peter Penchev .Aq roam@ringlet.net pslist-1.3/pslist000755 001750 000000 00000017345 11210740613 014233 0ustar00roamwheel000000 000000 #!/usr/bin/perl -w # # Copyright (c) 2000, 2005, 2009 Peter Pentchev # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # $Ringlet: pslist 3732 2009-06-01 11:54:51Z roam $ use strict; my($PS, $PSflags) = ("/bin/ps", "axco pid,ppid,command"); my(%proc) = (); my(%parproc) = (); # Function: # help - display usage information # Inputs: # $err - error code; non-zero for program termination # Returns: # nothing; calls exit() if $err is non-zero # Modifies: # nothing; writes to STDOUT # If $err is non-zero, writes to STDERR and exits. sub help { my($err) = @_; my($s) = "Usage:\n" ." pslist [pid/name...] - list child pids\n" ." rkill [-sig] pid/name... - kill a process and its children\n" ." rrenice [+/-]pri pid/name... - renice a process and its children\n" ."\n" ."The priority for rrenice may be specified as an absolute value, or as\n" ."a +/- delta to current process priority.\n" ."At least one pid/name argument is mandatory for rkill and rrenice.\n" ; if ($err) { print STDERR $s; exit($err); } else { print $s; } } # Function: # version - output program version information # Inputs: # none # Returns: # nothing # Modifies: # nothing; writes to STDOUT sub version { print "pslist 1.3 - control processes and their descendants\n"; } # Function: # proc_gather - parse ps output to fill out process arrays # Inputs: # none # Returns: # nothing # Modifies: # fills out %proc and %parproc # invokes a pipe to 'ps' sub proc_gather { my($line); open(PS, "$PS $PSflags |") or die("failed to invoke '$PS $PSflags' - $!\n"); while(defined($line = )) { chomp $line; if ($line =~ /^\s*(\d+)\s+(\d+)\s+(\S+)(.*)$/) { my($pid, $ppid, $cmd, $args) = ($1, $2, $3, $4); $proc{$pid} = {'ppid'=>$ppid, 'cmd'=>$cmd, 'args'=>$args}; $parproc{$ppid} .= "$pid "; } } close PS; } # Function: # proc_display - display a process and its children # Inputs: # $pid - process ID to display # Returns: # nothing # Modifies: # nothing by itself; writes to STDOUT and calls proc_get_children_r() sub proc_display { my($pid) = shift; my(@arr); @arr = proc_get_children_r($pid); print "$pid $proc{$pid}{'cmd'} @arr\n"; } # Function: # proc_display_all - display all processes and children lists # Inputs: # none # Returns: # nothing # Modifies: # nothing by itself; calls proc_display() sub proc_display_all { my($pid); foreach $pid (keys(%parproc)) { proc_display($pid); } } # Function: # proc_kill - recursively kill a process and its children # Inputs: # $pid - PID to kill # $sig - signal to send # Returns: # 0 on success # negative number of unkilled children on failure, $! is set sub proc_kill { my($pid, $sig) = @_; my(@arr); die("bad pid ($pid)\n") if ($pid !~ /^\d+$/); die("non-existent pid ($pid)\n") unless defined($proc{$pid}); $arr[0] = $pid; push(@arr, proc_get_children_r($pid)); print "@arr "; return kill($sig, @arr) - ($#arr + 1); } # Function: # proc_nice - recursively renice a process and its children # Inputs: # $pid - PID to kill # $sig - signal to send # Returns: # 0 on success # negative number of unkilled children on failure, $! is set sub proc_nice { my($pid, $delta) = @_; my(@arr); my($kpid, $exact) = (0, 1); die("bad pid ($pid)\n") if ($pid !~ /^\d+$/); die("non-existent pid ($pid)\n") unless defined($proc{$pid}); $exact = 0 if ($delta =~ /^[+-]/); $arr[0] = $pid; push(@arr, proc_get_children_r($pid)); print "@arr "; foreach $kpid (@arr) { if ($exact) { setpriority(0, $kpid, $delta) or return -1; } else { my($cpri) = getpriority(0, $kpid); setpriority(0, $kpid, $cpri + $delta) or return -1; } } return 0; } # Function: # proc_get_children_r - get a list of PIDs of a process's child tree # Inputs: # $pid - PID to examine # Returns: # array of children PIDs # Modifies: # nothing; calls proc_get_children() sub proc_get_children_r { my($pid, $i) = (shift || 0, 0); my(@chi) = (); my(@res) = (); @chi = proc_get_children($pid); return () if ($#chi == -1); for($i = 0; $i <= $#chi; $i++) { next if $chi[$i] == 0; $res[++$#res] = $chi[$i]; push(@res, proc_get_children_r($chi[$i])); } return @res; } # Function: # proc_get_children - get a list of a process's immediate children # Inputs: # $pid - process ID to examine # Returns: # array of children PIDs # Modifies: # nothing sub proc_get_children { my($pid) = (shift || 0); my(@arr) = (); my($s); return () unless defined($parproc{$pid}); $s = $parproc{$pid}; while($s =~ /^(\d+) (.*)/) { $arr[++$#arr] = $1; $s = $2; } return @arr; } # Main block MAIN:{ my($killem, $niceem, $killpid) = (0, 0, 0); my($sig) = 15; # check for help, version if ($#ARGV > -1) { if (($ARGV[0] eq '-h') || ($ARGV[0] eq '--help')) { version(); help(0); exit(0); } if (($ARGV[0] eq '-v') || ($ARGV[0] eq '--version')) { version(); exit(0); } } # are we invoked as pslist, rkill, or rrenice? if ($0 =~ /kill$/) { help(1) if ($#ARGV == -1); if ($ARGV[0] =~ /^-(.*)/) { help(1) if ($#ARGV == 0); $sig = $1; shift @ARGV; } $killem = 1; } elsif ($0 =~ /nice$/) { help(1) if (($#ARGV < 1) || (($ARGV[0] !~ /^[+-]?\d+$/))); $sig = $ARGV[0]; shift @ARGV; $niceem = 1; } # Let the user override the ps program location and flags $PS = $ENV{'PS'} if (defined($ENV{'PS'})); $PSflags = $ENV{'PSflags'} if (defined($ENV{'PSflags'})); proc_gather(); # no arguments, no kill requested - display all and exit if (($#ARGV == -1) && !($killem || $niceem)) { exit(proc_display_all()); } # either a kill request, or specific processes display foreach $killpid (@ARGV) { # pid or process name? if ($killpid =~ /^\d+$/) { # pid.. die("nonexistent pid $killpid\n") unless defined($proc{$killpid}); if ($killem) { (proc_kill($killpid, $sig) == 0) || die("rkill($killpid) failed - $!\n"); } elsif ($niceem) { (proc_nice($killpid, $sig) == 0) || die("rrenice($killpid) failed - $!\n"); } else { proc_display($killpid); } } else { # process name.. my($pid); foreach $pid (keys(%proc)) { if ($proc{$pid}{'cmd'} eq $killpid) { if ($killem) { (proc_kill($pid, $sig) == 0) || die("rkill($pid) failed - $!\n"); } elsif ($niceem) { (proc_nice($pid, $sig) == 0) || die("rrenice($pid) failed - $!\n"); } else { proc_display($pid); } } } } } print "\n" if ($killem); }