2025年4月28日 星期一

nohup and /dev/null for python

 介紹在 Ubuntu 環境下使用 nohup 命令將 Python 程式放到背景執行的用法。這在需要長時間運行,且不希望因為終端機關閉而中斷程式的情況下非常實用。

nohup 命令的基本概念

nohup 是 "no hang up" 的縮寫,它的主要作用是讓程式在使用者登出終端機後,仍然能夠繼續執行。當你使用 nohup 啟動一個程式時,它會忽略 SIGHUP (hangup) 訊號。這個訊號通常在終端機連線中斷時發送給所有與該終端機相關的程序。

使用 nohup 執行 Python 程式於背景

以下是基本的用法和步驟:

  1. 確保你的 Python 程式可以正常執行: 首先,請確認你的 Python 程式 (your_script.py) 在前台可以正確地執行。你可以使用以下命令測試:

    Bash
    python your_script.py
    
  2. 使用 nohup 執行 Python 程式並放到背景: 要使用 nohup 將你的 Python 程式放到背景執行,你可以使用以下命令:

    Bash
    nohup python your_script.py &
    
    • nohup: 這個命令會讓後面的程式忽略 SIGHUP 訊號。
    • python your_script.py: 這是你要執行的 Python 命令。
    • &: 這個符號放在命令的最後面,表示將該命令放到背景執行。執行後,終端機會立即返回提示符號,你可以繼續輸入其他命令。
  3. 查看輸出: nohup 會將程式的標準輸出 (stdout) 和標準錯誤輸出 (stderr) 預設重新導向到目前目錄下一個名為 nohup.out 的檔案中。你可以使用 catlesstail 等命令來查看這個檔案的內容,以了解程式的執行情況。

    Bash
    cat nohup.out
    less nohup.out
    tail -f nohup.out  # 實時追蹤輸出
    
  4. 指定輸出檔案: 如果你想要將輸出導向到特定的檔案,可以使用重新導向符號 >>>

    • 覆蓋寫入:
      Bash
      nohup python your_script.py > my_output.log &
      
    • 追加寫入:
      Bash
      nohup python your_script.py >> my_output.log &
      
    • 同時導向標準輸出和標準錯誤輸出到同一個檔案:
      Bash
      nohup python your_script.py > output.log 2>&1 &
      
      或者更簡潔的寫法:
      Bash
      nohup python your_script.py &> output.log &
      
  5. 查看背景執行的程序: 你可以使用 jobsps 命令來查看目前在背景執行的程序。

    • jobs: 這個命令會列出目前終端機會話中放到背景執行的任務。但如果你關閉了終端機,jobs 就無法顯示這些程序了。

    • ps: 這個命令可以列出目前系統中正在執行的程序。你可以搭配 grep 來過濾出你的 Python 程序。

      Bash
      ps aux | grep "python your_script.py"
      

      這個命令會顯示包含 "python your_script.py" 的所有程序資訊。

  6. 終止背景執行的程序: 要終止一個在背景執行的程序,你需要先找到它的程序 ID (PID)。你可以使用 ps aux | grep "python your_script.py" 命令找到 PID,通常是輸出的第二欄的數字。然後使用 kill 命令加上 PID 來終止程序。

    Bash
    kill <PID>
    

    如果程序沒有正常終止,你可以嘗試使用 kill -9 強制終止它。

    Bash
    kill -9 <PID>
    

總結用法範例:

假設你的 Python 程式是 my_long_task.py,你想要在背景執行它,並將輸出寫入到 task.log 檔案中,你可以使用以下命令:

Bash
nohup python my_long_task.py > task.log 2>&1 &

執行後,你可以關閉你的終端機,這個 Python 程式仍然會在伺服器上繼續執行,並且所有的輸出都會被記錄在 task.log 檔案中。

[use  /dev/null ]

如果你不希望 nohup 產生預設的 nohup.out 檔案,或者你指定了其他的輸出檔案,但現在想避免這些檔案的寫入以減少對硬碟讀寫壽命的影響,你可以將標準輸出 (stdout) 和標準錯誤輸出 (stderr) 重新導向到一個特殊的「空設備」檔案,即 /dev/null

/dev/null 是一個特殊的檔案,所有寫入到這個檔案的資料都會被丟棄,而從這個檔案讀取資料則會立即得到檔案結束 (EOF)。將輸出導向到 /dev/null 實際上就是將輸出「丟掉」,不會有任何資料被寫入到硬碟。

以下是如何修改你的 nohup 命令來避免寫入 log 檔案:

1. 丟棄標準輸出 (stdout):

如果你只想丟棄程式的標準輸出,可以使用 > 將其導向到 /dev/null

Bash
nohup python your_script.py > /dev/null &

2. 丟棄標準錯誤輸出 (stderr):

如果你只想丟棄程式的標準錯誤輸出,可以使用 2> 將其導向到 /dev/null

Bash
nohup python your_script.py 2> /dev/null &

3. 同時丟棄標準輸出和標準錯誤輸出:

如果你想同時丟棄標準輸出和標準錯誤輸出,可以將它們都導向到 /dev/null。有幾種寫法:

  • 分別導向:

    Bash
    nohup python your_script.py > /dev/null 2> /dev/null &
    
  • 先導向 stdout 到 /dev/null,然後將 stderr 導向到與 stdout 相同的位置(即 /dev/null):

    Bash
    nohup python your_script.py > /dev/null 2>&1 &
    
  • 使用 &> (bash 4 及更新版本):

    Bash
    nohup python your_script.py &> /dev/null &
    

    這個語法會將標準輸出和標準錯誤輸出都導向到 /dev/null

選擇哪種方式取決於你的需求:

  • 如果你完全不關心程式的任何輸出(包括正常的資訊和錯誤訊息),那麼同時導向標準輸出和標準錯誤輸出到 /dev/null 是最直接的方法。
  • 如果你希望偶爾能夠檢查程式是否出錯(即使沒有詳細的 log),你可能需要考慮其他記錄錯誤的方式,或者在開發和測試階段開啟 log 記錄,在正式長時間運行時再禁用。

注意事項:

  • 將輸出導向到 /dev/null 後,你將無法看到程式運行的任何資訊或錯誤訊息。這可能會在程式出現問題時增加除錯的難度。
  • 如果你的 Python 程式本身有其他的檔案寫入操作,這些操作仍然會發生,並且不受你使用 /dev/null 重新導向 nohup 輸出的影響。

總之,使用 /dev/null 是一個有效避免 nohup 產生 log 檔案的方法,但你需要權衡這樣做可能帶來的除錯不便。在決定是否使用這種方法時,請仔細考慮你的應用場景和對程式輸出的需求。




沒有留言:

張貼留言