Script Bash que abre várias instâncias do netcat e as libera

2

Eu estou tentando criar um script que abre vários terminais gnome e abre uma conexão netcat. Depois de alguns segundos, gostaria que os terminais fechassem. Estou perplexo e acredito que não pode ser feito, mas imaginei que fosse pedir.

Isto é o que eu tenho até agora, mas depois que eu corri, os ids do processo são considerados incorretos e eu acredito que é porque o gnome-terminal forks o processo a bater e eu não estou capturando esse pid.

ipaddress=
port=
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
    
por Pegleg 06.09.2014 / 00:26

1 resposta

1

Isso porque gnome-terminal é "inteligente". Quando você acionar gnome-terminal , ele determinará se outra instância de gnome-terminal já está em execução.

  • Se não, cria um novo processo gnome-terminal e gera uma janela.
  • Se sim, simplesmente fará com que o processo gnome-terminal existente crie uma nova janela.

Portanto, todas gnome-terminal janelas são executadas como um único processo, com um único PID.

Você pode facilmente verificar isso abrindo várias gnome-terminal janelas, então pegue seus PIDs emitindo xprop _NET_WM_PID em algum lugar e clique dentro deles. Você verá que o PID é o mesmo para todas as janelas.

Então, o que acontece no seu roteiro?

Você está capturando os PIDs das instâncias de gnome-terminal que você inicia bem, mas o problema é que esses PIDs existem apenas por uma fração de segundo. Esses processos apenas fazem com que o processo gnome-terminal existente crie uma nova janela e termine.

Então, se você já tem um processo gnome-terminal ativo ao executar seu script (o que eu suponho), os PIDs que você coletou não existem mais quando você tenta matá-los. Se você não o fizer (digamos, você executar esse script de um xterm ou algum outro emulador de terminal), o primeiro PID que você coletar estará de fato "correto". Os seguintes PIDs que você coletar serão "incorretos". Uma vez que você insere o loop de eliminação, a primeira iteração mataria todas as gnome-terminal windows e as seguintes resultariam em erros, porque esses PIDs não existem mais.

Então, como resolver isso?

Bem, de cara, posso pensar em duas maneiras.

  1. Se você não insistir em usar gnome-terminal , use outro emulador de terminal que não se comporte dessa maneira. xterm , por exemplo, gera um processo separado para cada janela. Se você usar xterm em vez de gnome-terminal em seu script, isso deve funcionar. Fácil & amp; limpo.

  2. Se você insistir em usar gnome-terminal , a maneira de matar uma janela gnome-terminal específica seria matar o processo que está sendo executado dentro dessa janela específica. Assim que você terminar esse processo, essa janela será fechada. Mas como você está usando a opção -e , esse processo será netcat $ipaddress $port primeiro, depois bash , e é difícil obter os PIDs. Você não pode coletá-los facilmente como está fazendo atualmente com $! . Você poderia tentar algo como killall netcat ou killall bash , mas claramente isso também terminaria todas as outras instâncias de netcat ou bash , o que você provavelmente não deseja. Você poderia, possivelmente, grep sobre uma chamada ps habilmente projetada para tentar encontrar os PIDs exatos que deseja matar, mas isso é instável e propenso a erros. Honestamente, eu iria apenas para a solução 1.

Dois pequenos comentários no seu script:

  • Linha 10: deve ser port=0 , não $port=0 .

  • Linha 13: deve ser processarray+=("$!") , não processarray+= ("$!") .

Espero que ajude.

Editar: Acabei de encontrar a opção --disable-factory para gnome-terminal , o que faz com que não reutilize processos existentes. Aqui está o seu script fixo:

#!/bin/bash

ipaddress=
port=
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

    
por Malte Skoruppa 13.09.2014 / 14:34