摘自: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().