Steins;Lab

  • 项目
  • 折腾
  • 笔记
  • 图册
  • 杂谈
  • 文章索引 - 博主自荐博文
  • 关于/留言
Steins;Lab
某团的自留研究所
  1. 首页
  2. 学习笔记
  3. 正文

stderr, exit status 与 Go os/exec 错误捕捉

2022年7月31日 3518点热度 0人点赞 1条评论

Unix-like 操作系统中,程序的 stderr、exit status,以及 Go 语言如何捕捉命令执行错误实例。

 

Table of Contents

  • 1 stderr
    • 1.1 standard stream
    • 1.2有stderr输出意味着程序失败吗?
    • 1.3输出重定向
  • 2 status code
    • 2.1错误捕捉
    • 2.2常见错误约定
  • 3 Go os/exec错误捕捉
  • 4 小结
  • 参考资料

在一次开发中,需要用 Go 语言的 os/exec 包执行命令、捕获成功与否。

本文在此梳理 Unix-like 操作系统中进程对错误信息的处理,并提供了几组实例。

 

1 stderr

1.1 standard stream

stderr 即 standard error,定义于POSIX标准中,是进程用来输出错误信息的文件描述符。

在Linux中,有3种标准流(standard stream),分别为stdin,stdout, stderr。

这些标准流也被当做文件看待,因此也有对应的文件描述符做标识。

文件描述符 名称
0 stdin
1 stdout
2 stderr

如此设计,一个进程的错误输出和标准输出可以分别被处理。

 

1.2有stderr输出意味着程序失败吗?

Tip:
我们最终目的是使用 os/exec 捕捉错误信息。 所以需要了解到,有错误输出并不一定意味着程序发生了致命错误。

比如 ffmepg 中编解码可能遇到一些被容忍的错误,并输出 stderr 异常信息。但并不意味着该程序执行失败。

 

1.3输出重定向

我们在shell中执行命令,可以使用 > 将输出流重定向,比如到文件中。

经常见到的 2>&1 ,即将 stderr 重定向到 stdout 中, 并保持原有 stdout 输出。

实例:

ls 的重定向输出
ls 存在的文件时,返回标准输出 stdout,反之输出到 stderr。

# 实验目录总览
➜  ls -lh
total 0
-rw-rw-r-- 1 pi pi 0 7 月  31 17:38 1.txt

# stdout
➜  ls -lh 1.txt 1>/dev/null
➜  ls -lh 1.txt
-rw-rw-r-- 1 pi pi 0 7 月  31 17:38 1.txt

# stderr
➜  ls -lh 2.txt
ls: cannot access '2.txt': No such file or directory
➜  ls -lh 2.txt 1>/dev/null
ls: cannot access '2.txt': No such file or directory
➜  ls -lh 2.txt 2>/dev/null

# 重定向 2>&1, 一并输出到文件
➜  ls -lh 2.txt > result.txt 2>&1
# 查看得到的文件内容
➜  cat ./result.txt 
ls: cannot access '2.txt': No such file or directory

 

 

2 status code

status code 是Linux中进程执行返回的退出代码,用于标志成功与否。为0时,标志成功执行,非零表示发生错误。

 

2.1错误捕捉

在shell中可以使用 $? 来捕捉上次命令的退出状态。

# status code = 0
➜  ls -lh 1.txt                  
-rw-rw-r-- 1 pi pi 0 7 月  31 17:38 1.txt
➜  echo $?
0

# status code != 0
➜ ls -lh 2.txt
ls: cannot access '2.txt': No such file or directory
➜  echo $?
2

在一些多功能的shell套件中,如oh-my-zsh,可配置直接将 status code 以各种形式快捷显示出来,如:

 

2.2常见错误约定

一般情况为0时,标志成功执行,非零表示发生错误。

具体可以参考 Appendix E. Exit Codes With Special Meanings - Advanced Bash-Scripting Guide

 

 

3 Go os/exec错误捕捉

假设情景为,我们需要使用Go语言执行 nginx -s reload 指令,并捕捉是否成功。

os/exec 包为我们提供了健壮的外部命令调用。包内的 cmd 能够让我们自行指定stdin,stdout,stderr的IO输入输出。

为了实现简单,我们可以使用 CombinedOutput() 将stdout,stderr组合作为输出(即2>&1),然后捕获 cmd 自身的错误或程序输出的异常 status code。

 

实例Go代码

package main

import (
    "fmt"
    "os/exec"
)

func main() {
        ReloadNginx()
}

func ReloadNginx() {
        cmd := exec.Command("/usr/sbin/nginx", "-s", "reload")
    output, err := cmd.CombinedOutput()
    if err != nil {
                fmt.Println("[ERROR] Reload nginx failed:", err)
                fmt.Println("[ERROR] Reload nginx output:", string(output))
        return
    }
    fmt.Println("[INFO] Reload nginx success:", string(output))
}

 

失败时的捕获

➜  sudo ./main            
[ERROR] Reload nginx failed:  exit status 1
[ERROR] Reload nginx output:  nginx: [alert] could not open error log file: open()"/var/log/nginx/error.log" failed (13: Permission denied)
2022/07/31 19:33:50 [warn] 2390199#2390199: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:1
2022/07/31 19:33:50 [notice] 2390199#2390199: signal process started
2022/07/31 19:33:50 [error] 2390199#2390199: open()"/run/nginx.pid" failed (2: No such file or directory)

 

成功时的输出

➜  sudo ./main
[INFO] Reload nginx success:  

 

 

4 小结

梳理了 stderr exit status,写了个简单的错误捕捉例程。

对于我们自己编写的程序或者shell脚本,只要遵守上述的输出和返回码,就可以方便地被第三方调用和捕获状态。

 

 

参考资料

  • Linux bash exit status and how to set exit status in bash
  • Appendix E. Exit Codes With Special Meanings
  • go os/exec简明教程

相关

标签: 暂无
最后更新:2022年7月31日

SPtuan

SPtuan 是一名普通的工程师,最大的愿望是度过平静的时光。 当前从事网络/CDN/对象存储研发。

点赞
< 上一篇
下一篇 >
0 0 votes
文章评分
Subscribe
Login
提醒
guest

guest

1 评论
最新
最旧 得票最多
Inline Feedbacks
View all comments
SPtuan
SPtuan
作者
2 年 之前

我的这套 wordpress 实在是太老旧了,markdown 写的笔记发表在上面展示得一塌糊涂,排版非常痛苦。
真应该找个时间修整一番

0
回复

SPtuan

SPtuan 是一名普通的工程师,最大的愿望是度过平静的时光。
当前从事网络/CDN/对象存储研发。

  • 1 stderr
    • 1.1 standard stream
    • 1.2有stderr输出意味着程序失败吗?
    • 1.3输出重定向
  • 2 status code
    • 2.1错误捕捉
    • 2.2常见错误约定
  • 3 Go os/exec错误捕捉
  • 4 小结
  • 参考资料
分类
  • Uncategorized
  • 图册
  • 学习笔记
  • 库
  • 折腾
  • 杂谈
  • 瞎**扯
  • 碎碎念
  • 项目跟踪
最近评论
SPtuan 发布于 2 个月前(03月22日) 书签: 关于 disk-io 的经验, 异步/同步 io 系统设计的经验 https://you...
SPtuan 发布于 2 个月前(03月21日) 如果公司不是对外提供这些服务的,这种岗位都是 infra 部门,平均年龄确实会大一些。尤其构建和维护...
HUA 发布于 2 个月前(03月19日) 想请问博主对于国内CDN行业,以及CDN调度、DNS托管类服务相关岗位的看法,以及是否还推荐校招新人...
SPtuan 发布于 3 个月前(02月03日) 2025 注: 长辈对于只身去深圳的担忧,更多地来自于 80s/90s 治安情况。近几年了解了严打...
SPtuan 发布于 4 个月前(01月16日) 哈哈,100就100吧,新年快乐!
热门主题 & 页面
  • 全球互联网拓扑探索 (1) : 互联网是如何工作的
  • Intel Movidius Neural Compute Stick - 英特尔Movidius神经计算棒上手体验
  • iowait 到底是什么?
  • 使用 WSL2 + X11 转发 - 在 Windows10 中打造 GNU/Linux 学习生产环境
  • 动手做!基于nRF24L01P的Arduino无线通信
归档
  • 2025 年 5 月
  • 2025 年 3 月
  • 2024 年 12 月
  • 2024 年 9 月
  • 2024 年 8 月
  • 2024 年 5 月
  • 2024 年 3 月
  • 2024 年 2 月
  • 2023 年 12 月
  • 2023 年 11 月
  • 2023 年 9 月
  • 2023 年 8 月
  • 2023 年 4 月
  • 2023 年 1 月
  • 2022 年 12 月
  • 2022 年 10 月
  • 2022 年 9 月
  • 2022 年 7 月
  • 2022 年 6 月
  • 2022 年 2 月
  • 2021 年 12 月
  • 2021 年 11 月
  • 2021 年 2 月
  • 2021 年 1 月
  • 2020 年 9 月
  • 2020 年 4 月
  • 2020 年 3 月
  • 2020 年 1 月
  • 2019 年 8 月
  • 2019 年 7 月
  • 2019 年 5 月
  • 2019 年 4 月
  • 2019 年 3 月
  • 2019 年 2 月
  • 2018 年 12 月
  • 2018 年 10 月
  • 2018 年 9 月
  • 2018 年 8 月
  • 2018 年 5 月
  • 2018 年 2 月
  • 2018 年 1 月
  • 2017 年 11 月
  • 2017 年 9 月
  • 2017 年 7 月
  • 2017 年 6 月
  • 2017 年 5 月
  • 2017 年 4 月
  • 2017 年 3 月
  • 2017 年 2 月
  • 2017 年 1 月
  • 2016 年 12 月
  • 2016 年 11 月
  • 2016 年 10 月
  • 2016 年 9 月
  • 2016 年 8 月
  • 2016 年 7 月
  • 2016 年 6 月
  • 2016 年 5 月
  • 2016 年 4 月
  • 2016 年 3 月
  • 2016 年 2 月
  • 2016 年 1 月
  • 2015 年 12 月
  • 2015 年 11 月
  • 2015 年 9 月

友情链接:

Blessing Studio hahaschool 绘枫和畅 魔法少女Fandy monsterx Clarke的博客 Luminous’ Home Shintaku's Blog
蓝黑的博客 haruhi.club Yida的博客 Bo2SS 涛叔 TangBao 同和君Hocassian

Steins;Lab 团子神社 zdfmc.net

steinslab.io built with ❤. Thanks for all 2015-2025.

Theme Kratos Made By Seaton Jiang

wpDiscuz