Linux bash 退出状态以及如何在 bash 中设置退出状态
每个 Linux 或 Unix 命令在正常或异常终止时都会返回一个状态。您可以在 shell 脚本中使用退出状态的值来显示错误消息或运行命令。例如,如果 tar 命令失败,它会返回一个代码,告诉 shell 脚本向系统管理员发送电子邮件。
教程详细信息 | |
---|---|
难度等级 | 简单的 |
Root 权限 | 不 |
要求 | Linux 或 Unix 终端 |
类别 | Linux shell 脚本 |
先决条件 | 猛击 |
操作系统兼容性 | BSD • Linux • macOS • Unix |
预计阅读时间 | 3 分钟 |
有关 Linux bash shell 退出状态代码的更多信息
- 每个由 shell 脚本或用户执行的 Linux 或 Unix 命令都有一个退出状态。
- 退出状态是一个整数。
- 对于 bash shell 的目的而言,以零 (0) 退出状态退出的命令表示成功。
- 非零(1-255)退出状态表示失败。
- 如果未找到命令,则为执行该命令而创建的子进程将返回状态 127。如果找到命令但不可执行,则返回状态为 126。
- 如果成功,所有 Bash 内置命令都会返回退出状态零,如果失败则返回非零状态。
如何显示 shell 命令的退出状态?
您可以使用调用的特殊 shell 变量$?来获取先前执行的命令的退出状态。要打印$?变量,请使用 echo 命令/printf 命令。语法为:
或
$ command
$ echo $?
$ /path/to/script.sh
$ command
$ printf "%d\n" $?
$ date
$ echo $?
## OR use the printf command ##
$ printf "%d\n" $?
## run non-existence command ##
$ foobar13535
## display status code ##
$ echo $?
Bash 中的 $? (美元问号) 是什么?
(美元问号$?) 是 bash 执行的最后一个任务或命令的退出状态。它是一个特定的保留 shell 变量,您可以使用它来查明您最后执行的命令是否失败。让我们看看 shell 变量 $? 在 bash 中是什么意思,以及如何在脚本中使用它。
如何将命令的退出状态存储在 shell 变量中
将 $? 赋值给 shell 变量。语法如下:
date status=$? echo "The date command exit status : ${status}"
Linux 退出状态和条件/列表构造
一个用于定位主机名的简单 shell 脚本(findhost.sh)
#!/bin/bash # set var FILE="/etc/hosts" # get host name read -p "Enter a hostname : " hostname # try to locate hostname/computer name in $FILE grep -q -w "${hostname}" "${FILE}" # store exit status of grep # if found grep will return 0 exit status # if not found, grep will return a nonzero exit status status=$? if test $status -eq 0 then echo "Host '$hostname' found in $FILE file." else echo "Host '$hostname' not found in $FILE file." fi
如何将 && 和 || 运算符与退出代码一起使用
语法是:
command && echo "success" command || echo "failed" command && echo "success" || echo "failed"
如果未找到名为“/tmp/foo”的目录,则创建它:
[ ! -d "/tmp/foo" ] && mkdir -p "/tmp/foo"
例如,当文件名未作为命令行参数传递时,显示使用语法:
#!/bin/Bash _files="$@" ## fail safe ## [[ "$_files" == "" ]] && { echo "Usage: $0 filexfcolrxrvkjutidsbhbcqexuvunyawhv.png filejgwsanhgqivghcfhomxmruykhukcwiwr.png"; exit 1; } ## continue below ##
下面是另一个显示用法的 shell 脚本:
#!/bin/bash set -e I=~/bin/tags.deleted.410 O="/tmp/https.www.example.com.410.url.conf" t="$1" [ ! -f "$I" ] && { echo "$I file not found."; exit 10; } [ "$t" == "" ] && { echo "Usage: $0 number-of-urls-to-purge-from-$I"; exit 11; } >$O cat "$I" | sort | uniq | while read -r u do uu="${u##https://www.example.com}" echo "~^$uu 1;" >>"${O}" done echo "* Config file created at ${O} ..." echo "* Installing ${O} file on utls-wp-mg-www ..." ~/bin/install.py "${O}" echo "* Send config to rest of cluster nodes ... " ~/bin/install.py --sync --cluster --reload cbz-www echo "* Building list purge urls for Cloudflare CDN ..." sleep 1 url="" while IFS= read -r u do url="$url $u" done <<<"$(tail -${t} ${I})" [ "$url" != "" ] && ~/bin/cloudflare.purge.urls.sh "$url" [ -f "$O" ] && rm -f "$O"
GNU/Linux 常见退出代码列表
退出代码 | 描述 |
---|---|
0 | 成功 |
1 | 不允许操作 |
2 | 没有这样的文件或目录 |
3 | 没有这样的过程 |
4 | 中断的系统调用 |
5 | 输入/输出错误 |
6 | 没有此设备或地址 |
7 | 参数列表太长 |
8 | 执行格式错误 |
9 | 坏文件描述符 |
10 | 没有子进程 |
11 | 资源暂时不可用 |
12 | 无法分配内存 |
十三 | 没有权限 |
14 | 错误地址 |
15 | 需要块设备 |
16 | 设备或资源繁忙 |
17 | 文件存在 |
18 | 跨设备链接无效 |
19 | 没有此设备 |
20 | 不是目录 |
21 | 是目录 |
22 | 无效参数 |
23 | 系统中打开的文件过多 |
24 | 打开的文件过多 |
二十五 | 设备的 ioctl 不合适 |
二十六 | 文本文件繁忙 |
二十七 | 文件太大 |
二十八 | 设备上没有剩余空间 |
二十九 | 非法寻觅 |
三十 | 只读文件系统 |
31 | 链接过多 |
三十二 | 管道破裂 |
33 | 数值参数超出范围 |
三十四 | 数值结果超出范围 |
三十五 | 避免资源死锁 |
三十六 | 文件名太长 |
三十七 | 没有可用的锁 |
三十八 | 功能未实现 |
三十九 | 目录不为空 |
40 | 符号链接层数过多 |
四十二 | 没有所需类型的消息 |
43 | 标识符已移除 |
四十四 | 通道号超出范围 |
四十五 | 2 级未同步 |
四十六 | 3级暂停 |
四十七 | 三级重置 |
四十八 | 链接数超出范围 |
49 | 未连接协议驱动程序 |
50 | 没有可用的 CSI 结构 |
51 | 2级暂停 |
52 | 无效兑换 |
53 | 无效的请求描述符 |
54 | 交易所已满 |
55 | 无阳极 |
56 | 请求代码无效 |
57 | 无效的插槽 |
59 | 字体文件格式不正确 |
60 | 设备不是流 |
61 | 没有可用数据 |
62 | 计时器已到期 |
63 | 流外资源 |
64 | 机器未接入网络 |
65 | 未安装软件包 |
66 | 对象是远程的 |
67 | 链接已断开 |
68 | 广告错误 |
69 | Srmount 错误 |
70 | 发送时出现通信错误 |
71 | 协议错误 |
72 | 尝试多跳 |
73 | RFS 特定错误 |
74 | 坏消息 |
75 | 对于定义的数据类型来说值太大 |
76 | 名称在网络上不唯一 |
77 | 文件描述符状态不正确 |
78 | 远程地址已更改 |
79 | 无法访问所需的共享库 |
80 | 访问损坏的共享库 |
81 | a.out 中的 .lib 部分已损坏 |
82 | 尝试链接过多的共享库 |
83 | 无法直接执行共享库 |
84 | 无效或不完整的多字节或宽字符 |
85 | 中断的系统调用应该重新启动 |
86 | 流管道错误 |
87 | 用户过多 |
88 | 非套接字上的套接字操作 |
89 | 需要目的地地址 |
90 | 消息太长 |
91 | 套接字的协议类型错误 |
92 | 协议不可用 |
93 | 不支持协议 |
94 | 不支持套接字类型 |
95 | 不支持该操作 |
96 | 不支持协议系列 |
97 | 协议不支持的地址系列 |
98 | 地址已被使用 |
99 | 无法分配请求的地址 |
100 | 网络中断 |
101 | 网络无法连接 |
102 | 重置时网络断开连接 |
103 | 软件导致连接中止 |
104 | 对端重置连接 |
105 | 没有可用的缓冲空间 |
106 | 传输端点已连接 |
107 | 传输端点未连接 |
108 | 传输端点关闭后无法发送 |
109 | 引用过多 |
110 | 连接超时 |
111 | 连接被拒绝 |
112 | 主机宕机 |
113 | 没有到主机的路由 |
114 | 操作已在进行中 |
115 | 操作正在进行中 |
116 | 过时的文件句柄 |
117 | 结构需要清洁 |
118 | 不是 XENIX 命名类型文件 |
119 | 没有可用的 XENIX 信号量 |
120 | 是命名类型文件 |
121 | 远程 I/O 错误 |
122 | 超出磁盘配额 |
123 | 未找到任何媒体 |
125 | 操作已取消 |
126 | 所需密钥不可用 |
127 | 密钥已过期 |
128 | 密钥已被撤销 |
129 | 密钥被服务拒绝 |
130 | 主人去世 |
131 | 状态不可恢复 |
132 | 由于 RF-kill,无法进行操作 |
133 | 内存页面有硬件错误 |
perror 命令解释错误代码,它是 MySQL/MariaDB 包的一部分:
$ perror 0
$ perror 1
结论
本页解释了 bash 退出状态和相关命令。有关更多信息,请参阅此处的bash shell 手册页或使用 man 命令/info 命令或 help 命令离线阅读。例如:
$ man bash
$ info bash
$ help printf
$ help echo