system函數的返回值和執行腳本的返回值

1、先統一兩個說法:
(1)system返回值:指調用system函數后的返回值,比如上例中status為system返回值
(2)shell返回值:指system所調用的shell命令的返回值,比如上例中,test.sh中返回的值為shell返回值。

2、如何正確判斷test.sh是否正確執行?
僅判斷status是否==0?或者僅判斷status是否!=-1?

都錯!

3、man中對于system的說明

RETURN VALUE
?????? 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)
.
看得很暈吧?

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腳本正常執行結束的健全代碼如下:
[cpp]?view plaincopy
  1. #include?<stdio.h>??
  2. #include?<stdlib.h>??
  3. #include?<sys/wait.h>??
  4. #include?<sys/types.h>??
  5. ??
  6. int?main()??
  7. {??
  8. ????pid_t?status;??
  9. ??
  10. ??
  11. ????status?=?system("./test.sh");??
  12. ??
  13. ????if?(-1?==?status)??
  14. ????{??
  15. ????????printf("system?error!");??
  16. ????}??
  17. ????else??
  18. ????{??
  19. ????????printf("exit?status?value?=?[0x%x]\n",?status);??
  20. ??
  21. ????????if?(WIFEXITED(status))??
  22. ????????{??
  23. ????????????if?(0?==?WEXITSTATUS(status))??
  24. ????????????{??
  25. ????????????????printf("run?shell?script?successfully.\n");??
  26. ????????????}??
  27. ????????????else??
  28. ????????????{??
  29. ????????????????printf("run?shell?script?fail,?script?exit?code:?%d\n",?WEXITSTATUS(status));??
  30. ????????????}??
  31. ????????}??
  32. ????????else??
  33. ????????{??
  34. ????????????printf("exit?status?=?[%d]\n",?WEXITSTATUS(status));??
  35. ????????}??
  36. ????}??
  37. ??
  38. ????return?0;??
  39. }??
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().
言歸正傳,下面這段代碼則會導致程序system調用總是返回-1

?
[cpp]?view plaincopy
  1. #include?<stdio.h>??
  2. #include?<stdlib.h>??
  3. #include?<signal.h>??
  4. ??
  5. int?main(int?argc?,char?*argv[])??
  6. {??
  7. ????signal(SIGCHLD,SIG_IGN);??
  8. ????int?status?=?system("ls?-l");??
  9. ????if(status?==?-1)???
  10. ????{?????
  11. ????????printf("system?fork?faild?!\n");??
  12. ????}?????
  13. ????else????
  14. ????{?????
  15. ????????printf("exit?status?value?=?[0x%x]\n",?status);????
  16. ??
  17. ????????if?(WIFEXITED(status))????
  18. ????????{?????
  19. ????????????if?(0?==?WEXITSTATUS(status))????
  20. ????????????{?????
  21. ????????????????printf("run?shell?script?successfully.\n");????
  22. ????????????}?????
  23. ????????????else????
  24. ????????????{?????
  25. ????????????????printf("run?shell?script?fail,?script?exit?code:?%d\n",?WEXITSTATUS(status));????
  26. ????????????}?????
  27. ????????}?????
  28. ????????else????
  29. ????????{?????
  30. ????????????printf("exit?status?=?[%d]\n",?WEXITSTATUS(status));????
  31. ????????}?????
  32. ????}?????
  33. ????return?0;??
  34. } ?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444806.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444806.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444806.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OJ匯總

國內&#xff1a;&#xff08;一下排名不分先后&#xff09; 浙江大學&#xff08;ZJU&#xff09;&#xff1a;http://acm.zju.edu.cn/ 北京大學&#xff08;PKU&#xff09;&#xff1a;http://acm.pku.edu.cn/JudgeOnline/ 同濟大學&#xff08;TJU&#xff09;&#xff1a;…

C++(15)--面向對象編程實踐-歡樂斗地主(vector的花式輸出)

面向對象編程實踐-歡樂斗地主《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------要求&#xff1a;實現錄入及…

Google Protobuf 使用介紹

直接在 www.google.com.hk 上搜索google protobuf 后下載官方版本。 官方版本支持C\Java\Python三門語言。 還有很多非官方的語言版本支持&#xff0c;如C\NET(C#/Vb.net)\Flex(AS3)等. 要通信&#xff0c;必須有協議&#xff0c;否則雙方無法理解對方的碼流。在protobuf中&…

epoll的再次認識

使用mmap加速內核與用戶空間的消息傳遞。 這 點實際上涉及到epoll的具體實現了。無論是select,poll還是epoll都需要內核把FD消息通知給用戶空間,如何避免不必要的內存拷貝就很 重要,在這點上,epoll是通過內核于用戶空間mmap同一塊內存實現的。而如果你想我一樣從2.5內核就關…

leetcode82. 刪除排序鏈表中的重復元素 II

給定一個排序鏈表&#xff0c;刪除所有含有重復數字的節點&#xff0c;只保留原始鏈表中 沒有重復出現 的數字。 示例 1: 輸入: 1->2->3->3->4->4->5 輸出: 1->2->5 示例 2: 輸入: 1->1->1->2->3 輸出: 2->3 思路&#xff1a;判斷n…

C++(16)--運算符重載(自定義Integer類)

運算符重載1.運算符重載--重點2.友元函數--難點(流運算符重載)《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》 -------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)--------…

反應器組件 ACE_Reactor

6.1 反應器組件 ACE_Reactor反應器的基本原理是: 針對關心的某個事件寫一個事件處理器(event_handler). 將該事件處理器登記到反應器中(同時指明關心的事件). 然后反應器會自動檢測事件的發生. 并調用預先登記的事件處理器中的回調函數. 所以ACE Reactor 框架的責任&#x…

C++(17)--詳解const

詳解const《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------1.const修飾成員變量 2.const修飾函數參數 3.c…

cppcheck的安裝和使用

首先從這里下載linux版本的:http://sourceforge.net/projects/cppcheck/files/cppcheck/ 然后下載對應的版本,解壓,之后安裝: 編譯: g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp 安裝: make install

leetcode24 兩兩交換鏈表中的節點

給定一個鏈表&#xff0c;兩兩交換其中相鄰的節點&#xff0c;并返回交換后的鏈表。 你不能只是單純的改變節點內部的值&#xff0c;而是需要實際的進行節點交換。 示例: 給定 1->2->3->4, 你應該返回 2->1->4->3. 思路&#xff1a;這一看就是個遞歸定義&…

再議指針和引用的一些事情吧

關于指針和引用一直是學習C++的同學們爭論的焦點,什么時候用指針,什么時候用引用,還有怎么引用數組,這么用指針訪問數組,以及初始化的問題。 不過有一些文章我在很早就已經寫過,但是由于當時時間不充分,自己也都是隨性寫的,可以參看以前我的一個文章:http://blog.csd…

C++(18)--復制構造函數

復制構造函數《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------包裝基本類&#xff0c;封裝一些算法。 需求…

lua與C++粘合層框架

一. lua調用C 在lua中是以函數指針的形式調用函數, 并且所有的函數指針都必須滿足如下此種類型: typedef int (*lua_CFunction) (lua_State *L);   也就是說, 偶們在C中定義函數時必須以lua_State為參數, 以int為返回值才能被Lua所調用. 但是不要忘記了, 偶們的lua_State是…

leetcode147 對鏈表進行插入排序

丟人&#xff0c;我就是按插入排序老老實實寫的啊。。。。 別人肯定map了hhh。 對鏈表進行插入排序。 插入排序的動畫演示如上。從第一個元素開始&#xff0c;該鏈表可以被認為已經部分排序&#xff08;用黑色表示&#xff09;。 每次迭代時&#xff0c;從輸入數據中移除一個…

PaperNotes(13)-Conditional Image Generation with PixelCNN Decoders

conditional Image generation with PixelCNN DecodersICML的best paperpixel cnn 屬于完全可見的信念網絡&#xff0c;需要對 概率密度 建模。給定圖像數據x&#xff0c;想要對概率分布p(x)建模。概率分布p(x)可以看做&#xff0c;每一像素分布同時作用結果的一個聯合分布。一…

Expression : invalid operator 解決方法

從技術上說&#xff0c;用于排序關聯容器的比較函數必須在它們所比較的對象上定義一個“嚴格的弱序化(strict weak ordering)”。&#xff08;傳給sort等算法的比較函數也有同樣的限制&#xff09;,就是兩個對象比大小或先后的規則&#xff0c;比如兩個 string對象比大小的規則…

leetcode23 合并K個排序鏈表

合并 k 個排序鏈表&#xff0c;返回合并后的排序鏈表。請分析和描述算法的復雜度。 示例: 輸入: [ 1->4->5, 1->3->4, 2->6 ] 輸出: 1->1->2->3->4->4->5->6 思路&#xff1a;把初始的每一個鏈表當成數組中的一個數&#xff0c;做…

Xcode LaunchImage 載入界面大小設置

iPhone Portrait iOS 8-Retina HD 5.5 (12422208) @3x iPhone Portrait iOS 8-Retina HD 4.7 (7501334) @2x iPhone Portrait iOS 7,8-2x (640960) @2x iPhone Portrait iOS 7,8-Retina 4 (6401136) @2x iPhone Portrait iOS 5,6-1x (320480) @1x iPhone Portrait iO…

leetcode237 刪除鏈表中的節點(你意想不到的做法,注意細節)

請編寫一個函數&#xff0c;使其可以刪除某個鏈表中給定的&#xff08;非末尾&#xff09;節點&#xff0c;你將只被給定要求被刪除的節點。 現有一個鏈表 -- head [4,5,1,9]&#xff0c;它可以表示為: 示例 1: 輸入: head [4,5,1,9], node 5 輸出: [4,1,9] 解釋: 給定你鏈…

cppcheck值得注意的一些篩選項

使用完cppcheck進行C代碼檢測之后&#xff0c;可能篩選起來很麻煩&#xff0c;一般常見的優化有 emptiness&#xff0c;就是當你使用stl的時候&#xff0c;最好用empty替代size 還有就是 leak