Linux 标准数据流 (Standard Stream)
标准数据流 (Standard Stream)
Linux 命令执行时,通常会打开三个标准数据流:stdin、stdout、stderr
stdin 标准输入,来自键盘输入、pipe、here-document、here-string 或文件等。stdout 和 stderr 分别是标准输出和标准错误输出,默认都流向终端,也可以被重定向到 pipe 或文件等
文件描述符 (File Descriptors)
Linux 中几乎所有东西,包括数据流都被视作文件。和一个进程关联的每个文件都会被分配到单独的标识数字,即文件描述符。一般地,0 表示标准输入 (stdin), 1 表示标准输出 (stdout), 2 表示标准错误输出 (stderr)
重定向 (Redirection)
重定向 stdout 和 stderr
1 | 使用 stdout 替换文件内容 |
指定 stdin 输入源
指定已有文件作为输入
1 | cat < foo.txt |
here-document。指定结束符,程序会将结束符前的所有内容作为 stdin
1 | name=jakey |
here-string。指定预先写的 string 作为 stdin
1 | cat <<< "Hello world" |
pipe。将前一命令输出作为后一命令的输入
1 | echo 123 | wc |
process substitution。将命令输出以临时文件描述符路径的形式传给另一个命令。与 pipe 不同的是,它更适合需要“文件名参数”的场景(如 diff)。这里面的命令通常仍在子进程中执行
1 | cat <(echo 123) <(echo 456) |
其他
输出到文件的过程中可以移动、重命名或删除文件
在同一个文件系统下移动或重命名文件,仅改变访问路径或文件名,其在磁盘上的位置,即索引(inode)并不改变。而程序正是通过索引来找文件的
删除文件后,不能再通过常规的方式访问到文件,但程序依然可以通过索引来访问文件。这些文件只有在程序关闭文件描述符后才真正被释放(会造成实际的磁盘占用比系统报告的大)
判断输出目的地
一个常见的方法是使用 test 命令(也可使用 [ 和 ])与 -t 选项,来检查文件描述符(如 1 代表 stdout)是否与终端相连。-t 选项会检查给定文件描述符是否连接到终端:
if [ -t 1 ]; then
echo “输出到终端”
else
echo “输出被重定向到文件或其他地方”
fi
通过这个方法可以向不同的输出目的地输出不同的结果,Linux 命令如 ls、git 等都有类似优化。
This article was inspired by ThoughtBot and HowToGeek