使用 netcat 和管道创建 shell 的 bash 代码中到底发生了什么?

What is really happening in this bash code that creates a shell with netcat and pipes?

mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f

我是bash的新手,我正在尝试理解这段“代码”。

  1. 为什么不需要 while 循环?这怎么行?它本身是一个循环吗?为什么?如何? 另外,cat filePipe 本身只打印一行,然后退出(我刚刚测试过),为了让 cat 不退出,我做了:while cat pipeFile ; do : ; done。那么上面的方法是如何工作的?
  2. 我不知道执行顺序...开始时 /tmp/f 是空的,所以 cat /tmp/f 应该“发送”一个空流到 /bin/bash将它发送到 nc,它打开一个连接并将交互式 bash“发送”给任何连接的人...然后将客户端的响应发送到 /tmp/f...然后呢?什么?它怎么能回去做同样的事情呢?

/tmp/f 不是空的,而是一个 fifo,一个 bi-directional link.

有人连接到端口 1234,输入一些内容,nc 将转发到 fifo,然后输入 bash

bash 运行命令并将结果发送回 nc

bash 解析行 mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f 时,会发生几件事。首先,创建 fifo。然后,不按特定顺序发生 3 件事:cat 启动,bash 启动,nc 启动,其输出流连接到 /tmp/fcat 现在将阻塞,直到其他进程打开 /tmp/f 进行写入; nc 即将这样做(或已经这样做了,但我们不知道 cat 是否会在 nc 之前开始,或者 nc 是否会在 [=12= 之前开始],我们也不知道他们打开 fifo 的顺序,但谁先打开,谁就会阻塞,直到另一个完成操作)。一旦所有 3 个进程都启动,它们就会坐在那里等待一些数据。最终,一些外部进程连接到端口 1234 并将一些数据发送到 nc,然后写入 /tmp/fcat(最终)读取该数据并将其发送到下游 bash,后者处理输入并(可能)将一些数据写入 nc,后者通过套接字连接将其发回。

如果你有一个测试用例,其中 cat /tmp/f 只写了一行数据,那只是因为你用来写入 /tmp/f 的任何进程只写了一行。尝试:printf 'foo\nbar\nbaz\n' > /tmp/f & cat /tmp/fwhile sleep 1; do date; done > /tmp/f & cat /tmp/f

.1 你误解了 echo "string" >/path/fifo

时发生的事情

.a) 当你 echo something >/path/to/somewhere 时,你

  • (测试可访问性,然后)打开 目标某处 用于写入
  • 写入 someting in openned file descriptor (fd)
  • 关闭(放松)访问文件。

.b) A fifo (The First In 是 First Out.) 不是文件.

试试这个:

# Window 1:

mkfifo /tmp/fifotest
cat /tmp/fifotest

# Window 2:

exec {fd2fifo}>/tmp/fifotest
echo >&$fd2fifo Foo bar

您将看到 cat 未终止

echo >&$fd2fifo Baz
exec {fd2fifo}>&-

现在,cat 将关闭

所以不需要任何循环!

.2 命令cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f

可以这样写(避免无用的使用cat

bash -i 2>&1 </tmp/f | nc -l -p 1234 > /tmp/f

但您可以相同操作,但从不同的视角:

nc -l -p 1234 </tmp/f | bash -i >/tmp/f 2>&1

目标是

  • 驱动器 bash的STDINncSTDOUT
  • 连接回 bash的STDOUTSTDERRncSTDIN.

.3 越:bash主义

下,您可以通过使用 unnamed fifo:

来避免创建 fifo
coproc nc -l -p 1234; bash -i >&${COPROC[1]} 2>&1 <&${COPROC[0]}

exec {ncin}<> <(:); nc -l -p 1234 <&$ncin | bash -i >&$ncin 2>&1