摘要:背景幸福的生活總是相似的,天降的大鍋各有各不同。那現(xiàn)在其實(shí)一目了然了,調(diào)用了觸發(fā)初始化了,在初始化變量時(shí)候調(diào)用了,因?yàn)楂@取父目錄失敗了,所以輸出了那段錯(cuò)誤。
背景
幸福的生活總是相似的,天降的大鍋各有各不同。
我們有個(gè)功能是這樣的:有個(gè)以 root 運(yùn)行的 python 程序,它需要以 test 用戶執(zhí)行 linux 命令,所以就通過 subprocess 庫(kù) + sudo 來執(zhí)行,也就是下面的關(guān)系圖:
./test_b 就是這么一個(gè)很簡(jiǎn)單的需求,本來是沒有什么太大的問題的,然而事實(shí)總是喜歡打我們臉。
就輸出下面的錯(cuò)誤了:
雖然上面的錯(cuò)誤不會(huì)影響程序的運(yùn)行,但是處女座沒法忍,一定要干干凈凈,明明白白!
錯(cuò)誤定位憑借過硬的英語水平,我們明白這個(gè)報(bào)錯(cuò)是因?yàn)樵L問不到父目錄導(dǎo)致 getcwd 出錯(cuò)了。
聰明的童鞋一想就覺得是不是和上面的刪除目錄有關(guān)系,這時(shí)候肯定得看看 test_b 是什么內(nèi)容,說不定能解決我們的疑問:
#!/usr/bin/python import time import os time.sleep(3) os.system("sleep 1")
那么問題來了,test_b 明明就只想睡個(gè)覺,不想涉足江湖事,也沒有調(diào)用getcwd,為什么會(huì)輸出這個(gè)報(bào)錯(cuò)咧!
在我們毫無頭緒時(shí),可以去喝喝快樂肥宅水,說不定就能脈動(dòng)回來。
因?yàn)槲揖褪沁@樣看到找到線索了:shell-init。
憑借過硬的英語水平,我們可以看到這個(gè)錯(cuò)誤應(yīng)該在 shell 初始化時(shí)候報(bào)的,這樣很明顯啦,去搜 bash 代碼。
很快我們就找到這句錯(cuò)誤定義的地方了:
root@bash-4.4 $ grep "shell-init" -r * variables.c: temp_string = get_working_directory ("shell-init");
看到 get_working_directory 這個(gè)函數(shù)名這么正規(guī),感覺這事靠譜了,順著看看內(nèi)容:
// builtins/common.c char * get_working_directory (for_whom) char *for_whom; { ... (跳過) if (the_current_working_directory == 0) { fprintf (stderr, _("%s: error retrieving current directory: %s: %s "), (for_whom && *for_whom) ? for_whom : get_name_for_error (), _(bash_getcwd_errstr), strerror (errno)); return (char *)NULL; } ... (跳過) }
雖然大部分是通過變量傳值進(jìn)去,但是還是能看出就是咱們那句報(bào)錯(cuò)的原型了,
其實(shí)上面的代碼實(shí)現(xiàn)并不是最關(guān)鍵的,關(guān)鍵的是,這些代碼文件是在 bash 里面的,為什么system 會(huì)和bash 扯上關(guān)系呢?難道 system 還需要擼一發(fā) shell 么,崩潰!我心目中的 system 不是這么隨便的!
System 源碼帶著不甘心去搜它的實(shí)現(xiàn):
int system(const char * cmdstring) { pid_t pid; int status; if(cmdstring == NULL){ return (1); } if((pid = fork())<0){ status = -1; } else if(pid = 0){ execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); exit(127); //子進(jìn)程正常執(zhí)行則不會(huì)執(zhí)行此語句 } else{ while(waitpid(pid, &status, 0) < 0){ if(errno != EINTER){ status = -1; break; } } } return status; }
它的出廠設(shè)置就是這樣,原來是我一直沒去深入了解它。
那現(xiàn)在其實(shí)一目了然了,system調(diào)用了 /bin/sh, 觸發(fā)shell 初始化了, 在初始化變量時(shí)候調(diào)用了
get_working_directory,因?yàn)楂@取父目錄失敗了,所以輸出了那段錯(cuò)誤。
既然我們知道錯(cuò)誤是 system 輸出的,那么我們換個(gè)方式就應(yīng)該能規(guī)避咯?
于是乎,./test_b 代碼改成這樣就不報(bào)錯(cuò)了:
#!/usr/bin/python import time import os time.sleep(3) # os.system("sleep") os.execl("/bin/sleep", "sleep", "1")
那么這里又引出了一個(gè)問題了
system 和 execl 都能執(zhí)行系統(tǒng)命令,那兩者有什么區(qū)別呢?
答案在上面的 system 的源碼已經(jīng)給出 80% 了,他們的區(qū)別就是:
system = fork + execl + waitpid
而 execl 只是系統(tǒng) exec 族函數(shù)的其中一個(gè),說到 exec 族函數(shù),它們是將新的程序內(nèi)容替換當(dāng)前進(jìn)程內(nèi)容運(yùn)行,具體大家可以去谷歌看看,這邊就不多說了~
我們對(duì) system 的實(shí)現(xiàn)已經(jīng)有一定熟悉了,在后面使用這個(gè)方法時(shí)候,不管是在資源使用還是問題排查,都應(yīng)該多一些意識(shí),眼不見不代表沒關(guān)系~
歡迎各位大神指點(diǎn)交流, QQ討論群: 258498217
轉(zhuǎn)載請(qǐng)注明來源: https://segmentfault.com/a/11...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/42856.html
摘要:模塊實(shí)現(xiàn)從程序外部向程序傳遞參數(shù)。位置參數(shù)代表文件本身,運(yùn)行方法參數(shù),參數(shù)。。是正常退出,其他為異常第次第五次退出模塊判斷現(xiàn)在正在實(shí)用的平臺(tái),返回返回得到當(dāng)前工作的目錄。指定所有目錄下所有的文件和目錄名。例檢驗(yàn)指定的對(duì)象是否存在。 sys模塊 sys.argv: 實(shí)現(xiàn)從程序外部向程序傳遞參數(shù)。 位置參數(shù)argv[0]代表py文件本身,運(yùn)行方法 python xx.py 參數(shù)1,參數(shù)2 ...
摘要:換句話說,環(huán)境或應(yīng)用程序沒有處于請(qǐng)求操作的適當(dāng)狀態(tài)。項(xiàng)目中異常分析引發(fā)崩潰日志的流程分析解決辦法常見的出現(xiàn)場(chǎng)景狀態(tài)異常非法線程操作。導(dǎo)致的方法出來顯示消息位于該消息之后,遲遲沒有執(zhí)行。這時(shí)候,的超時(shí)檢測(cè)結(jié)束,刪除了服務(wù)中的記錄。 目錄介紹 1.1 java.lang.UnsatisfiedLinkError找不到so庫(kù)異常 1.2 java.lang.IllegalStateExce...
摘要:出現(xiàn)錯(cuò)誤引發(fā)崩潰日志的流程分析這個(gè)錯(cuò)誤是應(yīng)用的方法總數(shù)限制造成的。 目錄介紹 1.1 java.lang.ClassNotFoundException類找不到異常 1.2 java.util.concurrent.TimeoutException連接超時(shí)崩潰 1.3 java.lang.NumberFormatException格式轉(zhuǎn)化錯(cuò)誤 1.4 java.lang.Illegal...
閱讀 2091·2023-04-25 22:50
閱讀 2887·2021-09-29 09:35
閱讀 3465·2021-07-29 10:20
閱讀 3244·2019-08-29 13:57
閱讀 3419·2019-08-29 13:50
閱讀 3102·2019-08-26 12:10
閱讀 3628·2019-08-23 18:41
閱讀 2695·2019-08-23 18:01