为什么exit status
之间不同巴什和外壳程序?, 在ls
男人:
Exit status:
0 if OK,
1 if minor problems (e.g., cannot access subdirectory),
2 if serious trouble (e.g., cannot access command-line
argument).
为了测试exit status
命令ls
,假设我们有一个名为ss
保存在文件夹中的文件。让我们使用通配符根据其字符的状态列出该文件?
在 csh 外壳中:
ls -d ss
ss
ls -d s?
ss
ls -d ?s
ss
ls -d ?z
ls: No match.
ls -d ?z | echo $? #check exit status
0
在重击中:
ls -d ss
ss
ls -d s?
ss
ls -d ?s
ss
ls -d ?z
ls: cannot access ?z: No such file or directory
ls -d ?z | echo $? #check exit status
2
这是相同的命令,但和ls
之间的退出状态不同:csh shell
bash
- 在 csh shell 中退出状态是
0
- 在 bash 中退出状态是
2
现在,问题是:
1)为什么相同的命令ls
在 bash 和 csh shell 中具有不同的退出状态?
2) bash 和 csh shell 下命令行为的这种差异有何重要性?
答案1
首先,你ls -d ?z | echo $?
在 Bash 中的衡量并不是你所认为的。管道全部立即启动,参数扩展甚至在此之前发生,因此echo $?
打印返回代码以前的命令,而不是管道之前的命令。在 csh 下,它甚至不这样做。那个输出是没有意义的。如果您将它们作为单独的命令运行:ls -d ?z ; echo $?
您将获得有关实际退出代码的信息输出。
sh -c 'exit 53'
将作为测试您是否真正从您想要的位置获取退出代码的命令。
其次,虽然您没有告诉我们,但第一个示例中的错误听起来像 csh,所以我假设就是这样。在这种情况下,ls -d ?z
ls
根本没有运行; shell 的通配符扩展失败并No match
报告错误 (" "),从而阻止命令运行。默认情况下,Bash 按字面意思传递不匹配的通配符:实际上,它运行ls '?z'
,并且您收到错误,ls
因为该文件不存在。无论如何,报告的错误代码来自上一行。
因此,该ls
命令在运行时在所有情况下都有相同的行为,只是有时它没有运行。
你可以改变 Bash 的(坦率地说,不好的)行为和shopt -s failglob
。当 glob 不匹配时,它将出错:
/tmp$ ls ?z
ls: cannot access '?z': No such file or directory
/tmp$ shopt -s failglob
/tmp$ ls ?z
bash: no match: ?z
第一个的退出代码为 2,来自ls
,第二个的$?
退出代码为 1,来自 Bash 本身。