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 的說明

image

看得很暈吧?

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().


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM