Shell揭秘——程序退出状态码

程序退出状态码

前言

在本篇文章当中主要给大家介绍一个shell的小知识——状态码。这是当我们的程序退出的时候,子进程会将自己程序的退出码传递给父进程,有时候我们可以利用这一操作做一些进程退出之后的事情,比如当程序执行失败或者被某个信号杀死我们就可以了解到,然后做出对应的措施。

状态码简介

Shell揭秘——程序退出状态码

上图是一个zsh的截图,当我们执行命令 asdsad之后,因为没有这个命令,所以zsh(类似于bash的一种shell),输出没有找到这个命令,但是我们发现图中箭头➡️由绿色变成红色,表示程序不是正常退出。现在有一个问题是,zsh是怎么知道程序不是正常退出的呢?其实就可以根据子进程退出的状态推断。在文章的最后我们用C语言实现一下,看看如果在父进程接收子进程的退出的状态。

我们在命令行当中可以通过命令 echo $? 查看上一个进程退出时候的退出码,这里的上一个进程就是 ls 命令:

Shell揭秘——程序退出状态码

程序正常退出的时候退出码等于0。

退出码表

退出码 含义 例子 解释 1 一般的错误 除以0 一般的除以0的错误,执行没有权限的操作 2 shell 内部操作失败 通常是shell操作时候的命令错误,文章后面有一个例子演示 126 执行不能够执行的文件 /dev/random 权限问题或者命令不能够执行 127 命令没有找到 非法或者不存在的命令 执行一个系统当中不存在的命令,可以通过设置PATH环境变量 128+n 错误的信号值 Kill -9 PID 杀死进程号为PID的进程,进程的退出码等于 128 + 9 130 ctrl+c 之后进程的返回值 和上一条一样ctrl+c的信号值等于2 其他 退出码s不在范围之内 exit(-1) 如果退出码n不在0-255之内,那么程序退出之后的退出码为n&255,并且取低8位作为最终的结果

实例说明

退出码——1

除以0

Shell揭秘——程序退出状态码

执行没有权限的操作

Shell揭秘——程序退出状态码

上面直接进入root用户的目录,因为没有权限,查看进程的退出码等于1。

shell内部操作失败——退出码2

a=1
if [ $a -eq 1 ]
then
  echo hello world

比如对于上面的shell脚本是有语法错误的正确的语法还需要在最后加上fi,现在我们执行上面的脚本查看结果:

Shell揭秘——程序退出状态码

退出码126

当因为权限问题或者命令不可以执行那么进程的退出码就是126:

Shell揭秘——程序退出状态码

命令没有找到——退出码127

Shell揭秘——程序退出状态码

信号值——128+n(信号对应的数值)

我们可以使用 kil -l命令查看 linux 操作系统当中信号以及对应的数值:

 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

当我们在命令行使用ctrl+c中断程序的执行的时候,这个正在执行的进程就会接受到SIGINT信号,根据上文这个信号对应的数值为2,因此程序的退出码等于130(128 + 2)。

Shell揭秘——程序退出状态码

下面是一个通过kill命令发送对应的信号的例子:

Shell揭秘——程序退出状态码

可以看到的程序的退出码是符号我们的预期的。

不在范围内不的退出码

不在范围内(0-255)的退出码,需要和 0xff 进行 & 操作,得到的结果作为无符号数作为最终的程序的退出码!

Shell揭秘——程序退出状态码

在上面的例子当中退出码256的二进制表示 1_0000_0000 他和 255(二进制表示为1111_1111)进行与操作得到的结果为1_0000_000,低8位等于0000_0000,因此最终的退出码等于0。

Shell揭秘——程序退出状态码

在上面的图当中-1的二进制表示等于1111_1111 因此最后得到的退出码等于1111_1111 = 255。

C/Python语言获取进程退出的状态码

#include
#include
#include
#include

int main() {

  if(fork() ==  0) {
    _exit(1);  // 子进程执行
  } else {
    // 父进程执行
    int status;
    wait(&status);         // WEXITSTATUS 这个宏就是获取子进程退出时候的退出码
    printf("status = %d\n", WEXITSTATUS(status));
  }
  return 0;
}

在上面的代码当中父进程执行的 wait 函数就是等待子进程的状态变化,当子进程退出的时候 wait 函数会返回,同时将子进程一些状态信息保存在 status 当中,然后我们就可以子进程传递给父进程最后的信息啦。其中 WEXITSTATUS 这个宏就是获取子进程退出时候的退出码!对应的 python 实现如下图所示:

import os
import sys

if __name__ == '__main__':
    pid = os.fork()
    if pid == 0:
        sys.exit(-1)
    else:
        pid, status = os.wait()
        print(os.WEXITSTATUS(status))

总结

在本篇文章当中主要给大家介绍了一些常见的程序退出的状态码!并且给出一下例子帮助大家仔细理解,并且使用C语言和python语言实现获取子进程退出时候的退出状态码。

以上就是本篇文章的所有内容了,我是 LeHung,我们下期再见!!!更多精彩内容合集可访问项目:https://github.com/Chang-LeHung/CSCore

关注公众号: 一无是处的研究僧,了解更多计算机(Java、Python、计算机系统基础、算法与数据结构)知识。

Shell揭秘——程序退出状态码

Original: https://www.cnblogs.com/Chang-LeHung/p/16819836.html
Author: 一无是处的研究僧
Title: Shell揭秘——程序退出状态码

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/711806/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 支持JDK19虚拟线程的web框架,之三:观察运行中的虚拟线程

    本篇借助JProfiler工具,从线程的观察结果去印证官方资料,做到理论结合实践,让您领先一步,掌握和了解神秘的虚拟线程内幕 欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原…

    技术杂谈 2023年7月11日
    0111
  • 1. Two Sum——LeetCode

    Given an array of integers, return indices of the two numbers such that they add up to a s…

    技术杂谈 2023年6月21日
    0100
  • 从Spring中学到的【1】–读懂继承链

    最近看了一些 Spring 源码,发现源码分析的文章很多,而底层思想分析的文章比较少,这个系列文章准备总结一下Spring中给我的启示,包括设计模式思想、SOLID设计原则等,涉及…

    技术杂谈 2023年7月25日
    0121
  • Django框架

    Original: https://www.cnblogs.com/695189322/p/16500888.htmlAuthor: python00000001Title: Dj…

    技术杂谈 2023年6月21日
    087
  • luaFramework

    BeginStaticLibs 参考CustomSettings.cs LuaHelper Debugger Application . lua中使用-> UnityEngi…

    技术杂谈 2023年5月30日
    081
  • Python/Go/Java算法常用模板、数据结构

    记录一些个人在刷leetcode和CF中用的比较多的语法 初始化数组 Golang go语言中定义二维数组和初始化比较特殊,需要先初始化行数再初始化列,定义一个mxn数组:: ma…

    技术杂谈 2023年7月24日
    069
  • Spring事务(三)-事务传播行为

    在Spring里,一个事务方法被另外一个事务方法调用时,两个方法的事务应该如何进行,说白话一点,就是说当出现异常需要回滚时,各个方法的数据操作是否要全部回滚,事务传播行为就是决定了…

    技术杂谈 2023年7月11日
    082
  • 网页正文内容抽取测试

    网页正文内容抽取测试; 通过网页解析,抽取网页正文内容 Original: https://www.cnblogs.com/chenying99/p/10068855.htmlAu…

    技术杂谈 2023年5月31日
    0100
  • vim编辑器命令

    参考: https://blog.csdn.net/weixin_44191814/article/details/120091363 vim编辑器 ## Vim基本模式 【对文件…

    技术杂谈 2023年7月24日
    067
  • 高质量代码的特征

    回想起来,我觉得我们似乎在误读Uncle Bob的Clean Code,至少我们错误地将所谓Clean与可读性代码简单地划上了等号。尤为不幸的是,在Clean Code一书中,从第…

    技术杂谈 2023年5月31日
    0110
  • JDBC学习

    笔记如上 学了个代码 php;gutter:true; import java.sql.*;</p> <p>public class jdbc01 { pu…

    技术杂谈 2023年6月21日
    080
  • Linux文件属性及权限

    Linux文件属性及权限 首先我们以root用户的身份登录linux,执行ls -al 查看文件: 文件类型: 【d】 代表目录(directory)、【-】代表文件、【l】代表链…

    技术杂谈 2023年7月11日
    074
  • Lua语法要点2

    【 Lua语法要点2】 1、Lua函数 function 可以添加 local 关键字。添加后为局部函数,不添加(默认)为全局函数。return 可以 返回多个返回值,以, 分隔。…

    技术杂谈 2023年5月31日
    076
  • 双三次Bezier曲面算法

    双三次Bezier曲面 双三次Bezier曲面由u,v方向的两组三次Bezier曲线交织而成,控制网格由16和控制点构成。 [p(u,v)= \left[\begin{matrix…

    技术杂谈 2023年7月11日
    083
  • 网络中冗余备份

    冗余备份的重要性 如今社会,网络是各个产业的新的血脉,网络的稳定性至关重要,一旦网络出现故障,导致断网、延迟丢包等很可能会导致生产作业停滞,造成较经济损失,为此冗余备份至关重要,从…

    技术杂谈 2023年6月21日
    0114
  • shopify图文编辑如何实现左图右文/右图左文

    怎样让网站更美观?图文并茂是一个比较好的方式。shopify如果想要图文编辑要如何实现呢?比如左图右文、右图左文,有人说用pagefly、automizely等很快就能排版,但这些…

    技术杂谈 2023年5月31日
    082
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球