Linux system函数返回值
摘自:https://blog.csdn.net/cheyo/article/details/6595955
status = system("./test.sh");
或
system("canconfig can0 start");
1、先统一两个说法:
(1)system 返回值:指调用 system 函数后的返回值,比如上例中 status 为 system 返回值
(2)shell 返回值:指 system 所调用的 shell 命令的返回值,比如上例中,test.sh 中返回的值为 shell 返回值。
2、如何正确判断 test.sh 是否正确执行?
仅判断 status 是否 ==0?或者仅判断 status 是否!=-1?
都错!
3、man 中对于 system 的说明
看得很晕吧?
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 != status
- WIFEXITED(status) 为真
- 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().