欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解決python subprocess參數(shù)shell=True踩到的坑

 更新時間:2021年04月23日 09:35:55   作者:le31ei  
這篇文章主要介紹了解決python subprocess參數(shù)shell=True踩到的坑,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

0x01 問題現(xiàn)象

寫的程序使用subprocess創(chuàng)建子進(jìn)程運行其他程序,判斷其他程序運行完后進(jìn)行處理。

在subprocess使用了shell=True,判斷用戶程序退出的代碼如下

while self.proc.poll() is None:
    do_something

判斷子進(jìn)程是否運行結(jié)束,程序在子進(jìn)程運行結(jié)束后,代碼未向下繼續(xù)運行,而是卡在了這個循環(huán)中。

0x02 原因分析

百度后對shell參數(shù)的解釋如下:

shell=True參數(shù)會讓subprocess.Popen接受字符串類型的變量作為命令,并調(diào)用shell去執(zhí)行這個字符串,當(dāng)shell=False是,subprocess.Popen只接受數(shù)組變量作為命令,并將數(shù)組的第一個元素作為命令,剩下的全部作為該命令的參數(shù)。

通過查看服務(wù)器進(jìn)程可以看到,仍然有進(jìn)程存在,進(jìn)程如下

這里寫圖片描述

為shell中運行的程序,由此可以得出,shell=true時,子進(jìn)程在運行完后,shell并沒有退出,而是卡在shell命令中,可由進(jìn)程看到。

這里寫圖片描述

補(bǔ)充:Python踩坑之旅其一殺不死的Shell子進(jìn)程

1.1 踩坑案例

踩坑的程序是個常駐的Agent類管理進(jìn)程, 包括但不限于如下類型的任務(wù)在執(zhí)行:

a. 多線程的網(wǎng)絡(luò)通信包處理

和控制Master節(jié)點交互

有固定Listen端口

b. 定期作業(yè)任務(wù), 通過subprocess.Pipe執(zhí)行shell命令

c. etc

發(fā)現(xiàn)坑的過程很有意思:

a.重啟Agent發(fā)現(xiàn)Port被占用了

=> 立刻想到可能進(jìn)程沒被殺死, 是不是停止腳本出問題

=> 排除發(fā)現(xiàn)不是, Agent進(jìn)程確實死亡了

=> 通過 netstat -tanop|grep port_number 發(fā)現(xiàn)端口確實有人占用

=> 調(diào)試環(huán)境, 直接殺掉占用進(jìn)程了之, 錯失首次發(fā)現(xiàn)問題的機(jī)會

b.問題在一段時間后重現(xiàn), 重啟后Port還是被占用

定位問題出現(xiàn)在一個叫做xxxxxx.sh的腳本, 該腳本占用了Agent使用的端口

=> 奇了怪了, 一個xxx.sh腳本使用這個奇葩Port干啥(大于60000的Port, 有興趣的磚友可以想下為什么Agent默認(rèn)使用6W+的端口)

=> review該腳本并沒有進(jìn)行端口監(jiān)聽的代碼

一拍腦袋, c.進(jìn)程共享了父進(jìn)程資源了

=> 溯源該腳本,發(fā)現(xiàn)確實是Agent啟動的任務(wù)中的腳本之一

=> 問題基本定位, 該腳本屬于Agent調(diào)用的腳本

=> 該Agent繼承了Agent原來的資源FD, 也就是這個port

=> 雖然該腳本由于超時被動觸發(fā)了terminate機(jī)制, 但terminate并沒有干掉這個子進(jìn)程

=> 該腳本進(jìn)程的父進(jìn)程(ppid) 被重置為了1

d.問題****出在腳本進(jìn)程超時kill邏輯

1.2 填坑解法

通過代碼review, 找到shell具體執(zhí)行的庫代碼如下:

self._subpro = subprocess.Popen(
    cmd, shell=True, stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    preexec_fn=_signal_handle
)
# 重點是shell=True !

把上述代碼改為:

self._subpro = subprocess.Popen(
    cmd.split(), stdout=subprocess.PIPE,
    stderr=subprocess.PIPE, preexec_fn=_signal_handle
)
# 重點是去掉了shell=True

1.3 坑位分析

Agent會在一個新創(chuàng)建的threading線程中執(zhí)行這段代碼, 如果線程執(zhí)行時間超時(xx seconds), 會調(diào)用 self._subpro.terminate()終止該腳本.

表面正常:

啟用新線程執(zhí)行該腳本

如果出現(xiàn)問題,執(zhí)行超時防止hang住其他任務(wù)執(zhí)行調(diào)用terminate殺死進(jìn)程

深層問題:

Python 2.7.x中subprocess.Pipe 如果shell=True, 會默認(rèn)把相關(guān)的pid設(shè)置為shell(sh/bash/etc)本身(執(zhí)行命令的shell父進(jìn)程), 并非執(zhí)行cmd任務(wù)的那個進(jìn)程

子進(jìn)程由于會復(fù)制父進(jìn)程的opened FD表, 導(dǎo)致即使被殺死, 依然保留了擁有這個Listened Port FD

這樣雖然殺死了shell進(jìn)程(未必死亡, 可能進(jìn)入defunct狀態(tài)), 但實際的執(zhí)行進(jìn)程確活著. 于是1.1中的坑就被結(jié)實的踩上了.

1.4 坑后擴(kuò)展

1.4.1 擴(kuò)展知識

本節(jié)擴(kuò)展知識包括二個部分:

Linux系統(tǒng)中, 子進(jìn)程一般會繼承父進(jìn)程的哪些信息

Agent這種常駐進(jìn)程選擇>60000端口的意義

擴(kuò)展知識留到下篇末尾講述, 感興趣的可以自行搜索

1.4.1 技術(shù)關(guān)鍵字

Linux系統(tǒng)進(jìn)程

Linux隨機(jī)端口選擇

程序多線程執(zhí)行

Shell執(zhí)行

1.5 填坑總結(jié)

1.子進(jìn)程會繼承父進(jìn)程的資源信息

2.如果只kill某進(jìn)程的父進(jìn)程, 集成了父進(jìn)程資源的子進(jìn)程會繼續(xù)占用父進(jìn)程的資源不釋放, 包括但不限于

listened port

opened fd

etc

3.Python Popen使用上, shell的bool狀態(tài)決定了進(jìn)程kill的邏輯, 需要根據(jù)場景選擇使用方式

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • python 調(diào)用pyautogui 實時獲取鼠標(biāo)的位置、移動鼠標(biāo)的方法

    python 調(diào)用pyautogui 實時獲取鼠標(biāo)的位置、移動鼠標(biāo)的方法

    今天小編就為大家分享一篇python 調(diào)用pyautogui 實時獲取鼠標(biāo)的位置、移動鼠標(biāo)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • 詳解Python中openpyxl模塊基本用法

    詳解Python中openpyxl模塊基本用法

    這篇文章主要介紹了Python中openpyxl模塊基本用法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • Python類中使用cursor.execute()時語法錯誤的解決方法

    Python類中使用cursor.execute()時語法錯誤的解決方法

    在 Python 類中使用 cursor.execute() 時,出現(xiàn)語法錯誤(如 SyntaxError 或 SQL 語法相關(guān)錯誤)通常是因為 SQL 語句格式不正確、占位符使用不當(dāng),或參數(shù)傳遞方式不符合預(yù)期,以下是解決此類問題的常見方法和建議,需要的朋友可以參考下
    2024-09-09
  • python獲取元素在數(shù)組中索引號的方法

    python獲取元素在數(shù)組中索引號的方法

    這篇文章主要介紹了python獲取元素在數(shù)組中索引號的方法,實例分析了Python中index方法的相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • 時間序列預(yù)測中的數(shù)據(jù)滑窗操作實例(python實現(xiàn))

    時間序列預(yù)測中的數(shù)據(jù)滑窗操作實例(python實現(xiàn))

    滑動窗口操作非常普遍,非常有用,它們也很容易在Python中實現(xiàn),下面這篇文章主要給大家介紹了關(guān)于時間序列預(yù)測中的數(shù)據(jù)滑窗操作python實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • Python辦公自動化之文件的比較合并與xml操作

    Python辦公自動化之文件的比較合并與xml操作

    這篇文章主要為大家詳細(xì)介紹了Python辦公自動化之文件的比較合并與xml文件操作的相關(guān)知識,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-12-12
  • 基于python實現(xiàn)監(jiān)聽Rabbitmq系統(tǒng)日志代碼示例

    基于python實現(xiàn)監(jiān)聽Rabbitmq系統(tǒng)日志代碼示例

    這篇文章主要介紹了基于python實現(xiàn)監(jiān)聽Rabbitmq系統(tǒng)日志代碼示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • 如何使用Python創(chuàng)建json文件

    如何使用Python創(chuàng)建json文件

    眾所周知JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,這篇文章主要給大家介紹了關(guān)于如何使用Python創(chuàng)建json文件的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • 如何通過python畫loss曲線的方法

    如何通過python畫loss曲線的方法

    這篇文章主要介紹了如何通過python畫loss曲線的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • python實現(xiàn)360皮膚按鈕控件示例

    python實現(xiàn)360皮膚按鈕控件示例

    這篇文章主要介紹了python實現(xiàn)360皮膚按鈕控件示例,需要的朋友可以參考下
    2014-02-02

最新評論