您的位置:首頁 > 軟件教程 > 教程 > python執(zhí)行shell并獲取結(jié)果

python執(zhí)行shell并獲取結(jié)果

來源:好特整理 | 時(shí)間:2024-07-10 16:15:15 | 閱讀:184 |  標(biāo)簽: T Hell Shell El S Python   | 分享到:

本文詳細(xì)介紹了python執(zhí)行shell并獲取結(jié)果的方法,介紹了如何使用Shell編程,給出了詳細(xì)的代碼示例。

在Python中執(zhí)行Shell命令并獲取其結(jié)果,通?梢允褂 subprocess 模塊。這個(gè)模塊允許我們啟動(dòng)新的進(jìn)程,連接到它們的輸入/輸出/錯(cuò)誤管道,并獲取它們的返回碼。下面是一個(gè)詳細(xì)的示例,展示了如何使用 subprocess.run() 函數(shù)來執(zhí)行Shell命令并獲取其輸出。

1. 示例一:使用 subprocess.run() 執(zhí)行 ls 命令并獲取結(jié)果

這個(gè)示例將執(zhí)行 ls 命令(在Unix/Linux/macOS系統(tǒng)上列出當(dāng)前目錄下的文件和文件夾),并捕獲命令的輸出和返回碼。

import subprocess  
  
# 定義要執(zhí)行的命令  
command = ['ls', '-l']  # 使用列表形式,更安全,可以避免shell注入攻擊  
  
# 執(zhí)行命令  
# capture_output=True 參數(shù)表示捕獲命令的輸出(stdout和stderr)  
# text=True 參數(shù)表示將輸出作為文本處理(Python 3.7+),之前版本使用universal_newlines=True  
result = subprocess.run(command, capture_output=True, text=True)  
  
# 獲取命令的標(biāo)準(zhǔn)輸出  
stdout = result.stdout  
  
# 獲取命令的錯(cuò)誤輸出(如果有的話)  
stderr = result.stderr  
  
# 獲取命令的返回碼  
returncode = result.returncode  
  
# 打印結(jié)果  
print(f"標(biāo)準(zhǔn)輸出:\n{stdout}")  
if stderr:  
    print(f"錯(cuò)誤輸出:\n{stderr}")  
print(f"返回碼: {returncode}")  
  
# 注意:如果命令成功執(zhí)行,returncode通常為0;非0值表示有錯(cuò)誤發(fā)生

注意事項(xiàng)

(1) 安全性 :本例中使用命令列表而非字符串來避免shell注入攻擊。當(dāng)命令和參數(shù)以列表形式提供時(shí),Python會(huì)直接將它們傳遞給系統(tǒng),不會(huì)通過shell解釋,從而減少了安全風(fēng)險(xiǎn)。

(2) 文本與字節(jié) capture_output=True text=True (或 universal_newlines=True ,在舊版本中)的組合使得輸出以文本(字符串)形式返回,而不是字節(jié)。這對(duì)于處理文本數(shù)據(jù)很方便,但如果我們需要處理二進(jìn)制數(shù)據(jù)(如圖像或視頻文件),則可能需要以字節(jié)形式捕獲輸出。

(3) 錯(cuò)誤處理 :通過檢查 returncode 可以判斷命令是否成功執(zhí)行。如果 returncode 不為0,則可能需要根據(jù) stderr 中的信息來診斷問題。

(4) 跨平臺(tái)兼容性 :本示例中的 ls -l 命令是Unix/Linux/macOS系統(tǒng)特有的。在Windows系統(tǒng)上,我們可能需要執(zhí)行不同的命令(如 dir ),并可能需要調(diào)整命令的調(diào)用方式(例如,使用 shell=True ,但請(qǐng)注意這會(huì)增加安全風(fēng)險(xiǎn))。

(5) 性能考慮 :頻繁地啟動(dòng)外部進(jìn)程可能會(huì)降低程序的性能。如果可能,盡量在Python內(nèi)部解決問題,或者考慮使用多線程/多進(jìn)程來并行處理外部命令的調(diào)用。

2. 示例二:使用 subprocess.run() 函數(shù)來執(zhí)行Shell命令

以下是一個(gè)更詳細(xì)的代碼示例,它展示了如何在Python中使用 subprocess.run() 函數(shù)來執(zhí)行Shell命令(在這個(gè)例子中是 ls -l ),并處理可能出現(xiàn)的各種情況,包括成功執(zhí)行、命令不存在、以及捕獲標(biāo)準(zhǔn)輸出和錯(cuò)誤輸出。

請(qǐng)注意,這個(gè)示例假設(shè)我們?cè)谝粋(gè)Unix/Linux/macOS系統(tǒng)上運(yùn)行,因?yàn)? ls -l 是這些系統(tǒng)的命令。如果我們?cè)赪indows上,我們可能需要替換為 dir 命令,并可能需要調(diào)整 shell 參數(shù)的使用(盡管通常建議避免使用 shell=True 以避免安全風(fēng)險(xiǎn))。

import subprocess  
  
def run_command(command):  
    """  
    執(zhí)行給定的命令并返回其輸出和返回碼。  
  
    參數(shù):  
    - command: 要執(zhí)行的命令,作為列表傳遞(例如 ['ls', '-l']),以避免shell注入。  
  
    返回:  
    - output: 命令的標(biāo)準(zhǔn)輸出(如果有的話)。  
    - error: 命令的錯(cuò)誤輸出(如果有的話)。  
    - returncode: 命令的返回碼。  
    """  
    try:  
        # 使用subprocess.run()執(zhí)行命令  
        # capture_output=True表示捕獲stdout和stderr  
        # text=True表示將輸出作為文本處理(Python 3.7+)  
        result = subprocess.run(command, capture_output=True, text=True, check=True)  
        # 如果命令成功執(zhí)行(沒有異常),則返回其輸出和返回碼  
        return result.stdout, None, result.returncode  
    except subprocess.CalledProcessError as e:  
        # 如果命令執(zhí)行失。ǚ祷卮a非0),則捕獲CalledProcessError異常  
        # 并返回錯(cuò)誤輸出、標(biāo)準(zhǔn)輸出(如果有的話)和返回碼  
        return None, e.stderr, e.returncode  
    except Exception as e:  
        # 捕獲其他可能的異常(雖然在這個(gè)簡單的例子中可能不太常見)  
        return None, f"An unexpected error occurred: {e}", None  
  
# 定義要執(zhí)行的命令  
command = ['ls', '-l']  
  
# 執(zhí)行命令并獲取結(jié)果  
output, error, returncode = run_command(command)  
  
# 根據(jù)返回的結(jié)果打印相應(yīng)的信息  
if output:  
    print("標(biāo)準(zhǔn)輸出:")  
    print(output)  
if error:  
    print("錯(cuò)誤輸出:")  
    print(error)  
if returncode is not None:  
    print(f"返回碼: {returncode}")  
    if returncode == 0:  
        print("命令成功執(zhí)行。")  
    else:  
        print("命令執(zhí)行失敗。")

在這個(gè)示例中, run_command 函數(shù)封裝了 subprocess.run() 的調(diào)用,并處理了幾種可能的情況:

(1)命令成功執(zhí)行(返回碼為0):返回標(biāo)準(zhǔn)輸出、 None 作為錯(cuò)誤輸出,以及返回碼。

(2)命令執(zhí)行失。ǚ祷卮a非0):捕獲 subprocess.CalledProcessError 異常,并返回 None 作為標(biāo)準(zhǔn)輸出、錯(cuò)誤輸出,以及返回碼。

(3)其他異常情況:捕獲并返回一條錯(cuò)誤消息和 None 作為返回碼(雖然在這個(gè)特定的例子中,由于 subprocess.run() 通常只拋出 CalledProcessError ,所以這部分可能不會(huì)被執(zhí)行)。

請(qǐng)注意, subprocess.run() check=True 參數(shù)會(huì)在命令返回非零退出碼時(shí)自動(dòng)拋出 CalledProcessError 異常,這使得我們可以在 try-except 塊中捕獲它。然而,在這個(gè)示例中,我選擇了顯式地捕獲異常,以便能夠更靈活地處理輸出和返回碼。如果我們只想在命令失敗時(shí)拋出異常,并且不關(guān)心錯(cuò)誤處理的具體細(xì)節(jié),那么可以在調(diào)用 subprocess.run() 時(shí)設(shè)置 check=True ,并讓Python的默認(rèn)異常處理機(jī)制來處理它。

3. shell編程及shell命令

3.1 Shell編程

Shell編程是指使用Shell(也稱為命令行解釋器或命令行界面)作為編程語言來編寫腳本的過程。Shell是Unix/Linux/macOS等類Unix操作系統(tǒng)中的一個(gè)特殊程序,它為用戶提供了一個(gè)與操作系統(tǒng)交互的環(huán)境。Shell腳本是一系列Shell命令的集合,這些命令被編寫在文本文件中,并通過Shell解釋器執(zhí)行,以實(shí)現(xiàn)自動(dòng)化任務(wù)、批處理文件、管理系統(tǒng)資源等目的。

Shell腳本具有跨平臺(tái)性,因?yàn)樗鼈冎饕蕾囉赟hell的功能和命令,而這些在大多數(shù)類Unix系統(tǒng)中都是相似的。然而,不同的Shell(如Bash、Zsh、Fish等)可能有自己的特性和擴(kuò)展,因此編寫的腳本可能需要針對(duì)特定的Shell進(jìn)行適配。

Shell編程通常包括變量定義、條件判斷、循環(huán)控制、函數(shù)調(diào)用等編程元素,但與傳統(tǒng)編程語言相比,Shell腳本的語法相對(duì)簡單且靈活。

3.2 Shell命令

Shell命令是用戶在Shell環(huán)境中輸入的指令,用于執(zhí)行各種操作,如文件管理、程序執(zhí)行、系統(tǒng)管理等。Shell命令可以是Shell內(nèi)置的,也可以是系統(tǒng)上的外部程序。

(1) 內(nèi)置命令 :由Shell本身提供的命令,這些命令在Shell啟動(dòng)時(shí)就已經(jīng)加載到內(nèi)存中,因此執(zhí)行速度較快。內(nèi)置命令不依賴于系統(tǒng)上的其他程序,因此它們?cè)谙到y(tǒng)啟動(dòng)時(shí)就已經(jīng)可用。常見的內(nèi)置命令包括 cd (改變目錄)、 echo (顯示信息)、 exit (退出Shell)等。

(2) 外部命令 :也稱為文件系統(tǒng)命令,這些命令是系統(tǒng)上獨(dú)立的程序,通常位于 /bin 、 /usr/bin 、 /sbin /usr/sbin 等目錄下。當(dāng)Shell需要執(zhí)行這些命令時(shí),它會(huì)查找這些目錄來找到對(duì)應(yīng)的程序并執(zhí)行。常見的外部命令包括 ls (列出目錄內(nèi)容)、 cp (復(fù)制文件或目錄)、 mv (移動(dòng)或重命名文件或目錄)等。

Shell命令可以通過管道( | )、重定向( > < 、 >> )、命令替換( command $(command) )等機(jī)制進(jìn)行組合,以實(shí)現(xiàn)更復(fù)雜的操作。例如, ls -l | grep '^d' 命令會(huì)列出當(dāng)前目錄下所有目錄的詳細(xì)信息( ls -l 列出詳細(xì)信息, grep '^d' 篩選出以 d 開頭的行,即目錄)。

Shell編程和Shell命令是Unix/Linux/macOS等系統(tǒng)用戶日常工作中不可或缺的工具,它們能夠極大地提高用戶的工作效率,并幫助用戶自動(dòng)化地完成各種任務(wù)。

3.3 如何使用Shell編程

使用Shell編程主要涉及到編寫Shell腳本,這些腳本包含了一系列的Shell命令,通過Shell解釋器執(zhí)行以實(shí)現(xiàn)特定的功能。以下是使用Shell編程的基本步驟:

3.3.1 選擇Shell

首先,我們需要確定使用哪種Shell。常見的Shell有Bash(Bourne Again SHell,大多數(shù)Linux發(fā)行版的默認(rèn)Shell)、Zsh(Z Shell,具有許多增強(qiáng)特性和更好的用戶體驗(yàn))、Fish(Friendly Interactive SHell,以用戶友好和易于學(xué)習(xí)而著稱)等。對(duì)于初學(xué)者來說,Bash是一個(gè)很好的起點(diǎn),因?yàn)樗鼜V泛可用且文檔豐富。

3.3.2 編寫Shell腳本

Shell腳本通常保存在以 .sh 為擴(kuò)展名的文件中。我們可以使用任何文本編輯器來編寫Shell腳本,比如 nano 、 vim 、 emacs 或簡單的 echo 和重定向。

以下是一個(gè)簡單的Shell腳本示例,它打印出“Hello, World!”:

#!/bin/bash  
# 這是一個(gè)簡單的Shell腳本示例  
echo "Hello, World!"

在腳本的第一行, #!/bin/bash 被稱為shebang,它告訴系統(tǒng)這個(gè)腳本應(yīng)該使用哪個(gè)解釋器來執(zhí)行。在這個(gè)例子中,它指定了Bash。

3.3.3 保存腳本

將我們的腳本保存到文件中,例如 hello.sh 。

3.3.4 賦予執(zhí)行權(quán)限

在Linux或macOS上,我們需要給腳本文件賦予執(zhí)行權(quán)限,以便能夠直接運(yùn)行它。我們可以使用 chmod 命令來做到這一點(diǎn):

bash復(fù)制代碼

chmod +x hello.sh

這個(gè)命令會(huì)給 hello.sh 文件添加執(zhí)行權(quán)限。

3.3.5 運(yùn)行腳本

現(xiàn)在,我們可以通過以下兩種方式之一來運(yùn)行我們的腳本:

直接通過腳本的路徑和名稱(如果腳本具有執(zhí)行權(quán)限):

bash復(fù)制代碼

./hello.sh

注意,我們需要使用 ./ 來指定腳本位于當(dāng)前目錄下。

使用Shell解釋器來執(zhí)行腳本(無論腳本是否具有執(zhí)行權(quán)限):

bash復(fù)制代碼

bash hello.sh

這個(gè)命令會(huì)告訴Bash解釋器來執(zhí)行 hello.sh 腳本中的命令。

小編推薦閱讀

好特網(wǎng)發(fā)布此文僅為傳遞信息,不代表好特網(wǎng)認(rèn)同期限觀點(diǎn)或證實(shí)其描述。

Shell 1.0
Shell 1.0
類型:飛行射擊  運(yùn)營狀態(tài):正式運(yùn)營  語言: 英文   

游戲攻略

游戲禮包

游戲視頻

游戲下載

游戲活動(dòng)

《Shell》是游戲商ShamBdour開發(fā)的一款趣味射擊闖關(guān)解謎游戲,游戲中,玩家將操作烏龜,你需要利用自己的

相關(guān)視頻攻略

更多

掃二維碼進(jìn)入好特網(wǎng)手機(jī)版本!

掃二維碼進(jìn)入好特網(wǎng)微信公眾號(hào)!

本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請(qǐng)發(fā)郵件[email protected]

湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2025 haote.com 好特網(wǎng)