Bash-скрипт, который открывает несколько экземпляров netcat и выходит из них

Я пытаюсь создать скрипт, который открывает несколько терминалов gnome и открывает соединение netcat. Через пару секунд я бы хотел закрыть терминалы. Я в растерянности, и я верю, что это невозможно, однако я решил спросить.

Это то, что я имею до сих пор, однако после того, как я запустил его, идентификаторы процесса считаются неправильными, и я полагаю, что это потому, что gnome-терминал разветвляет процесс на bash, а я не собираю этот 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

1 ответ

Решение

Это потому что gnome-terminal "умный". Когда вы запускаете gnome-terminal, это будет определять, если другой экземпляр gnome-terminal уже бежит.

  • Если нет, это создает новый gnome-terminal обрабатывает и порождает окно.
  • Если да, это просто приведет к тому, что существующие gnome-terminal процесс порождения нового окна.

Поэтому все gnome-terminal Windows работает как один процесс, с одним PID.

Вы можете легко проверить это, открыв несколько gnome-terminal Windows, а затем получить их PID, выдав xprop _NET_WM_PID где-нибудь и нажмите внутри них. Вы увидите, что PID одинаков для всех окон.

Так что же происходит в вашем сценарии?

Вы захватываете PID gnome-terminal экземпляры запускаются нормально, но проблема в том, что эти PID существуют только в течение доли секунды. Эти процессы вызывают только существующие gnome-terminal процесс, чтобы создать новое окно, а затем завершить.

Так что если у вас уже есть активный gnome-terminal При выполнении вашего сценария (который я предполагаю) PID, которые вы собираете, больше не существуют, когда вы пытаетесь их убить. Если вы этого не сделаете (скажем, вы выполняете этот скрипт из xterm или другой эмулятор терминала), первый полученный вами PID действительно будет "правильным". Следующие идентификаторы PID будут "неправильными". Как только вы войдете в свой цикл убийств, первая итерация убьет все gnome-terminal окна, и следующие будут выводить ошибки, потому что эти PID больше не существует.

Итак, как это решить?

Ну, я могу придумать два пути.

  1. Если вы не настаиваете на использовании gnome-terminalвместо этого используйте другой эмулятор терминала, который не ведет себя таким образом. xterm например, порождает отдельный процесс для каждого окна. Если вы используете xterm скорее, чем gnome-terminal в вашем сценарии это должно работать. Легко чистить.

  2. Если вы настаиваете на использовании gnome-terminalспособ убить конкретного gnome-terminal Окно будет убить процесс, который работает внутри этого конкретного окна. Как только вы завершите этот процесс, это окно закроется. Но так как вы используете это -e вариант, этот процесс будет netcat $ipaddress $port сначала, потом потом bashи трудно получить PID. Вы не можете легко собрать их, как вы делаете с $!, Вы можете попробовать что-то вроде killall netcat или же killall bash, но ясно, что это также прекратит все остальные netcat или же bash случаи, которые вы, вероятно, не хотите. Вы могли бы возможно grep более умно разработан ps позвоните, чтобы попытаться найти точные PID, которые вы хотите убить, но это шатко и подвержено ошибкам. Честно говоря, я бы просто пошел к решению 1.

Два небольших комментария к вашему сценарию:

  • Строка 10: должно быть port=0не $port=0,

  • Строка 13: должно быть processarray+=("$!")не processarray+= ("$!"),

Надеюсь, это поможет.

Редактировать: О, я только что нашел --disable-factory вариант для gnome-terminal, что заставляет его не повторно использовать существующие процессы. Вот ваш фиксированный скрипт:

#!/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

Другие вопросы по тегам