重拾Linux文件重定向


=Start=

缘由:

因为工作性质的变化,我已经很久没有关注IDC安全方面的内容了(很久之前搞了一段时间的Bash源码改写以支持bash命令的实时记录以及基于此的恶意命令分析)。前段时间在群里看到了一条反弹shell的命令,和之前我整理时略有不同的地方在于openssl命令的引入,对请求响应的流量做了加密,以规避在网络层面的异常检测。因为之前只是收集和记录了各编程语言一句话反弹shell的内容,但并没有具体拆解和学习这其中涉及到的知识点和原理,所以记忆并不深刻、命令敲起来也不够熟练(基本就是靠搜索/复制/粘贴),趁着最近有点时间,再整理和学习一下,加深记忆方便后面直接使用和参考。

正文:

参考解答:

Linux下一切皆文件。

文件描述符(fd,file descriptor)是一个非负整数,用以标明每一个被进程所打开的文件(常规文件、目录、字符设备、块设备、套接字、打印机、进程、线程、管道等)。

Linux下文件所有输入输出都是由该进程所有打开的文件描述符控制的。Linux下一个程序启动之后默认会有三个文件描述符(标准输入-0、标准输出-1、错误输出-2),在某些场景下如果想让它的输出不直接显示在屏幕上,而是输出到文件或者其他设备,此时我们就需要进行文件重定向。

The order of redirection is important, and they should be read left to right.
Redirections are processed in the order they appear, from left to right.
重定向的顺序是非常重要的(因为它会影响最终的结果),它们是从左到右依次进行处理的。

下面简单整理了 bash 手册中重定向一节中的内容(内容根据个人经验做了一些精简):

  • 重定向输入
# 将 word 展开之后的输出作为文件描述符n(如果n没有指定,则默认为0,表示stdin)的输入
[n]<word

# 样例:在终端中显示文件的内容(将文件的输出重定向到标准输入0上)
$ <file_name # 等价于 cat file_name 命令
nihao
test
exit
  • 重定向输出
# 将文件描述符n(如果n没有指定,则默认为1,表示stdout)的输出重定向到 word 展开之后用于输入的文件中,除了 > 操作符之外还可以用管道操作符 |
[n]>[|]word
  • 重定向标准输出和错误输出(这个很有用,建议多看看)
# 有2种格式的写法

# 写法一,推荐的简写用法
&>word

# 写法二
>&word

# 上面两种写法【建议使用第一种】,都等价于下面这种更易于理解的写法
>word 2>&1
  • 将标准输出和错误输出进行追加式重定向
# 写法一(和上面的相比只是将覆写>改成了追加>>)
&>>word

# 等价写法,更容易理解,更不容易写错
>>word 2>&1
  • Here Documents(部分场景很有用)
# 需要额外说明的是,这里要用 cat 而不是 echo 才能把内容打印出来,因为是 documents 而不是 strings
$ cat <<diffstring
heredoc> this is 1st line of here documents
heredoc> 2nd line
heredoc> 3rd line
heredoc> 4th line
heredoc>        5th line with '\t' at begin of line
heredoc>  last line with ' ' at begin of line
heredoc> diffstring

this is 1st line of here documents
2nd line
3rd line
4th line
    5th line with '\t' at begin of line
 last line with ' ' at begin of line
$
# 相比上面多了一个破折号,用于删除每一行内容中行首的制表符
$ cat <<-diffstring
heredocd> this is 1st line
heredocd>       2nd line with '\t' at begin of line
heredocd>  3rd line with ' ' at begin of line
heredocd>               4th line with 2*'\t' at begin of line
heredocd> 5th line
heredocd> diffstring

this is 1st line
2nd line with '\t' at begin of line
 3rd line with ' ' at begin of line
4th line with 2*'\t' at begin of line
5th line

# 利用 here-documents 的特性在shell脚本中将特定内容写入文件(起到类似内嵌文件的功能)
$ cat << EOF > /tmp/yourfilehere
These contents will be written to the file.
        This line is indented.
EOF
  • Here Strings
# 说明,在 <<< 后面的第一个字段不会显示
$ echo <<<diffstring 1,2,3,4,5 line
1,2,3,4,5 line
$ echo <<< content here
here
$ echo <<<no_display content here
content here
  • 复制文件描述符(个人建议为了可读性,最好不要简写)

文件描述符的复制这个地方把我绕了好久,主要在于gnu的bash手册和Advanced Bash-Scripting Guide中的解释不太一样,而且实际测试发现不同shell中的支持情况和表现也不一致,所以暂时也不多纠结了,起码能将我个人的经验和手册中的说明对上,后面在碰到特殊情况就可以按个人经验进行合理的解释了。

# 经过实际测试发现在不同种类和版本的shell上重定向中的复制文件描述符的行为不一致(很可能还不生效)
# 所以这一内容先按官方文档进行理解,到了实际需要用的时候,需要根据实际情况进行测试验证以找出实际可行的具体方法/命令


[n]<&word #表示用 word 扩展出的文件描述符的值覆盖 n ,**最后word和n的值都相等,都是原先word的指向**,即用word做为n的输入,n默认为0即标准输入

[n]>&word #将文件描述符 n 代表的文件输出重定向到了 word 上,**最后word和n的值都相等,都是原先word的指向**,输出到n的也都同样输出到了word,特殊情况若n省略,就是将标准输出和错误输出都输出到了word中

# 即,不管是复制输入还是复制输出,有一个点是相同的,最后两者的值相同,都是原先的word,区别在于一个用word作为输入,一个用word作为输出

# 不管是哪个,最后 word 和 n 的值都是相等的,且都是word的值,所以 0>&1 == 0<&1 == <&1 这3者等价(输入输出连接成了环状,在终端交互的表现就是输入什么就输出什么)


# 用于复制【输入】文件描述符,将 word 展开之后的文件的输入复制到文件描述符n上,若n没有指定则默认为0
[n]<&word

# 用于复制【输出】文件描述符(比较好理解),n默认为1,特别的当n省略时就是之前介绍过的——重定向标准输出和错误输出
[n]>&word

i>&j
  # Redirects file descriptor i to j. "i" defaults to 1, if not set.
  # All output of file pointed to by i gets sent to file pointed to by j.

0>&1 (same as 0<&1 or <&1) duplicates fd 1 to 0 as well (fd 0 is made to point to the same resource as pointed to by fd 1).
  • 更新文件描述符(相比于上面的复制,只是增加了复制后关闭原文件描述符的动作)
# 将 digit 这个数字指定的文件描述符更新到文件描述符n上,在此之后原 digit 文件描述符就会关闭,若n没有指定则表示为标准输入0
[n]<&digit-

# 将 digit 这个数字指定的文件描述符更新到文件描述符n上,在此之后原 digit 文件描述符就会关闭,若n没有指定则表示为标准输出1
[n]>&digit-
  • 打开文件描述符用于文件读写
# 将 word 展开之后的文件的输入和输出绑定到文件描述符n(如果n没有指定,则默认为0,表示stdin)上
[n]<>word

# 举例
# 将n省略,则表示新建一个名叫 word 的空文件
$ <> word

# 将n设置为1,则表示将当前从终端输入的任何内容(在你按住 Ctrl-d 表示输入结束之前)写入名叫 word 的文件中
$ 1<>word
参考链接:

3.6.8 Duplicating File Descriptors
https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Duplicating-File-Descriptors

Chapter 20. I/O Redirection
https://tldp.org/LDP/abs/html/io-redirection.html#IOREDIRREF

Order of redirections
https://unix.stackexchange.com/questions/37660/order-of-redirections/176214#176214

Shell redirection i/o order
https://stackoverflow.com/questions/17975232/shell-redirection-i-o-order

exec redirects in bash
https://unix.stackexchange.com/questions/184125/exec-redirects-in-bash

20.1. Using exec
https://tldp.org/LDP/abs/html/x17974.html

Chapter 19. Here Documents
https://tldp.org/LDP/abs/html/here-docs.html

Here Document And Here String
https://www.baeldung.com/linux/heredoc-herestring

Here document使用方法总结
https://blog.csdn.net/liumiaocn/article/details/86715953

How can I write a heredoc to a file in Bash script?
https://stackoverflow.com/questions/2953081/how-can-i-write-a-heredoc-to-a-file-in-bash-script

=END=


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注