2016-06-10 8 views
1

0 Ich habe ein sehr kurzes Skript geschrieben, das PID von $ 1 bekommt, dann tötet den Prozess. Ich habe ein paar Fragen/Verbesserungswünsche. (OSX)Verwenden von ps und awk, um pid zu bekommen, und dann

#!/bin/bash 

getpid=$(ps aux -O start | grep -i "$1" | grep -v grep | grep -v $0 | awk '{ if (NR==1) {print $2}}') 

kill $getpid 

Zum Beispiel:

$ ~/killpro.sh java 

, die die jüngste Instanz von Java tötet.

Oder:

$ ~/killpro.sh chrome 

zu töten Google Chrome, offensichtlich.

Erstens ist es eine praktische Möglichkeit, diese zusammen zu einer einzigen Linie aufgereiht werden, vielleicht mit lesen -p, so dass es wiederum aliased und so etwas wie werden kann:

$ killpro 
$ Enter name: chrome 
$ 

Nicht, dass es wesentlich einfacher, in der Tat ist es etwas mehr Arbeit, aber es umgeht die Notwendigkeit, einen Pfad und Shell-Erweiterung, die wünschenswert ist, eingeben.

Zweitens, gibt es irgendetwas grundsätzlich falsch mit meinem ursprünglichen Ansatz/fehlt mir etwas Offensichtliches, das die Notwendigkeit für das alles negiert?

Jede Rückmeldung wird geschätzt.

Vielen Dank im Voraus, ich bin (wie Sie sagen) neu zu diesem Thema.

+0

Hat OS X nicht einen 'killall' oder' pidof' Befehl? – melpomene

+0

@melpomene: Es hat 'killall', aber es kann nicht nur den neuesten Prozess töten. Kein 'Pidof', aber es ist leicht genug zu implementieren. – Amadan

+2

Shell-Skripte können beliebigen Namen haben. Die Erweiterung '.sh' dient nur dazu, anzuzeigen, was drin ist. Sie könnten 'file killpro' verwenden und es würde etwas wie' shell script' melden. Also nenne einfach dein Skript 'killpro'. DANN brauchst du ein lokales Verzeichnis, normalerweise '~/usr/local/bin', um dein Skript zu speichern UND dein' .bashrc' oder anderswo zu editieren, um 'export PATH =" ~/usr/local/bin: $ PATH "' anzuzeigen. Dann sind keine lästigen Funktions- oder Aliasdefinitionen erforderlich. Gib einfach 'killpro' ein und es wird ausgeführt. Viel Glück. – shellter

Antwort

0

Sie nur awk allein mit getline nutzen könnten, um ps zu rufen und erhalten die gewünschten Daten:

awk -vv_kp="bash" 'BEGIN{ cmd="ps -axu -O T | grep "v_kp" |head -1"; cmd | getline var; close(cmd); split(var,var2," ");print var2[2];}'

oder weniger awk, mehr Schale:

awk -vv_kp="bash" 'BEGIN{ cmd="ps -axu -O T | grep "v_kp" |head -1|cut -d\" \" -f2"; cmd | getline var; close(cmd); print var;}'

1

Die meisten Skripte mit grep | awk sind ein useless use of grep und sollte umgestaltet werden, um nur Awk zu verwenden.

#!/bin/bash 

# Maybe add a case for $# > 1 and quit with an error message 
# Or maybe loop over arguments if there is more than one 
case $# in 0) read -p "Process name? " proc;; *) proc=$1;; esac 

# Maybe your ps aux doesn't have the command in $11 -- adapt 
kill $(ps aux -O start | 
    awk -v name="$proc" 'NR>1 && tolower($11) ~ tolower(name) {print $2}') 

Ihre Kommentare zeigen Sie die „neuesten“ Prozess zu töten suchen (durch die Metrik?), Aber der Code, und dieser Code versucht, alle Instanzen zu töten. Wenn Sie den zuletzt gestarteten Prozess möchten, ist die PID kein guter Indikator; Sie sollten sich die Startzeiten des Prozesses ansehen. Die Ausgabe von ps ist stark systemabhängig. Sie sollten daher wahrscheinlich eine separate Frage mit weiteren Details zu Ihrem Betriebssystem veröffentlichen, wenn Sie Hilfe benötigen, um das herauszufinden.

Dieses spezielle Problem wird hier regelmäßig mehrere Male pro Monat zu Tode geprügelt, also sollten Sie sich andere Implementierungen zur Inspiration ansehen. Meine Empfehlung wäre "mach das nicht", aber da du es bereits getan hast, ist es wahrscheinlich sinnvoll, auf die Fehler hinzuweisen und den Code zu verfestigen. Aber wenn Sie keinen zwingenden Grund haben, warum Sie pkill nicht installieren können, sollten Sie wahrscheinlich nur das verwenden (und wenn Sie dies tun, ist die Verwendung eines ordnungsgemäß debuggten und getesteten Skripts viel besser als das Schreiben eines eigenen von Grund auf neu).

+0

Ich habe meinen Kommentar entfernt, weil es davon abhängt, wie das OP den * letzten * Prozess ermitteln will. Aber wahrscheinlich werden "neueste" und "älteste" Flags von "pgrep/pkill" für das OP funktionieren. Am Ende kann ich mir Anwendungsfälle vorstellen, bei denen "awk" immer noch praktisch ist, aber zuerst könnte man versuchen, die Aufgabe mit 'pgrep/pkill' zu lösen. – hek2mgl

+1

Danke für die Kommentare. Fügte einen Zeiger zu 'pkill' zum letzten Absatz von Gedanken hinzu. – tripleee

+0

Warum ist die PID kein guter Indikator? (Ich frage unschuldig; ich denke, es ist wert, den Grund in der Antwort zu erwähnen.) @ Hek2mgl: guter Tipp re 'pgrep' /' pkill'; sie sind tatsächlich auf OS X vorinstalliert (auf dem das OP läuft), unterstützen aber dort keine _long_ Optionen (BSD-Implementierungen); '-n' für' -neueste', '-o' für' -älteste' funktionieren jedoch. – mklement0

3

Mein Rat ist, stattdessen pkill zu verwenden. Von der Manpage:

NAME 
pgrep, pkill -- find or signal processes by name 
Verwandte Themen