2016-06-10 1 views
1

J'ai écrit un script très court qui obtient un pid de $ 1 puis tue le processus. J'ai quelques questions/demandes d'amélioration. (OSX)Utiliser ps et awk pour obtenir pid, puis le tuer

#!/bin/bash 

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

kill $getpid 

Par exemple:

$ ~/killpro.sh java 

qui tue l'instance la plus récente de java.

Ou:

$ ~/killpro.sh chrome 

Pour tuer Google Chrome, évidemment.

D'abord, est-il un moyen pratique pour obtenir ce enfilés en une seule ligne, à l'aide de lire -p peut-être, afin qu'il puisse à son tour être aliasé et devenir quelque chose comme:

$ killpro 
$ Enter name: chrome 
$ 

Non pas que ce beaucoup plus facile, en fait c'est un peu plus de travail, mais cela contourne le besoin de taper un chemin et une extension de coque qui est souhaitable. Deuxièmement, y a-t-il quelque chose de fondamentalement faux dans mon approche initiale? Ai-je manqué quelque chose d'évident qui annule le besoin de tout cela?

Tout commentaire est apprécié.

Merci d'avance, je suis (comme vous pouvez le dire) nouveau à cela.

+0

OS X n'a-t-il pas une commande 'killall' ou' pidof'? – melpomene

+0

@melpomene: Il a 'killall', mais il ne peut pas tuer seulement le dernier processus. Pas de "pidof", mais c'est assez facile à implémenter. – Amadan

+2

Les scripts shell peuvent avoir n'importe quel nom. l'extension '.sh' est juste pour indiquer ce qui s'y trouve. Vous pourriez utiliser 'file killpro' et cela rapporterait quelque chose comme' shell script'. Alors nommez votre script 'killpro'. ALORS vous avez besoin d'un répertoire local, communément '~/usr/local/bin' pour stocker votre script ET éditer votre' .bashrc' ou ailleurs pour indiquer 'export PATH =" ~/usr/local/bin: $ PATH "'. Alors aucune fonction embêtante ou définitions d'alias requises. Tapez simplement 'killpro' et il fonctionnera. Bonne chance. – shellter

Répondre

0

Vous pouvez simplement utiliser awk seul avec getline pour appeler à ps et obtenir les données que vous voulez:

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];}'

ou moins awk, plus shell:

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

La plupart des scripts avec grep | awk sont un useless use of grep et devraient être refactorisés pour utiliser juste Awk.

#!/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}') 

Vos commentaires indiquent que vous cherchez à tuer le processus « dernier » (par laquelle métrique?) Mais votre code et ce code, les tentatives de tuer tous les cas. Si vous voulez le dernier processus démarré, le PID n'est pas un bon indicateur; Vous devriez regarder les heures de début du processus, etc. La sortie de ps dépend fortement du système, donc vous devriez probablement poster une question séparée avec plus de détails sur votre système d'exploitation si vous avez besoin d'aide pour le déterminer.

Ce problème particulier est régulièrement battu à mort plusieurs fois par mois ici, donc vous devriez probablement regarder d'autres implémentations pour vous inspirer. Ma recommandation serait "ne faites pas cela" mais puisque vous l'avez déjà fait, je suppose qu'il est logique de souligner les failles et de tenter de solidifier le code. Mais si vous n'avez pas une raison impérieuse pour laquelle vous ne pouvez pas installer pkill, vous devriez probablement l'utiliser (et si vous le faites, utiliser un script correctement débogué et testé est bien mieux que d'écrire le vôtre depuis le début).

+0

J'ai supprimé mon commentaire car cela dépend de la façon dont l'OP veut déterminer le * dernier * processus. Mais probablement les drapeaux '-newest' et' -oldest' de 'pgrep/pkill' fonctionneront pour l'OP. À la fin, je peux imaginer des cas d'utilisation où 'awk' est toujours disponible, mais on pourrait d'abord essayer d'accomplir la tâche avec' pgrep/pkill'. – hek2mgl

+1

Merci pour les commentaires. Ajout d'un pointeur sur 'pkill' au dernier paragraphe des rêveries. – tripleee

+0

Pourquoi le PID n'est-il pas un bon indicateur? (Je demande innocemment, je pense qu'il vaut la peine de mentionner la raison dans la réponse.) @ Hek2mgl: bon conseil re 'pgrep' /' pkill'; ils sont en fait préinstallés sur OS X (ce qui est le cas de l'OP), mais ne supportent pas les options _long_ (implémentations BSD); '-n' pour' --newest', '-o' pour' --oldest' fonctionnent, cependant. – mklement0

3

Mon conseil est d'utiliser pkill à la place. À partir de la page de manuel:

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