zsh中&>重定向与分设1/2号重定向为何退出码不同?
解答:zsh中
&>与分开重定向的差异及curl行为分析 这是个很容易踩坑的问题,我来帮你拆解清楚其中的关键点:
首先纠正一个常见的误解——不管是zsh还是bash,&>name都不等价于1>name 2>name,而是等价于>name 2>&1。这是你困惑的核心根源之一,虽然这个差异通常不会直接改变命令的退出状态,但结合curl的行为,我们可以理清问题所在。
1. 两种重定向方式的本质区别
&> /dev/null:先把标准输出(stdout)定向到/dev/null,再把标准错误(stderr)重定向到stdout的当前目标(也就是/dev/null)。简单说,两个流最终共享同一个文件描述符指向空设备。1> /dev/null 2> /dev/null:分别为stdout和stderr独立打开/dev/null,两个流用的是不同的文件描述符。虽然最终都是丢弃输出,但底层的文件打开逻辑是不一样的。
2. 为什么你的两个curl命令结果不一样?
你给出的两个命令里,curl的参数是不同的:
- 第一个命令用的是
curl doesntexist -i:尝试连接不存在的主机doesntexist,curl必然连接失败,返回非0的退出状态,所以if条件判断为假,输出False。 - 第二个命令用的是
curl 6 -i:这里的6大概率是一个能被解析到的主机(比如本地网络里的某个设备,或者你的系统对6有特殊的DNS解析),curl成功完成了连接/请求,返回0的退出状态,所以if条件判断为真,输出True。
如果你的实际场景是同一个curl命令用两种重定向方式得到不同结果,那可能是以下原因:
可能性A:zsh的MULTIOS选项在搞鬼
zsh默认开启MULTIOS选项,它允许把命令输出同时定向到多个目标。当你用1> /dev/null 2> /dev/null时,这个选项可能会把两个独立的重定向合并成类似&>的行为,但在某些极端场景下(比如命令内部修改了文件描述符),可能导致退出状态异常。你可以关闭这个选项再测试:
unsetopt MULTIOS # 测试同一个curl命令的两种重定向 if curl doesntexist -i 1> /dev/null 2> /dev/null; then echo True; else echo False; fi if curl doesntexist -i &> /dev/null; then echo True; else echo False; fi
可能性B:curl的退出状态逻辑?
放心,curl的退出状态只和连接/传输的成功与否有关,和有没有stderr输出完全无关。哪怕你把stderr重定向到黑洞,curl的退出状态依然由核心操作结果决定。
3. 验证重定向行为的一致性
你可以用简单的命令验证重定向方式不会改变退出状态:
# 测试非0退出状态 if false &> /dev/null; then echo True; else echo False; fi # 应该输出False if false 1> /dev/null 2> /dev/null; then echo True; else echo False; fi # 同样输出False # 测试0退出状态 if true &> /dev/null; then echo True; else echo False; fi # 应该输出True if true 1> /dev/null 2> /dev/null; then echo True; else echo False; fi # 同样输出True
如果这两组测试结果一致,就说明重定向方式本身不影响退出状态,问题确实出在你两次用的curl参数不同上。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

