![打开多个 netcat 实例并退出它们的 Bash 脚本](https://linux22.com/image/861407/%E6%89%93%E5%BC%80%E5%A4%9A%E4%B8%AA%20netcat%20%E5%AE%9E%E4%BE%8B%E5%B9%B6%E9%80%80%E5%87%BA%E5%AE%83%E4%BB%AC%E7%9A%84%20Bash%20%E8%84%9A%E6%9C%AC.png)
我正在尝试创建一个脚本,打开多个 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-terminal
Windows 作为单个进程运行,具有单个 PID。
您可以通过打开多个gnome-terminal
窗口来轻松检查这一点,然后通过xprop _NET_WM_PID
在某个地方发出命令并单击它们来获取它们的 PID。您将看到所有窗口的 PID 都是相同的。
那么你的脚本中发生了什么?
您确实捕获了启动的实例的 PID gnome-terminal
,但问题是,这些 PID 仅存在几分之一秒。这些进程只会导致现有gnome-terminal
进程生成一个新窗口,然后终止。
因此,如果您在执行脚本时已经有一个活动gnome-terminal
进程(我假设如此),则当您尝试终止它们时,您收集的 PID 将不再存在。如果没有(例如,您从xterm
或其他终端仿真器执行该脚本),您收集的第一个 PID 确实会“正确”。您收集的后续 PID 将是“不正确的”。一旦您进入终止循环,第一次迭代将终止所有gnome-terminal
窗口,而后续迭代将输出错误,因为这些 PID 不再存在。
那么,如何解决这个问题呢?
好吧,我马上就能想到两种方法。
如果您不坚持使用
gnome-terminal
,请使用其他不以这种方式运行的终端仿真器。xterm
例如,为每个窗口生成一个单独的进程。如果您在脚本中使用xterm
而不是,它应该可以工作。简单又干净。gnome-terminal
如果您坚持使用
gnome-terminal
,终止特定窗口的方法gnome-terminal
是终止在该特定窗口内运行的进程。一旦终止该进程,该窗口就会关闭。但由于您使用该-e
选项,因此此过程将netcat $ipaddress $port
首先运行,然后在之后bash
运行,并且很难获取 PID。您无法像现在使用那样轻松地收集它们。您可以尝试类似或的$!
操作,但显然这也会终止所有其他或实例,而这可能不是您想要的。您可以通过一些精心设计的调用来尝试找到您想要终止的确切 PID,但这很不稳定并且容易出错。老实说,我只会选择解决方案 1。killall netcat
killall bash
netcat
bash
grep
ps
对您的脚本的两点小评论:
第 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