3

Is there a pkill-like tool which does this:

  1. send signal to all matching processes
  2. wait N seconds until the processes have terminated
  3. if all processes have terminated, nice: exit
  4. if some processes have not terminated send SIGKILL

For me it is important that the tool waits until the processes have really terminated.

I know that it is quite easy to do this in my favourite scripting language, but in this case it would be very nice if I use a tool which already exists.

This needs to run on SuSE-Linux and Ubuntu.

2
  • 1
    Before and after the wait, how would one determine that the list of PIDs corresponds to the same set of processes (and weren't recycled)? Alternatively, how would one determine that the matched command names before and after corresponds to the same processes? Even if you save (command_name, PID) tuples, one can't be 100% sure that these are "correct" both before and after the wait. There's a inherent race-condition here.
    – Kusalananda
    Jan 29, 2018 at 11:09
  • @Kusalananda yes, you are right. There will be some guessing involved. And this means it is not a 100% reliable solution.
    – guettli
    Jan 29, 2018 at 16:17

3 Answers 3

9

There is no “standard” command which provides the behaviour you’re after. However, on Debian and derivatives, you can use start-stop-daemon’s --stop action with the --retry option:

start-stop-daemon --stop --oknodo --retry 15 -n daemontokill

will send SIGTERM to all processes named daemontokill, wait up to 15s for them to stop, then send SIGKILL to all remaining processes (from the initial selection), and wait another 15s for them to die. It will exit with status 0 if there was nothing to kill or all the processes stopped, 2 if some processes were still around after the second timeout.

There are a number of options to match processes in various ways, see the documentation (linked above) for details. You can also provide a more detailed schedule with varying timeouts.

start-stop-daemon is part of the dpkg package so it’s always available on Debian systems (and derivatives). Some non-.deb distributions make the package available too; for example, openSUSE Leap 42 has it. It’s quite straightforward to build on other platforms:

git clone https://salsa.debian.org/dpkg-team/dpkg.git 
cd dpkg
autoreconf -fi && ./configure && make

You’ll need autoconf, automake, libtool, gettext. Once the build is finished you’ll find start-stop-daemon in the utils directory.

5
  • I need to support Ubuntu and SuSE. It seems that start-stop-daemon is not available for SUSE :-(
    – guettli
    Jan 24, 2018 at 9:10
  • Right, it’s not available on SuSE, but it’s fairly easy to build (see the source code). Jan 24, 2018 at 9:13
  • A solution without building (even if it is easy) would be nice :-)
    – guettli
    Feb 7, 2018 at 12:37
  • Is an openSUSE Leap package any use to you? Feb 7, 2018 at 13:02
  • Try killall procname; sleep 15; killall -9 procname
    – ingopingo
    Feb 8, 2018 at 14:27
6
+50

You can use the timeout command with killall -w

e.g:

# timeout 3 killall -vws2 $PROCESS_NAME || killall -vws9 $PROCESS_NAME

timeout will "timeout" after 3 secends and will exit with error code, which then you catch with || and then run killall -s9 to force the kill.

2

You can create your own script that will fulfil your case. Following this post useless use of kill -9 and source reallykill

#!/bin/sh
#
# $Id: reallykill,v 1.2 2004/10/11 09:36:48 jmates Exp $
#
# The author disclaims all copyrights and releases this script into the
# public domain.
#
# Kills the specified processes by starting with the TERM signal and
# only if necessary working up to the violent KILL signal. For more
# information, see:
#
# http://sial.org/howto/shell/kill-9/

if [ -z "$1" ]; then
  echo "usage: `basename $0` pid [pid ..]" >&2
  exit 100
fi

cycle_kill () {
  PID=$1
  RETVAL=0

  for signal in "TERM" "INT" "HUP" "KILL"; do
    kill -$signal $PID
    RETVAL=$?
    [ $RETVAL -eq 0 ] && break
    echo "warning: kill failed: pid=$PID, signal=$signal" >&2
    sleep 1
  done

  return $RETVAL
}

for pid in "$@"; do
  cycle_kill $pid
done

So you can just download script to your bin directory:

 curl http://web.archive.org/web/20080213192428if_/http://sial.org:80/howto/shell/kill-9/reallykill > $HOME/bin/killwait && chmod +x $HOME/bin/killwait

I would use this that way:

ping -q localhost &
killwait `pidof ping`

Maybe you would like to change order of signals with INT as first, so you would have output with summary of ping command. Provided command does not wait if KILL signal succeed but it should work as process will be killed by system.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.