使用 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的新手,我正在尝试理解这段“代码”。
- 为什么不需要 while 循环?这怎么行?它本身是一个循环吗?为什么?如何?
另外,
cat filePipe
本身只打印一行,然后退出(我刚刚测试过),为了让 cat 不退出,我做了:while cat pipeFile ; do : ; done
。那么上面的方法是如何工作的?
- 我不知道执行顺序...开始时 /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/f
。 cat
现在将阻塞,直到其他进程打开 /tmp/f
进行写入; nc
即将这样做(或已经这样做了,但我们不知道 cat
是否会在 nc
之前开始,或者 nc
是否会在 [=12= 之前开始],我们也不知道他们打开 fifo 的顺序,但谁先打开,谁就会阻塞,直到另一个完成操作)。一旦所有 3 个进程都启动,它们就会坐在那里等待一些数据。最终,一些外部进程连接到端口 1234 并将一些数据发送到 nc
,然后写入 /tmp/f
。 cat
(最终)读取该数据并将其发送到下游 bash
,后者处理输入并(可能)将一些数据写入 nc
,后者通过套接字连接将其发回。
如果你有一个测试用例,其中 cat /tmp/f
只写了一行数据,那只是因为你用来写入 /tmp/f
的任何进程只写了一行。尝试:printf 'foo\nbar\nbaz\n' > /tmp/f & cat /tmp/f
或 while 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的STDIN从
nc
的STDOUT和
- 连接回 bash的STDOUT和STDERR到
nc
的 STDIN.
.3 越:bash主义
在 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
mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc -l -p 1234 > /tmp/f
我是bash的新手,我正在尝试理解这段“代码”。
- 为什么不需要 while 循环?这怎么行?它本身是一个循环吗?为什么?如何?
另外,
cat filePipe
本身只打印一行,然后退出(我刚刚测试过),为了让 cat 不退出,我做了:while cat pipeFile ; do : ; done
。那么上面的方法是如何工作的? - 我不知道执行顺序...开始时 /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/f
。 cat
现在将阻塞,直到其他进程打开 /tmp/f
进行写入; nc
即将这样做(或已经这样做了,但我们不知道 cat
是否会在 nc
之前开始,或者 nc
是否会在 [=12= 之前开始],我们也不知道他们打开 fifo 的顺序,但谁先打开,谁就会阻塞,直到另一个完成操作)。一旦所有 3 个进程都启动,它们就会坐在那里等待一些数据。最终,一些外部进程连接到端口 1234 并将一些数据发送到 nc
,然后写入 /tmp/f
。 cat
(最终)读取该数据并将其发送到下游 bash
,后者处理输入并(可能)将一些数据写入 nc
,后者通过套接字连接将其发回。
如果你有一个测试用例,其中 cat /tmp/f
只写了一行数据,那只是因为你用来写入 /tmp/f
的任何进程只写了一行。尝试:printf 'foo\nbar\nbaz\n' > /tmp/f & cat /tmp/f
或 while 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的STDIN从
nc
的STDOUT和 - 连接回 bash的STDOUT和STDERR到
nc
的 STDIN.
.3 越:bash主义
在 bash 下,您可以通过使用 unnamed fifo:
来避免创建 fifocoproc nc -l -p 1234; bash -i >&${COPROC[1]} 2>&1 <&${COPROC[0]}
或
exec {ncin}<> <(:); nc -l -p 1234 <&$ncin | bash -i >&$ncin 2>&1