我正在学习一个简短的 shell 脚本视频课程,给出的示例之一是:
if [[ ! $1 ]]; then
echo "Need line length argument" >&2
exit 1
fi
课程材料说“这是将错误打印到标准错误。”但这并不符合我有限的理解,我认为默认文件描述符(如果未指定)是“1”(因此,在本例中为 stdout,即上面与 相同1>&2
)。在我看来,这将是将标准输出重定向/合并到标准错误。
我是否遗漏了“&”作为重定向的一部分如何工作的信息?
答案1
那只是一个误会。 “这是将错误打印到标准错误”意味着“标准错误是输出结束的地方”。你是对的,这是“将标准输出重定向/合并到标准错误”。但这并不矛盾。
该命令不会注意到此更改。该命令打印到stdout
(即fd 1)。但在运行命令之前,shell 会stdout
创建stderr
.
$ strace -f bash -c '/bin/echo foo >&2'
[...]
dup2(1, 2) = 2
fcntl(1, F_GETFD) = 0
execve("/bin/echo", ["/bin/echo", "foo"], 0x55ffb063e5d0 /* 103 vars */) = 0
[...]
man 2 dup
int dup2(int oldfd, int newfd);
dup() 系统调用创建文件描述符 oldfd 的副本,使用编号最小的未使用文件描述符作为新描述符。
成功返回后,新旧文件描述符可以互换使用。它们引用相同的打开文件描述(参见 open(2)),因此共享文件偏移量和文件状态标志;例如,如果在其中一个文件描述符上使用 lseek(2) 修改文件偏移量,则另一个文件描述符的偏移量也会更改。
这两个文件描述符不共享文件描述符标志(close-on-exec 标志)。重复描述符的 close-on-exec 标志(FD_CLOEXEC;请参阅 fcntl(2))已关闭。
答案2
此外@HaukeLaging 的回答,你是对>&2
的,这是 的语法糖1>&2
。应将其&
解读为指针或间接引用。基本上1>&2
在命令中意味着“对于该命令(或命令组,如果使用{}
或()
),将文件描述符 1 指向文件描述符 2 在处理该字之前所指向的位置”。但这是壳语法,并且不是命令的参数。