Linux system函数返回值

news/2025/2/12 21:13:05/

一、简介

1、语法

#include <stdlib.h>int system(const char *command);

2、函数说明

system()会调用fork()产生子进程,由子进程来调用/bin/sh -c command来执行参数command字符串所代表的命令,此命令执行完后随即返回原调用的进程。

command命令执行完成后,system函数才会返回。--意味着system是阻塞的

在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。

3、返回值

1、先统一两个说法:

(1)system 返回值:指调用 system 函数后的返回值,比如上例中 status 为 system 返回值

(2)shell 返回值:指 system 所调用的 shell 命令的返回值,比如上例中,test.sh 中返回的值为 shell 返回值。

2、如何正确判断 test.sh 是否正确执行?

仅判断 status 是否 ==0?或者仅判断 status 是否!=-1?

都错!

看得很晕吧?

system 函数对返回值的处理,涉及 3 个阶段:

阶段 1:创建子进程等准备工作。如果失败,返回 - 1。

阶段 2:调用 / bin/sh 拉起 shell 脚本,如果拉起失败或者 shell 未正常执行结束(参见备注 1),原因值被写入到 status 的低 8~15 比特位中。system 的 man 中只说明了会写了 127 这个值,但实测发现还会写 126 等值。

阶段 3:如果 shell 脚本正常执行结束,将 shell 返回值填到 status 的低 8~15 比特位中。

备注 1:

只要能够调用到 / bin/sh,并且执行 shell 过程中没有被其他信号异常中断,都算正常结束。
比如:不管 shell 脚本中返回什么原因值,是 0 还是非 0,都算正常执行结束。即使 shell 脚本不存在或没有执行权限,也都算正常执行结束。
如果 shell 脚本执行过程中被强制 kill 掉等情况则算异常结束。

如何判断阶段 2 中,shell 脚本是否正常执行结束呢?系统提供了宏:WIFEXITED(status)。如果 WIFEXITED(status) 为真,则说明正常结束。

如何取得阶段 3 中的 shell 返回值?你可以直接通过右移 8bit 来实现,但安全的做法是使用系统提供的宏:WEXITSTATUS(status)。

由于我们一般在 shell 脚本中会通过返回值判断本脚本是否正常执行,如果成功返回 0,失败返回正数。

所以综上,判断一个 system 函数调用 shell 脚本是否正常结束的方法应该是如下 3 个条件同时成立:

  1. -1 != status
  2. WIFEXITED(status) 为真
  3. 0 == WEXITSTATUS(status)

注意:

根据以上分析,当 shell 脚本不存在、没有执行权限等场景下时,以上前 2 个条件仍会成立,此时 WEXITSTATUS(status) 为 127,126 等数值。

所以,我们在 shell 脚本中不能将 127,126 等数值定义为返回值,否则无法区分中是 shell 的返回值,还是调用 shell 脚本异常的原因值。shell 脚本中的返回值最好多 1 开始递增。

判断 shell 脚本正常执行结束的健全代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>int main()
{pid_t status;status = system("./test.sh");if (-1 == status){printf("system error!");}else{printf("exit status value = [0x%x]\n", status);if (WIFEXITED(status)){if (0 == WEXITSTATUS(status)){printf("run shell script successfully.\n");}else{printf("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));}}else{printf("exit status = [%d]\n", WEXITSTATUS(status));}}return 0;
}

WIFEXITED(stat_val) Evaluates to a non-zero value if status
was returned for a child process that
terminated normally.
WEXITSTATUS(stat_val) If the value of WIFEXITED(stat_val) is
non-zero, this macro evaluates to the
low-order 8 bits of the status argument
that the child process passed to _exit()
or exit(), or the value the child
process returned from main().

ref:

https://www.cnblogs.com/Rainingday/p/15070262.html

从Linux system()函数谈起 – 又见杜梨树

system(3) - Linux manual page

https://linux.die.net/man/3/system

宏伟精讲·linux system()函数完全解密 - 知乎

system函数的原理和调用方法_c++system函数原理-CSDN博客

linux system 函数源代码分析-ShadowSrX-ChinaUnix博客

system.c - sysdeps/posix/system.c - Glibc source code (glibc-2.38) - Bootlin


http://www.ppmy.cn/news/1152610.html

相关文章

OpenCV实现人脸关键点检测

目录 实现过程 1&#xff0c;代码解读 1.1 导入工具包 1.2导入所需图像&#xff0c;以及训练好的人脸预测模型 1.3 将 dlib 的关键点对象转换为 NumPy 数组&#xff0c;以便后续处理 1.4图像上可视化面部关键点 1.5# 读取输入数据&#xff0c;预处理 1.6进行人脸检测 1…

灿芯股份将上会:计划募资6亿元,董事长、总经理均为外籍

10月11日&#xff0c;上海证券交易所披露的信息显示&#xff0c;灿芯半导体&#xff08;上海&#xff09;股份有限公司&#xff08;下称“灿芯股份”&#xff09;将于10月18日接受上市审核委员会审议会议的现场审议。目前&#xff0c;该公司已递交了招股书&#xff08;上会稿&a…

项目串讲(后端)要讲哪些东西?

刚进入一家公司&#xff0c;leader说给你几天时间&#xff0c;对咱们的公司的项目熟悉熟悉&#xff0c;做一个串讲吧。我很慌&#xff0c;没有串讲过&#xff0c;啥也不知道&#xff0c;不知道该怎么写&#xff0c;不知道讲出来leader满不满意&#xff0c;这些都是我在串讲前的…

四、RocketMQ发送普通消息、批量消息和延迟消息

Producer发送普通消息的方式 1.同步发送消息 同步消息代表发送端发送消息到broker之后&#xff0c;等待消息发送结果后&#xff0c;再次发送消息 实现步骤 创建生产端&#xff0c;声明在哪个生产组注册NameServer地址构建Message实体&#xff0c;指定topic、tag、body启动…

Elasticsearch —索引性能技巧

目录 一、科学的测试性能 二、使用批量请求并调整其大小 三、存储 四、段和合并 五、其他 如果你是在一个索引负载很重的环境&#xff0c;比如索引的是基础设施日志&#xff0c;你可能愿意牺牲一些搜索性能换取更快的索引速率。在这些场景里&#xff0c;搜索常常是很少见的…

LangChain的发展史

LangChain 发展史 LangChain 的作者是 Harrison Chase&#xff0c;最初是于 2022 年 10 月开源的一个项目&#xff0c;在 GitHub 上获得大量关注之后迅速转变为一家初创公司。2017 年 Harrison Chase 还在哈佛上大学&#xff0c;如今已是硅谷的一家热门初创公司的 CEO&#xf…

element树形控件单选

需求功能&#xff1a; 1&#xff0c;element树形控件单选 2&#xff0c;双击节点编辑 <div style"height: calc(100% - 48px)"><el-scrollbar class"scrollbar-wrapper"><el-tree :data"treesObj" show-checkbox default-expan…