萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux 前台/後台進程切換實戰:&、Ctrl+Z、jobs、fg、bg、disown、nohup、systemd

在終端機操作中,將長時間運行的任務放入後台、從後台喚回前台、脫離終端會話持久化運行,是提升效率的關鍵技能。本文系統講解 Shell 作業控制機制、核心指令組合、脫離終端持久化方案 (nohup, disown, systemd-run, tmux/screen)、進程組與信號傳遞原理。

前後台進程切換示意圖

一、Shell 作業控制基礎

  • 前台進程 : 佔用終端標準輸入/輸出/錯誤,接收終端信號 (Ctrl+C=SIGINT, Ctrl+Z=SIGTSTP, Ctrl+\=SIGQUIT)。
  • 後台進程 : 不佔用終端標準輸入,輸出仍導向終端 (可重導向),不接收終端鍵盤信號 (SIGINT/SIGTSTP),但會接收 SIGHUP (終端關閉時)。
  • 作業 : Shell 管理的命令管線實體,有作業號 [1], [2]...,可用 %n 引用。

二、核心指令速查

指令功能典型用法
cmd &啟動命令直接放入後台運行firefox &, python3 server.py &
Ctrl+Z暫停前台進程 (發送 SIGTSTP),返回 Shell 提示符運行中 ./long_task.sh 按 Ctrl+Z
jobs [-l]列出當前 Shell 作業 (含 PID、狀態 Running/Stopped/Done)jobs -l
fg [%n]將後台/暫停作業喚回前台繼續運行fg %1 (喚回作業 1)
bg [%n]讓暫停作業在後台繼續運行 (發送 SIGCONT)bg %1
kill %n向作業發送信號 (預設 SIGTERM),kill -9 %1 強制殺死kill %1
disown [%n] [-h]從 Shell 作業表移除,-h 標記不接收 SIGHUP (需配合 bg)disown -h %1
nohup cmd &啟動時忽略 SIGHUP,輸出重導向至 nohup.outnohup python3 server.py &

三、實戰場景演練

場景 1:啟動長時間任務直接放入後台


# 建議配合輸出重導向,避免干擾終端
nohup ./train_model.py > train.log 2>&1 &
# 或
./train_model.py > train.log 2>&1 &
# 此時 jobs 可見,但關閉終端會收到 SIGHUP 可能退出

場景 2:將正在運行的前台任務轉入後台並持久化


# 1. 正在運行 ./backup.sh
# 2. 按 Ctrl+Z 暫停
[1]+  Stopped                 ./backup.sh
# 3. bg %1 讓它在後台繼續
[1]+  Running                 ./backup.sh &
# 4. disown -h %1 讓 Shell 不再向它發送 SIGHUP (關鍵步驟)
# 5. 關閉終端,任務繼續運行

場景 3:使用 tmux/screen 實現真正的會話持久化 (最推薦)


# tmux (現代、功能強)
tmux new -s mysession     # 建立會話
# 執行任務...
# 按 Ctrl+b 然后 d 脫離
tmux attach -t mysession  # 重新連接 (即使斷開 SSH 也可)

# screen (經典、普遍預裝)
screen -S mysession
# 執行任務...
# 按 Ctrl+a 然后 d 脫離
screen -r mysession       # 重新連接

優勢: 保留完整終端狀態 (歷史、捲動、多視窗、分割)、支援斷線重連、多用戶共享會話。

場景 4:systemd-run 用戶級服務 (系統級持久化、開機自啟、日誌整合)


# 一次性運行 (用戶級)
systemd-run --user --scope -p MemoryMax=500M ./heavy_task.sh

# 建立持久化服務單元
cat > ~/.config/systemd/user/myapp.service <<'EOF'
[Unit]
Description=My App
[Service]
ExecStart=/home/user/myapp.sh
Restart=on-failure
MemoryMax=1G
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now myapp.service
journalctl --user -u myapp -f  # 查看日誌

四、進程組、會話與信號傳遞原理

  • 進程組 (PGID) : 管線中所有進程屬於同一進程組,領頭進程 PID = PGID。kill -TERM -PGID 可殺死整組。
  • 會話 : 終端登入建立會話,Shell 為會話領頭進程。前台進程組 = 終端前台進程組 (TPGID)。
  • SIGHUP 傳遞: 終端關閉 → 內核向會話領頭進程 (Shell) 發送 SIGHUP → Shell 預設向所有子進程組發送 SIGHUP → 進程預設行為為終止。
  • nohup/disown/tmux/systemd 皆是阻斷此傳遞鏈路的不同層面手段。

五、常見問題與最佳實踐

  1. 後台任務輸出干擾終端: 啟動時重導向 > log.txt 2>&1 或 &> log.txt (bash)。
  2. 後台任務嘗試讀取 stdin 導致停止 (SIGTTIN): 確保輸入重導向 或不讀取 stdin。
  3. 關閉終端後任務消失: 必須使用 nohup、disown -h、tmux 或 systemd-run。
  4. 無法 fg 別人啟動的進程: 作業控制屬於 Shell 會話,無法跨會話操作。需用 reptyr (需 ptrace 權限) 或 tmux 共享會話。
  5. 生產環境服務化: 重要長期服務**務必寫 Systemd Unit (系統級) 或 User Unit (用戶級)**,勿依賴 Shell 作業控制。

總結

Linux 進程前後台切換核心工具鏈:**& 後台啟動 → Ctrl+Z 暫停 → jobs 列表 → bg/fg 切換 → disown -h/nohup 脫離 SIGHUP**。**現代最佳實踐:開發調試用 tmux/screen,生產服務用 systemd**。理解進程組/會話/SIGHUP 傳遞機制,能從根本上掌控進程生命週期。

copyright © 萬盛學電腦網 all rights reserved