# 容器异常退出状态码
当容器启动失败或终止时，K8s事件中将会打印容器异常退出状态码（Exit Code）来报告容器异常的原因。本文将介绍如何通过事件中打印的Exit Code进一步定位容器异常的根本原因。
#### 查看容器异常退出状态码
您可使用kubectl连接集群，并通过以下命令查询Pod详细状态：
```
kubectl describe pod {pod name}
```
在返回结果中的Exit Code字段即为程序上次退出时的状态码，该值不为0即表示程序异常退出，可根据退出状态码进一步分析异常原因。
```
Containers: 
  container-1: 
    Container ID: ... 
    Image: ... 
    Image ID: ... 
    Ports: ... 
    Host Ports: ... 
    Args: ... 
    State: Running    
      Started: Sat, 28 Jan 2023 09:06:53 +0000 
    Last State: Terminated    
      Reason: Error    
      Exit Code: 255    
      Started: Sat, 28 Jan 2023 09:01:33 +0000    
      Finished: Sat, 28 Jan 2023 09:05:11 +0000 
    Ready: True 
    Restart Count: 1
```
#### 退出状态码说明
容器退出状态码的范围为0\~255之间：
- 0表示正常退出。
- 一般由于程序自身原因导致的异常退出，状态码区间在1\~128。在特殊场景下，程序也可以使用129\~255区间的状态码。
- 由于外界中断导致程序退出时，状态码区间在129\~255。当操作系统给程序发送[中断信号]时，程序退出时的状态码为操作系统的中断信号值加128。例如， SIGKILL（强制停止）的中断信号值为9，那么程序退出状态码则为9+128 = 137。
- 当指定的状态码不在0\~255范围内时（例如使用exit(-1)），将自动转化至0\~255范围内。 当指定的状态码为正数，转换公式如下：
  ```
  code % 256
  ```
  当指定的状态码为负数，转换公式如下：
  ```
  256 - (|code| % 256)
  ```
  
更多退出状态码说明请参见[Exit Codes With Special Meanings](https://tldp.org/LDP/abs/html/exitcodes.html)。
#### 常见的容器异常退出状态码
表1常见的容器异常退出状态码 
| 容器异常退出状态码 | 名称            | 含义                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
|:---|:---|:---|
| 0         | 正常退出           | 表示容器正常退出。该状态码不一定表示存在异常，例如，当容器内没有进程时，也会出现退出状态码为0的场景。                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| 1       | 一般程序错误         | 引起该异常状态的原因较多，大多由于程序自身错误导致，需要进一步通过容器日志定位原因。例如在ARM节点上运行X86镜像时，会出现该错误。                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| 125       | 容器未能运行          | 发生这种情况的常见原因有如下几种： - 命令中使用了未定义的flag，例如docker run --abcd。  - 镜像中用户定义的命令在本机权限不足。  - 容器运行时与宿主机操作系统或硬件不兼容。                                                                                                                                                                                     |
| 126     | 命令调用错误         | 镜像中调用的命令无法执行，例如文件权限不足或文件不可执行。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| 127      | 找不到文件或目录       | 无法找到镜像中指定的文件或目录。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| 128       | 无效的退出参数         | 容器退出但未提供有效的退出代码，可能的原因有多种，需要进一步定位原因。例如containerd节点上运行的应用尝试调用docker命令。                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| 137     | 立即终止（SIGKILL）  | 表示程序被SIGKILL信号终止，常见的原因有如下几种： - Pod中容器内存达到了其资源限制（resources.limits）。例如，内存溢出（OOM）会导致cgroup强制停止该容器。  - 运行容器的节点本身资源不足（OOM），则节点内核会选择停止一些进程来释放内存，可能会导致容器被终止。  - 容器健康检查失败，kubelet会停止该容器。  - 其他外部进程强制停止容器，例如恶意脚本。   |
| 139       | 分段错误（SIGSEGV） | 表示容器收到了来自操作系统的SIGSEGV信号，由于容器试图访问无权限的内存位置引起。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| 143      | 优雅终止（SIGTERM）  | 表示容器在主机指示后正确关闭。一般来说，退出码143不需要进行故障排除。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| 255      | 状态码超出范围        | 表示容器退出状态码超出范围。例如，可能是设置异常退出使用exit(-1)导致的，而-1将会自动转换成255。 出现该异常时无法判断原因，需要进一步通过容器日志定位原因。                                                                                                                                                                                                                                                                                                                                                                                                       |
   
 #### Linux标准中断信号
您可以使用**kill -l**命令查看Linux操作系统中信号以及对应的数值。
表2常用的Linux标准中断信号 
| 信号（Signal）  | 状态码（Value） | 动作（Action） | 描述（Commit）                          |
|:---|:---|:---|:---|
| SIGHUP     | 1          | Term       | 用户终端连接（正常或非正常）结束时发出                 |
| SIGINT     | 2         | Term      | 程序终止信号，通常由终端发出中断指令，例如键盘输入Ctrl+C   |
| SIGQUIT   | 3        | Core     | 和SIGINT类似，由终端发出退出指令，通常是键盘输入Ctrl+\\来控制 |
| SIGILL    | 4         | Core        | 非法指令，通常是因为可执行文件本身出现错误               |
| SIGABRT  | 6         | Core         | 调用abort函数时产生的信号，进程会非正常结束              |
| SIGFPE   | 8        | Core       | 发生浮点运算错误，出现除数为0等其它算术错误时也会产生          |
| SIGKILL   | 9        | Term     | 终止任何进程                               |
| SIGSEGV   | 11        | Core      | 试图访问无权限的内存位置                        |
| SIGPIPE   | 13         | Term       | 管道断开信号                               |
| SIGALRM    | 14        | Term       | 时钟定时信号                            |
| SIGTERM | 15         | Term       | 进程结束信号，通常是程序自行正常退出                 |
| SIGUSR1   | 10      | Term        | 用户在应用程序中自行定义的信号                       |
| SIGUSR2     | 12         | Term      | 用户在应用程序中自行定义的信号                      |
| SIGCHLD  | 17       | Ign        | 子进程结束或中断时产生该信号                      |
| SIGCONT    | 18      | Cont       | 让一个暂停（stopped）的进程继续执行                |
| SIGSTOP   | 19        | Stop        | 暂停进程的执行                               |
| SIGTSTP    | 20         | Stop        | 停止进程的运行                            |
| SIGTTIN     | 21        | Stop      | 后台进程从终端读取输入值                         |
| SIGTTOU  | 22        | Stop      | 后台进程从终端读取输出值                        |
   
