4 votes

Tuer un processus depuis perl script

J'essaie de tuer un processus par son nom que je vais passer comme variable à une commande système.

Voici ce que j'ai :

my $processName=$ARGV[0];
print "$processName\n";
system(q/kill -9 `ps -ef | grep '$processName' | grep -v grep | awk '{print $2}'`/);

Le script ci-dessus lance une erreur :

kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]

Cependant, si je saisis directement le nom du processus dans la commande système, cela fonctionne.

Quelqu'un peut-il m'aider ?

10voto

zdim Points 29788

Un problème est que la ligne de commande qui invoque le script a le nom du processus que vous interrogez ensuite, à dessein ; donc une chose trouvée sera le script lui-même.

On peut s'en prémunir, mais pourquoi aller jusqu'au système avec ce gros pipeline ?

Interroger le processus en Perl, par exemple avec Proc::ProcessTable

use warnings;
use strict;
use Proc::ProcessTable;

my $proc_name = shift // die "Usage: $0 process-name\n";  #/

my $pid;
my $pt = Proc::ProcessTable->new();
foreach my $proc (@{$pt->table}) {
    next if $proc->cmndline =~ /$0.*$proc_name/;  # not this script
    if ($proc->cmndline =~ /\Q$proc_name/) {
        $pid = $proc->pid;
        last;
    }   
}

kill 9, $pid;                    # must it be 9 (SIGKILL)? 
my $gone_pid = waitpid $pid, 0;  # then check that it's gone

Notez qu'il est bien plus agréable de "tuer" un processus en lui envoyant SIGTERM (généralement 15), et non SIGKILL .

La recherche d'un "nom" de processus peut être périlleuse car il existe de nombreux processus avec de longues lignes de commande fonctionnant sur un système moderne qui peuvent contenir ce mot. Le code utilise votre exigence, de simplement interroger par le nom soumis, mais je recommande de renforcer cela avec des vérifications supplémentaires.

Pour de nombreux détails de processus que le module peut interroger, voir sa page module de raccordement .

Même si vous préférez analyser la table de processus vous-même, je n'obtiendrais que ps -ef et ensuite l'analyser dans le script. Cela donne beaucoup plus de flexibilité pour s'assurer que vous terminez vraiment ce que vous voulez.

2voto

daxim Points 31874

Vous avez les différentes variables $processName y $jobName donc l'ensemble ` ` L'expression se termine par un vide. use strict l'aurait fait remarquer ; c'est utile même pour les scripts de trois lignes. Le site kill Le message d'erreur est celui que vous obtenez lorsque vous l'exécutez sans aucun argument.

Un conseil de pro : pkill existe, vous pouvez remplacer l'ensemble du hack problématique avec une seule commande.

1voto

blackfury Points 251
my $pid = `ps -ef | grep '$processName' | grep -v grep | awk '{print \$2}'`;
print $pid;
system("kill -9 $pid");

Celui-ci fonctionne ! !!

0voto

Filip Spiridonov Points 231

Vous pouvez tuer un processus par son nom sans invoquer le shell en utilisant IPC::System::Simple :

use IPC::System::Simple qw(systemx EXIT_ANY);
systemx(EXIT_ANY, 'pkill', '-9', '--', $processName);

Ou vous pouvez d'abord collecter une liste d'identifiants de processus :

use IPC::System::Simple qw(capturex EXIT_ANY);
kill 9, capturex(EXIT_ANY, 'pgrep', '--', $processName));

Alors vous n'avez pas à vous soucier String::ShellQuote . Voir cette réponse par daxim.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X