h1

prill – Prozess nach Namen killen

Oktober 8, 2008

Manchmal kommt man in die nervige Situation, dass ein Programm oder der ganze X-Server einfriert und sich nicht mehr normal beenden lassen will. Dann hilft nur noch das killen per ProzessID vom Terminal aus.

Mein Vorgehen sieht dabei meist so aus, dass ich mir mit ps -aux alle Prozesse ausgeben lasse, diese mit grep filtere und dann die jeweilige PID für kill abschreibe. Vereinfachen kann man das ganze schonmal so:

[thomas@jane ~]$ ps -aux | grep MUSTER | awk ‚{print $1}‘ | xargs kill

Damit werden immerhin schon die PIDs aus dem Ergebnis von grep herausgefiltert und an xargs übergeben. Xargs ruft dann wiederrum kill auf und übergibt als Parameter die PID des Prozesses. Das Problem dabei, man sieht nicht wirklich, ob man nur den/die richtigen Prozesse gekillt hat oder ob auch falsche dabei waren.

Also habe ich ein Programm geschrieben, welches das oben genannte macht, aber vor jedem kill nachfragt, ob das ein Prozess ist, der gekillt werden soll. Der Name prill ist einfach mangels Kreativität die Zusammensetzung von ps, grep und kill. Hier mal ein Beispiel für den Aufruf von prill:

[root@jane ~]# prill.sh evince
evince Dokumente/2008-03_PCWL-eBooklet.pdf
Killen? (y/n) n

evince Dokumente/python.pdf
Killen? (y/n) y
kill Prozess 5873 evince Dokumente/python.pdf[KILLED]

Hier der komplette bisherige Quellcode:

#!/bin/bash

#Zu wenig Parameter
if [ $# == 0 ];
then
    echo
    echo "Falscher Aufruf!!!";
    echo "Richtige Benutzung:";
    echo "$0 SUCHBEGRIFF";
    echo
    exit
elif [ $# == 2 ];
then
    if [ "$2" == "-g" ]; # Welcher Parameter ist die Option, welcher das Suchmuster
    then
        GLOBAL="TRUE"
        PATTERN=$1
    elif [ "$1" == "-g" ];
    then
        GLOBAL="TRUE"
        PATTERN=$2
    fi;
else
    PATTERN=$1
fi;
#For-Schleife durchläuft jede Zeile des voherigen Befehls
ps x | grep "$PATTERN" | grep -v "grep" | grep -v $0 | while read x;
    do
        if [ "$GLOBAL" == "TRUE" ]; # Nicht immer nachfragen, alles killen
        then
            yon="y"
        else
            echo $x | awk '{print $5 " " $6 " " $7 " " $8}'
            echo -n "Killen? (y/n) ";
            read -u1 yon
        fi

        if [ "$yon" == "y" ];
        then
            pid=`echo $x | awk '{print $1}'`
            echo -n "kill Prozess "
            echo -n `echo $x | awk '{print $1 " " $5 " " $6 " " $7 " " $8 " "}'`
            kill $pid && echo "[KILLED]"
        fi;
        echo
    done;

Zu den 2 letzten grep-aufrufen sollte man vielleicht noch sagen, dass die option ‚-v‘ alle Zeilen wegstreicht, die auf das Muster passen. Damit soll einfach der grep-Prozess und der Prozess von prill selbst gestrichen werden, weil man diese ja nicht killen will, sie aber auf das Muster vom ersten grep passen.

read -u1 yon

die Option ‚-u1‘ muss explizit angeben werden, damit dieses read nicht auch die Ausgabe von dem Ausdruck vor der For-Schleife benutzt, sondern von der Standardeingabe liest.

Sollten das Programm irgendwann mal mehr als 2 verschiedenen Parameter haben können, sollte man sicherlich den ersten Teil nochmal deutlich überarbeiten und auf jeden Parameter eine Funktion anwenden, die diesen auswertet.

Über Feedback und Verbesserungsvorschläge würde ich mich sehr freuen. =)

5 Kommentare

  1. Warum überhaupt so kompliziert?
    Habe eben mal den Post von noqqe rausgesucht, der über ein ähnliches Problem berichtet hatte:
    http://seufz.wordpress.com/2008/07/30/firefox3-close-quickie-guide-d/

    Da habe ich auch den Tipp mit „htop“ gegeben:
    „Oder so wie ich es mache:

    Konsole auf, “htop” starten (muss installiert sein), da einfach Firefox raussuchen und mit F9 abschießen. ;)“


  2. Jop aber der wille zählt und für den Programmieraufwand würd ich aufjedenfall ein dickes Plus geben!

    aber ich würde dir noch zu einer einbindung in path raten!
    ansonsten ists umständlich


  3. Ok, danke für das Plus =)
    Aber ich habe es sogar in PATH eingebunden, wenn wir das gleiche meinen. Also ich hatte erst das Programm in ~/bin liegen und dann ~/bin in die PATH-variable mit reingeschrieben. Also eine Anweisung:
    export PATH=$PATH“:~/bin“
    in der .bashrc
    Aber damit alle Benutzer es benutzen können, habe ich es dann auch noch nach /usr/local/bin kopiert und auch dieses Verzeichnis steht in der PATH variable.

    Danke auch für den Tipp mit htop. Ich habe heute morgen überlegt, ob es eventuell für xargs eine Option gibt, die jedes mal nachfragt, bevor ein Befehl aufgerufen wird, werde auch gleich mal nachgucken ob es sowas gibt. Das würde ja das Problem auch auf relativ einfache Weise lösen.

    Aber zum Andern war es auch als Herausforderung gedacht, mal ein kleines Bash-script zu schreiben um den Umgang wenigstens ein wenig zu erlernen. Montag bekomme ich ja dann zum Geburtstag hoffentlich das Buch Shell-Programmierung, vom Galileo Press Verlag, geschenkt =)


  4. Hmm also es gibt die Option –interactive von xargs die genau das mit dem Nachfragen macht. Das Problem an der Sache ist, dass die PIDs alle mit einmal übergeben werden und nicht für jede PID xargs neu aufgerufen wird. Also Beispiel:

    ps aux | grep evince | awk ‚{print $2}‘ | xargs –interactive kill

    Das übergibt mit einem mal für alle laufenden evince Prozesse die PIDs an xargs – Sinnvoll ist xargs –interactive aber nur, wenn es für jede PID aufgerufen wird. Hat jemand dafür einen Vorschlag?


  5. pkill -9 vi

    killt den Prozess „vi“
    -9 steht dabei für SIGKILL

    Codes wie SIGKILL erhält man mit „kill -l“ (minus L)
    damit man nicht soviel schreiben muss



Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: