Bash 脚本中的持久连接
Persistent connection in Bash script
我正在尝试使用 bash 创建持久连接。在终端 1 上,我保留了一个 netcat 运行ning 作为服务器:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
在 2 号航站楼,我创建了一个 fifo 并养了一只猫:
$ mkfifo fifo
$ cat > fifo
在终端 3 上,我将 fifo 作为客户端 netcat 的输入:
$ cat fifo | nc -v localhost 3000
Connection to localhost 3000 port [tcp/*] succeeded!
在 4 号航站楼,我想发送什么就发送什么:
$ echo command1 > fifo
$ echo command2 > fifo
$ echo command3 > fifo
返回终端 1,我看到正在接收的命令:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
Connection from [127.0.0.1] port 3000 [tcp/*] accepted (family 2, sport 41722)
command1
command2
command3
所以,一切正常。但是当我把它放在脚本中时(我称之为 fifo.sh),bash 无法写入 fifo:
在终端 1 上,相同的侦听服务器:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
在终端 2 上,我 运行 脚本:
#!/bin/bash
rm -f fifo
mkfifo fifo
cat > fifo &
pid1=$!
cat fifo | nc -v localhost 3000 &
pid2=$!
echo sending...
echo comando1 > fifo
echo comando2 > fifo
echo comando3 > fifo
kill -9 $pid1 $pid2
终端2的输出是:
$ ./fifo.sh
Connection to localhost 3000 port [tcp/*] succeeded!
sending...
在 1 号航站楼上,我只看到连接。没有命令:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
Connection from [127.0.0.1] port 3000 [tcp/*] accepted (family 2, sport 42191)
Connection closed, listening again.
知道为什么它只能交互工作吗?或者有没有其他方法可以仅使用 Bash 创建持久连接?我不想使用 Expect,因为我有一个更大的 Bash 脚本,它在发送 command1 后执行一些工作,而 command2 取决于 command1 输出等。
谢谢!
当脚本在后台启动进程时,标准输入从 /dev/null
重定向。这意味着第一个 cat
命令将在执行后立即读取并发出 EOF
,这将导致 netcat 在启动后立即退出,因此脚本后面的输出永远不会进入 fifo,因为当时没有活跃的听众。
在这种情况下,当评估 cat > fifo
时,shell 派生一个 child 进程,重定向来自 /dev/null
的标准输入,并尝试打开 [=16] =] 写。此时 child 仍处于阻塞 open
调用中。请注意,cat
直到 open
调用完成后才会执行。
接下来,生成cat fifo | nc -v localhost 3000
。 cat
打开 fifo
进行读取,这允许第一个 child 的阻塞 open
完成并执行第一个 cat
。
第一个 cat
继承了其 parent 的文件描述符,因此其标准输入附加到 /dev/null
,因此它立即读取并发出 EOF
。第二个 cat
读取 EOF
并将其传递给 nc
的标准输入,这会导致 netcat 退出。
在评估 echo
语句时,由 $pid1
和 $pid2
标识的进程已完成。由于 fifo
上不再有监听器,第一个 echo
将永远阻塞。
我没有 pure-shell 修复程序,但您可以使用 perl 等外部程序将占位符编写器打开到 fifo
而不是使用 shell 重定向。另外,请注意在 echo
语句之后有一个 nc
的竞争(其中 kill
发生在 netcat 有机会处理 input/send 输出之前),所以这里我在 cat | nc
表达式后添加了一个延迟。几乎肯定有更好的解决方案,但这是我想出的:
#!/bin/bash
rm -f fifo
mkfifo fifo
perl -e 'open(my $fh, ">", "fifo"); sleep 3600 while 1' &
pid1=$!
cat fifo | nc -v localhost 3000 &
pid2=$!
sleep 2
echo sending...
echo comando1 > fifo
echo comando2 > fifo
echo comando3 > fifo
kill -9 $pid1 $pid2
希望这对您有所帮助,好问题!
我正在尝试使用 bash 创建持久连接。在终端 1 上,我保留了一个 netcat 运行ning 作为服务器:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
在 2 号航站楼,我创建了一个 fifo 并养了一只猫:
$ mkfifo fifo
$ cat > fifo
在终端 3 上,我将 fifo 作为客户端 netcat 的输入:
$ cat fifo | nc -v localhost 3000
Connection to localhost 3000 port [tcp/*] succeeded!
在 4 号航站楼,我想发送什么就发送什么:
$ echo command1 > fifo
$ echo command2 > fifo
$ echo command3 > fifo
返回终端 1,我看到正在接收的命令:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
Connection from [127.0.0.1] port 3000 [tcp/*] accepted (family 2, sport 41722)
command1
command2
command3
所以,一切正常。但是当我把它放在脚本中时(我称之为 fifo.sh),bash 无法写入 fifo:
在终端 1 上,相同的侦听服务器:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
在终端 2 上,我 运行 脚本:
#!/bin/bash
rm -f fifo
mkfifo fifo
cat > fifo &
pid1=$!
cat fifo | nc -v localhost 3000 &
pid2=$!
echo sending...
echo comando1 > fifo
echo comando2 > fifo
echo comando3 > fifo
kill -9 $pid1 $pid2
终端2的输出是:
$ ./fifo.sh
Connection to localhost 3000 port [tcp/*] succeeded!
sending...
在 1 号航站楼上,我只看到连接。没有命令:
$ nc -vlkp 3000
Listening on [0.0.0.0] (family 0, port 3000)
Connection from [127.0.0.1] port 3000 [tcp/*] accepted (family 2, sport 42191)
Connection closed, listening again.
知道为什么它只能交互工作吗?或者有没有其他方法可以仅使用 Bash 创建持久连接?我不想使用 Expect,因为我有一个更大的 Bash 脚本,它在发送 command1 后执行一些工作,而 command2 取决于 command1 输出等。
谢谢!
当脚本在后台启动进程时,标准输入从 /dev/null
重定向。这意味着第一个 cat
命令将在执行后立即读取并发出 EOF
,这将导致 netcat 在启动后立即退出,因此脚本后面的输出永远不会进入 fifo,因为当时没有活跃的听众。
在这种情况下,当评估 cat > fifo
时,shell 派生一个 child 进程,重定向来自 /dev/null
的标准输入,并尝试打开 [=16] =] 写。此时 child 仍处于阻塞 open
调用中。请注意,cat
直到 open
调用完成后才会执行。
接下来,生成cat fifo | nc -v localhost 3000
。 cat
打开 fifo
进行读取,这允许第一个 child 的阻塞 open
完成并执行第一个 cat
。
第一个 cat
继承了其 parent 的文件描述符,因此其标准输入附加到 /dev/null
,因此它立即读取并发出 EOF
。第二个 cat
读取 EOF
并将其传递给 nc
的标准输入,这会导致 netcat 退出。
在评估 echo
语句时,由 $pid1
和 $pid2
标识的进程已完成。由于 fifo
上不再有监听器,第一个 echo
将永远阻塞。
我没有 pure-shell 修复程序,但您可以使用 perl 等外部程序将占位符编写器打开到 fifo
而不是使用 shell 重定向。另外,请注意在 echo
语句之后有一个 nc
的竞争(其中 kill
发生在 netcat 有机会处理 input/send 输出之前),所以这里我在 cat | nc
表达式后添加了一个延迟。几乎肯定有更好的解决方案,但这是我想出的:
#!/bin/bash
rm -f fifo
mkfifo fifo
perl -e 'open(my $fh, ">", "fifo"); sleep 3600 while 1' &
pid1=$!
cat fifo | nc -v localhost 3000 &
pid2=$!
sleep 2
echo sending...
echo comando1 > fifo
echo comando2 > fifo
echo comando3 > fifo
kill -9 $pid1 $pid2
希望这对您有所帮助,好问题!