最近工作中在Linux
下,某些指定的程序需要調(diào)用指定的shell腳本完成指定工作,以前也曾經(jīng)做過類似的功能,調(diào)用system
函數(shù)執(zhí)行指定的腳本,以前并不關(guān)心shell腳本是否執(zhí)行成功了,現(xiàn)在的功能需要根據(jù)shell腳本執(zhí)行成功與否,于是查詢了下system
函數(shù)的說明,有此文以做筆記之用卓囚。
system 函數(shù)說明
#include <stdlib.h>
int system(const char *command);
功能:調(diào)用/bin/sh -c 執(zhí)行指定的腳本 command
常規(guī)使用方法:
int ret = system("./test.sh");
關(guān)于返回值:
-
system
返回值,調(diào)用函數(shù)后的返回值 -
shell
返回值,指腳本執(zhí)行后的返回值
如何判斷腳本是否執(zhí)行成功
- ret == 0
- ret != -1
以上兩個(gè)對(duì)于返回值的判定削茁,是經(jīng)常被使用的,但是正確么私爷。街氢。。
答案是都錯(cuò)
system 返回值說明
man手冊(cè)
The value returned is -1 on error (e.g. fork() failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127).If the value of command is NULL, system() returns non-zero if the shell is available, and zero if not.system() does not affect the wait status of any other children.
看著挺暈的,但是如果對(duì)于system
的執(zhí)行過程了解的話,就很容易理解了,函數(shù)執(zhí)行分為以下幾個(gè)階段。
階段1:創(chuàng)建子進(jìn)程等準(zhǔn)備工作写妥。如果失敗,返回-1
階段2:調(diào)用/bin/sh
拉起腳本,如果拉起失敗或者shell未正常執(zhí)行,原因值被寫入ret中
階段3:如果shell
腳本執(zhí)行成功,shell
腳本的返回值寫入ret中
從上面可知,不管shell
腳本返回什么值,只要調(diào)用了/bin/sh,并且執(zhí)行過程沒有被信號(hào)中斷,都算正常結(jié)束劲弦。因?yàn)槟_本是在子進(jìn)程中執(zhí)行的,所以要想獲取腳本是否執(zhí)行成功的方法只能用系統(tǒng)提供的兩個(gè)宏。
WIFEXITED
用來判斷階段二的返回值
WEXITSTATUS
用來判斷階段三的返回值
由于我們一般在shell
中會(huì)通過返回值判斷腳本是否執(zhí)行成功醇坝,成功返回0邑跪,成功返回整數(shù)。所以判斷一個(gè)腳本是否執(zhí)行成功,應(yīng)該滿足三個(gè)條件:
- -1 != ret
- WIFEXITED(ret)為真
- 0 == WEXITSTATUS(ret)
注意:當(dāng)shell
腳本不存在時(shí)呼猪、沒有執(zhí)行條件等,前兩個(gè)條件也會(huì)成立,此時(shí)WEXITSTATUS(ret)為127,所以shell腳本中不能將127作為返回值,shell腳本中的異常返回值最好從1開始遞增,成功返回0画畅。
實(shí)例代碼
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
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;
}
總結(jié)
system
用起來,看則簡(jiǎn)單,實(shí)則不那么簡(jiǎn)單,有很多隱藏的坑,需要自己深入理解原理,才能更好地使用,也可以用其他實(shí)現(xiàn)方式完成相同的功能宋距。
最后對(duì)自己說,多寫,多思,多總結(jié)