在 Linux 中,错误码(通常指系统调用或库函数返回的错误)可以通过以下几种方式获取和处理,Linux 系统调用错误码,如何快速定位和处理致命错误?,Linux系统调用错误码,如何快速定位和处理致命错误?
系统调用错误码(errno)详解
在Linux系统编程中,当系统调用(如open()、read()、write()等)执行失败时,通常会返回-1并设置全局变量errno来指示具体的错误原因。errno是线程局部变量,每个线程都有自己独立的errno副本。
错误码获取与处理方法
#include <errno.h> // 必须包含的头文件
#include <stdio.h>
#include <string.h>
int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
// 方法1:直接输出错误码数字
printf("Error code: %d\n", errno);
// 方法2:转换为可读的错误消息
printf("Error message: %s\n", strerror(errno));
// 方法3:使用perror自动附加错误描述(推荐方式)
perror("fopen failed");
// 方法4:线程安全版本(POSIX标准)
char err_msg[256];
strerror_r(errno, err_msg, sizeof(err_msg));
printf("Thread-safe error: %s\n", err_msg);
}
return 0;
}
常见系统错误码详解
| 错误码 | 宏定义 | 描述 | 典型场景 |
|---|---|---|---|
| 1 | EPERM |
操作权限不足 | 普通用户尝试修改系统文件 |
| 2 | ENOENT |
文件或目录不存在 | 访问不存在的路径 |
| 13 | EACCES |
访问被拒绝 | 文件权限不足 |
| 17 | EEXIST |
文件已存在 | 创建已存在的文件 |
| 28 | ENOSPC |
设备空间不足 | 磁盘已满 |
| 22 | EINVAL |
无效参数 | 传递了非法参数给系统调用 |
| 5 | EIO |
输入/输出错误 | 硬件设备故障 |
| 12 | ENOMEM |
内存不足 | 内存分配失败 |
| 110 | ETIMEDOUT |
操作超时 | 网络连接超时 |
提示:完整错误码列表可通过以下方式查看:
- 命令行:
man errno- 头文件:
/usr/include/asm-generic/errno-base.h(基础错误码)- 头文件:
/usr/include/asm-generic/errno.h(扩展错误码)

Shell命令退出状态码解析
在Shell脚本中,每个命令执行后都会返回一个退出状态码,通过特殊变量获取,状态码范围是0-255,其中0表示成功,非零表示失败。
基本使用方法
ls /nonexistent # 故意执行一个会失败的命令
echo $? # 输出非零错误码(通常为2)
# 实际编程中的典型用法
if ! command; then
echo "Command failed with status: $?"
exit 1
fi
常见退出状态码详解
| 状态码 | 含义 | 典型场景 |
|---|---|---|
| 0 | 命令执行成功 | 正常执行完毕 |
| 1 | 一般性错误 | 命令参数错误或运行时错误 |
| 2 | 命令语法错误 | Shell脚本语法错误 |
| 126 | 命令不可执行 | 文件权限不足或非可执行文件 |
| 127 | 命令未找到 | 输入了不存在的命令 |
| 128+N | 命令被信号N终止 | 进程被信号终止 |
| 130 | 命令被Ctrl+C终止 | 对应SIGINT(2)信号 |
| 137 | 命令被强制终止 | 对应SIGKILL(9)信号 |
信号处理与状态码关系
当进程被信号终止时,Shell会返回128加上信号编号的值:
# 发送SIGTERM(15)给当前进程 kill -15 $$ echo $? # 输出143 (128 + 15) # 提取信号编号的两种方法 echo $(( $? & 127 )) # 按位与运算 echo $(( $? - 128 )) # 算术运算 # 常见信号编号 # 2: SIGINT (Ctrl+C) # 9: SIGKILL (强制终止) # 15: SIGTERM (优雅终止)

高级调试工具集锦
strace - 系统调用跟踪器
# 基本用法 strace ls /nonexistent # 高级用法 strace -e trace=open,read,write ./program # 只跟踪特定系统调用 strace -o trace.log -f ./program # 跟踪子进程并输出到文件 strace -p <PID> # 跟踪运行中的进程 strace -c ./program # 统计系统调用耗时
perror - 错误码解释工具
perror 2 # 输出:Error code 2: No such file or directory # 批量查询多个错误码 for err in 1 2 13; do perror $err; done
errno命令(部分系统提供)
errno -l # 列出所有错误码及其描述 errno 2 # 查询特定错误码 errno EPERM # 通过宏名查询
ltrace - 库函数调用跟踪器
ltrace ./program # 跟踪动态库函数调用
错误处理速查表
| 场景 | 处理方法 | 示例 | 适用语言 |
|---|---|---|---|
| C程序系统调用错误 | errno + perror()/strerror() |
perror("open failed"); |
C |
| Shell命令错误 | 变量 | if [ $? -ne 0 ]; then... |
Shell |
| 信号导致的错误 | $? & 127 |
signal=$(( $? & 127 )) |
Shell |
| 系统级调试 | strace工具 |
strace -f ./program |
通用 |
| 库函数调用调试 | ltrace工具 |
ltrace ./program |
通用 |
| 快速错误查询 | perror命令 |
perror 13 |
通用 |
| 线程安全错误处理 | strerror_r() |
见下方示例 | C |
最佳实践与进阶技巧
错误处理最佳实践
- 始终检查返回值:特别是系统调用和库函数的返回值
- 使用perror:比直接使用errno更便捷,能自动附加描述
- 考虑线程安全:在多线程环境中,使用
strerror_r替代strerror - 自定义错误处理:大型项目可考虑统一的错误处理机制
- 错误码分类:将错误分为可恢复和不可恢复两类区别处理
线程安全错误处理示例
#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <string.h>
void handle_error(const char *context) {
char buf[256];
char *msg = strerror_r(errno, buf, sizeof(buf));
fprintf(stderr, "[ERROR] %s: %s (errno=%d)\n", context, msg, errno);
}
int safe_file_open(const char *path) {
FILE *fp = fopen(path, "r");
if (fp == NULL) {
handle_error("safe_file_open");
return -1;
}
// 其他操作...
fclose(fp);
return 0;
}
Shell脚本错误处理技巧
#!/bin/bash
# 设置错误处理选项
set -euo pipefail
# 自定义错误处理函数
error_handler() {
local status=$?
local signal=""
if [ $status -ge 128 ]; then
signal=" (signal $((status-128)))"
fi
echo "[$(date)] Error in 错误码与异常的结合(C++示例)
: Line - Exit status: $status$signal" >&2
exit $status
}
trap 'error_handler $LINENO' ERR
# 示例命令
ls /nonexistent
#include <system_error>
#include <iostream>
void check_system_error(int rc) {
if (rc == -1) {
throw std::system_error(
errno,
std::system_category(),
"System call failed"
);
}
}
int main() {
try {
FILE* file = fopen("nonexistent.txt", "r");
check_system_error(file ? 0 : -1);
} catch (const std::system_error& e) {
std::cerr << "Error: " << e.what()
<< " (code: " << e.code() << ")\n";
return e.code().value();
}
return 0;
}
通过深入理解Linux系统的错误处理机制,开发者可以:
- 编写更健壮的应用程序
- 实现更优雅的错误恢复策略
- 提高系统的可维护性和可靠性
掌握这些错误处理技术后,您将能够更有效地解决Linux系统中的各类问题,并构建更稳定的应用程序。
相关阅读:
1、VPS文件页数轻松删除秘籍,操作指南揭秘!
2、如何在Linux系统中查看用户所属组及管理用户组权限,Linux用户组管理全攻略,如何快速查看用户所属组并精准控制权限?,Linux用户组权限管理,如何一键查看用户所属组并精准掌控权限?
3、ARM VPS上轻松安装安卓系统教程
4、微软系统VPS登录教程,轻松操作指南
5、在 Linux 系统中修改日期和时间可以通过多种方法实现,具体取决于你的需求和权限。以下是常用的几种方法,如何在Linux系统中快速修改日期和时间?,震惊!Linux系统修改时间竟有这些隐藏技巧?
高防服务器,游戏服务器,高防IP,服务器租用托管






