打开多个 netcat 实例并退出它们的 Bash 脚本

打开多个 netcat 实例并退出它们的 Bash 脚本

我正在尝试创建一个脚本,打开多个 gnome 终端并打开 netcat 连接。几秒钟后,我想关闭终端。我很困惑,我认为这不可能做到,但我想我会问一下。

这是我目前所拥有的,但是在运行它之后,进程 ID 被认为是不正确的,我相信这是因为 gnome-terminal 将进程分叉到 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-terminalWindows 作为单个进程运行,具有单个 PID。

您可以通过打开多个gnome-terminal窗口来轻松检查这一点,然后通过xprop _NET_WM_PID在某个地方发出命令并单击它们来获取它们的 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。您无法像现在使用那样轻松地收集它们。您可以尝试类似或的$!操作,但显然这也会终止所有其他或实例,而这可能不是您想要的。您可以通过一些精心设计的调用来尝试找到您想要终止的确切 PID,但这很不稳定并且容易出错。老实说,我只会选择解决方案 1。killall netcatkillall bashnetcatbashgrepps

对您的脚本的两点小评论:

  • 第 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

相关内容