Bash管道执行

时间:2014-09-08 22:56:38

标签: bash

netcat联机帮助页指示,如果没有-c和-e选项,可以使用以下命令通过nc提供shell。

$ rm -f /tmp/f; mkfifo /tmp/f
$ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f

现在,根据我的理解,来自fifos的读取和写入都是阻塞操作。例如,如果我运行

$ mkfifo foo
$ cat foo

bash会阻塞,因为没有任何内容写入foo。来自nc联机帮助页的示例中的管道如何不阻塞?我认为我误解了管道的执行方式。

2 个答案:

答案 0 :(得分:7)

管道中的所有命令同时运行,而不是顺序运行。因此cat /tmp/f确实会阻止,但/bin/shnc仍将在此时启动。当客户端连接到端口并发送命令时,nc将写入FIFO,这将允许cat取消阻止。

答案 1 :(得分:3)

bash中的管道字符不是esle,然后将第一个命令的输出流连接到第二个命令的输入流。 echo "123" | cat基本上与cat < <(echo 123)相同(后者只会启动一个子shell,而第一个为每个命令启动一个,但这里可以忽略 - 加上,它是一个基础,不起作用sh)。

$ mkfifo foo
$ cat foo

确实会阻止 - 但不会冻结。当任何其他程序向foo写入任何内容时,cat将显示它。

你在netcat调用中做什么实际上是创建一个cicrle:写入FIFO的任何内容都将由cat显示,并且cat连接到sh发送到后者。然后sh将执行代码(因为sh只执行写入其输入流的任何内容)并将输出发送到ncnc会将其发送给客户。 客户端发送给nc的任何内容都将写入FIFO - 我们的圈子已完成。

你犯的错误(我认为)是假设管道的第二个进程只读取数据一次,而不是连续读取,因此必须等待第一个进程结束。事实并非如此,因为管道中的每个进程都是在一个shubshel​​l中启动的,所以它们都是相互依赖的。


您还应该能够更改管道中所有命令的顺序。只要第一个从FIFO读取并且最后一个写入它(完成圆圈),它就应该有效。