web-dev-qa-db-fra.com

Script Bash qui ouvre et ferme plusieurs instances de netcat

J'essaie de créer un script qui ouvre plusieurs terminaux gnome et ouvre une connexion netcat. Après quelques secondes, j'aimerais que les terminaux se ferment. Je suis désemparé et je crois que cela ne peut être fait, mais je me suis dit que je le demanderais.

C’est ce que j’ai fait jusqu’à présent. Cependant, une fois que je l’ai exécuté, les identifiants de processus sont considérés comme incorrects et je pense que c’est parce que gnome-terminal impose le processus à bash et que je ne capture pas ce pid.

ipaddress=$1
port=$2
processarray=()
echo "netcat command set to ip: $ipaddress and port: $port"
if [ -z "$ipaddress" ]; then
    echo "No ip address entered"
fi
if [ -z "$port" ]; then
    echo "No port entered default set to 0"
    $port=0
fi
for i in {0..9}; do
    gnome-terminal -e "bash -c \"netcat $ipaddress $port; exec bash\"" & processarray+=  ("$!")
done

sleep 10;
for i in "${processarray[@]}"; do
    kill "$i"
done
2
Pegleg

C'est parce que gnome-terminal est "intelligent". Lorsque vous lancez gnome-terminal, il déterminera si une autre instance de gnome-terminal est déjà en cours d'exécution.

  • Si non, il crée un nouveau processus gnome-terminal et génère une fenêtre.
  • Si tel est le cas, le processus gnome-terminal existant générera simplement une nouvelle fenêtre.

Par conséquent, toutes les fenêtres gnome-terminal s'exécutent en tant que processus unique avec un seul PID.

Vous pouvez facilement vérifier cela en ouvrant plusieurs fenêtres gnome-terminal, puis obtenir leurs PID en émettant xprop _NET_WM_PID quelque part et en cliquant à l'intérieur. Vous verrez que le PID est le même pour toutes les fenêtres.

Alors, que se passe-t-il dans votre script?

Vous capturez les PID des instances gnome-terminal que vous lancez correctement, mais le problème est que ces PID n'existent que pour une fraction de seconde. Ces processus entraînent uniquement le processus gnome-terminal existant à générer une nouvelle fenêtre, puis à se terminer.

Donc, si vous avez déjà un processus actif gnome-terminal lors de l’exécution de votre script (ce que je suppose), les PID que vous collectez n’existent plus lorsque vous essayez de les tuer. Si vous ne le faites pas (par exemple, vous exécutez ce script à partir d'un xterm ou d'un autre émulateur de terminal), le premier PID que vous collectez sera en effet "correct". Les PID suivants que vous collectez seront "incorrects". Une fois que vous entrez dans votre boucle de destruction, la première itération tuera toutes les fenêtres gnome-terminal et les suivantes produiront des erreurs, car ces PID n'existent plus.

Alors, comment résoudre ce problème?

Bien, dès le départ, je peux penser à deux façons.

  1. Si vous n'insistez pas pour utiliser gnome-terminal, utilisez plutôt un autre émulateur de terminal qui ne se comporte pas de cette manière. xterm crée par exemple un processus distinct pour chaque fenêtre. Si vous utilisez xterm plutôt que gnome-terminal dans votre script, cela devrait fonctionner. Nettoyage facile.

  2. Si vous insistez pour utiliser gnome-terminal, le moyen de tuer une fenêtre spécifique gnome-terminal serait de tuer le processus en cours d'exécution dans cette fenêtre spécifique. Dès que vous terminez ce processus, cette fenêtre se ferme. Mais puisque vous utilisez cette option -e, ce processus sera d'abord netcat $ipaddress $port, puis bash, et il est difficile d'obtenir les PID. Vous ne pouvez pas facilement les collecter comme vous le faites actuellement avec $!. Vous pouvez essayer quelque chose comme killall netcat ou killall bash, mais il est clair que cela mettra également fin à toutes les autres instances netcat ou bash, que vous ne voudrez probablement pas. Vous pouvez éventuellement grep utiliser un appel ps intelligemment conçu pour essayer de trouver les PID exacts que vous voulez tuer, mais c'est fragile et sujet aux erreurs. Honnêtement, je voudrais juste aller pour la solution 1.

Deux commentaires mineurs sur votre script:

  • Ligne 10: Ce devrait être port=0, pas $port=0.

  • Ligne 13: Ce devrait être processarray+=("$!"), pas processarray+= ("$!").

J'espère que ça t'as aidé.

Edit: Oh, je viens de trouver l’option --disable-factory pour gnome-terminal, ce qui l’empêche de réutiliser les processus existants. Voici votre script fixe:

#!/bin/bash

ipaddress=$1
port=$2
processarray=()
echo "netcat command set to ip: $ipaddress and port: $port"
if [ -z "$ipaddress" ]; then
    echo "No ip address entered"
fi
if [ -z "$port" ]; then
    echo "No port entered default set to 0"
    port=0
fi
for i in {0..9}; do
    gnome-terminal --disable-factory -e "bash -c \"netcat $ipaddress $port; exec bash\"" & processarray+=("$!")
done

sleep 10;
for i in "${processarray[@]}"; do
    kill "$i"
done
1
Malte Skoruppa