Overview of Content
Linux 訊號是作業系統中用於通信的關鍵機制之一,本篇將帶您深入了解 Bash 腳本中的訊號處理、信號的產生、捕捉以及改變捕捉後的行為。同時,您還將學會如何在後台運行腳本以及有效管理後台進程,包括查看、暫停和恢復作業。此外,我們將探討如何調整進程的謙讓度,以及安排定期執行腳本的各種方法,包括使用 cron 和 at 命令,以及補足 cron 缺失的 anacron 命令。
啟動腳本的方式除了直接呼叫控制之外,還可以透過向腳本發送訊號來控制腳本
寫文章分享不易,如有引用參考請詳註出處,如有指導、意見歡迎留言(如果覺得寫得好也請給我一些支持),感謝 😀
個人程式分享時比較注重「縮排」,所以可能不適合手機的排版閱讀,建議切換至「電腦版」、「平板版」視窗看
認識 Linux 訊號
Linux 系統 & 應用程式可以產生很多信號,以下列出幾個我們最常見的信號
信號 | 對應值 | 說明 |
---|---|---|
1 | SIGHUP | 掛起(Hang up) |
2 | SIGINT | 中斷(interrupt) |
3 | SIGQUIT | 停止 |
9 | SIGKILL | 無條件終止 |
15 | SIGTERM | 盡可能地終止 |
17 | SIGSTOP | 無條件停止(不等於終止) |
18 | SIGCON | 繼續停止的進程 |
19 | SIGTSTP | 暫停 |
# 查看所有信號
man 7 signal
Bash 處理信號
● 信號會傳遞到腳本中讓腳本去處理,而 Bash Shell 對於信號的處理有以下特性
● 默認情況下 Bash Shell 會處理 SIGHUP
(1)、SIGINT
(2)信號,但忽略 SIGQUIT
(3)、SIGTERM
(15)信號
● 如果 Shell 收到信號,那它會 傳遞到每個 Sub Shell (Child Shell) 中
產生信號:快捷鍵 & 指令
● 使用 快捷鍵 產生訊號
A. 中斷:Ctrl + C
產生 SIGINT(2)信號;
測試如下:使用按鍵中斷 sleep
命令
sleep 100
B. 暫停:Ctrl + Z
產生 SIGTSTP(18)信號;暫停進程與停止進程不同,暫停進程代表該進程仍在記憶體中,隨時可恢復
測試如下:使用按鍵暫停 sleep
命令
sleep 100
暫停進程後,Linux 會分配一個作業好 (
job number
) 給暫停的進程
● 可以透過
ps f
命令查看STAT
欄位,來觀察進程的狀態可以看到上圖 進程 STAT 為
T
,這代表進程(執行命令的進程)被停止
● 使用 指令 產生訊號:
使用 kill
命令,並指定要產生的信號,就可以對進程發送指定信號;格式如下
kill [options] <PID>
可以透過 -l
查看 kill 可發送的訊號
● 範例:透過 kill 對指定進程(透過 PID)發送指定信號
# 對進程 99882
# 發送 SIGKILL 信號
kill -9 99882
捕捉信號 trap
● 我們知道每個腳本都預設可以接收訊號;我們也可以 透過 trap
命令主動去指定我們要捕捉某個訊號,trap
格式如下:
trap <命令> 指定訊號
捕捉到指定訊號後,執行
命令
的內容
● Trap 捕捉信號範例:
捕捉但不處理,以下捕捉 SIGINT
訊號(使用 Ctrl-C
來產生這個訊號)
#!/bin/bash
trap "echo 'Sorry! I have trapped Ctrl-C'" SIGINT
count=1
while [ $count -le 10 ] ; do
echo "Test times: $count"
sleep 1
(( count++ ))
done
捕捉腳本退出信號
● 在腳本完成並準備退出時會發出一個 EXIT
訊號
而我們也可以 透過 trap
命令捕捉腳本退出的時機(也就是腳本退出時發生的信號)… 範例如下:
#!/bin/bash
trap "echo 'The script finish'" EXIT
count=1
while [ $count -le 10 ] ; do
echo "Test times: $count"
sleep 1
(( count++ ))
done
● 這裡的
trap
捕捉的信號是退出的信號,如果想改成捕捉到某個信號才退出
,那我們可以這樣修改如下在補捉到信號時,去執行
exit
命令#!/bin/bash trap "echo 'The script get SIGSTP~'; exit" SIGSTP count=1 while [ $count -le 10 ] ; do echo "Test times: $count" sleep 1 (( count++ )) done
改變捕捉後的行為
● 如果要改變捕捉信號的行為,只需要「再寫一次 trap
命令」 並依照需求修改為需要執行的命令,這樣就會產生「後蓋前」的行為(後面的 trap
命令覆蓋前面的 trap
命令)
使用範例如下:
#!/bin/bash
trap "echo 'Sorry! I have trapped Ctrl-C'" SIGINT
count=1
while [ $count -le 5 ] ; do
echo "Test times: $count"
sleep 1
(( count++ ))
done
# 跳出循環時,再次覆蓋捕捉 SIGINT
trap "echo 'I modify trapped~~'; whoami" SIGINT
count=1
while [ $count -le 5 ] ; do
echo "~~ Second times: $count"
sleep 1
(( count++ ))
done
● 這裡要注意,要捕捉同一個信號才可以覆蓋
移除捕捉到的信號
● 將 trap
命令,轉換為「單破折號(-
)」或是「雙破折號(--
)」就可以取消捕捉;
格式如下,兩種方式都可以,擇一即可
trap - 指定信號
trap -- 指定信號
移除 trap
信號的範例:
#!/bin/bash
trap "echo 'Sorry! I have trapped Ctrl-C'" SIGINT
count=1
while [ $count -le 5 ] ; do
echo "Test times: $count"
sleep 1
(( count++ ))
done
# 移除信號
trap -- SIGINT
count=1
while [ $count -le 5 ] ; do
echo "~~ Second times: $count"
sleep 1
(( count++ ))
done
後台進程與腳本
腳本在後台(background
)模式中就不會影響前台,前台可以繼續作業
腳本後台運行:JobIndex
● 要讓腳本運行在後台很簡單,只需要在呼叫腳本時,在腳本後添加 &
符號即可;格式如下
運行腳本 &
腳本後台運行範例
#!/bin/bash
count=1
while [ $count -le 10 ] ; do
echo "Test times: $count"
sleep 1
(( count++ ))
done
● 腳本在後台運行時仍會使用
STDOUT
、STDERR
,如果你沒有重新指向的話,它就會輸出在螢幕上
● 在規定腳本後台運行後,會 返回一組號碼,那組號碼就是後台運行的 JobIndex
& PID
Job 概念後面會提及
在終端啟動的腳本後台腳本會與當前終端產生關聯,如果終端關閉了,那該終端啟動的後台進程也會關閉(下個小節會說一個脫離終端的方式)
腳本脫離終端關聯:nohup
● 前面有提到,腳本預設會與啟動它的終端有聯繫,如果終端關閉,該腳本就算沒運行完畢也會被關閉;以下範例,我們啟動一個腳本,關閉視窗(中斷)
A. 撰寫測試腳本:該腳本重新定向輸出到 relate_termial
檔案
#!/bin/bash
count=1
while [ $count -le 10 ] ; do
echo "Hello, relate with termial: $count"
sleep 1
(( count++ ))
done
B. 背景啟動以下腳本
./normal_output.sh &
C. 快速關閉啟動腳本的終端(按下叉叉),輸出自然被中斷
● Linux 有提供一個 nohup
命令,可以 1.切斷腳本 & 啟動它的終端的關聯,如果有輸出結果 2. 將結果輸出到 nohup.out
文件中
如果在同級目錄中多個
nohup
命令,那輸出結果全部都會匯集到nohup.out
文件(容易混亂)
使用的腳本跟上面相同,不過在啟動腳本時改變啟動命令
A. 啟動命令改動如下
nohup ./normal_output.sh &
B. 查看 nohup.out
檔案:可以發現輸出結果到指定檔案,關閉終端不對輸出產生影響
● 如果你在腳本中使用
exec
另起一個進程輸出結果到檔案,那終端仍與exec
啟動的進程有關聯,nohup
這時就無法中斷兩者(exec & 終端)之間的關聯
後台進程管理
管理進程可以使用 kill
命令對不同進程(指定 PID)來發送不同的信號,除了 kill
命令之外還有另一個常用的 jobs
命令
Jobs 查看後台進程
接下來使用這個腳本在背景運行,進行測試
#!/bin/bash
count=1
while [ $count -le 10 ] ; do
sleep 10
(( count++ ))
done
● jobs
命令可以查看當前 Shell 正在處理的作業,並且它有幾個常用的 options,如下表
Options | 說明 |
---|---|
-l | 列出進程的 PID & job 號 |
-n | 列出上次 Shell 發出的通知後改變的狀態 |
-p | 只列出 PID |
-r | 列出運行中的作業 |
-s | 列出已停止的作業 |
● jobs 列出的
+
、-
號
+
號代表默認作業,-
下一個會被指定的作業;在控制流程中,如果沒有指定作業號 就會用+
、-
號 依序處理
● 背景運行腳本,並使用 jobs
命令查看任務
● 測試多背景作業下:符號 +
、-
號的改變
A. 啟動多個背景腳本,並使用 jobs -l
查看,可以看到+
、-
號只會有一組
B. 使用 kill
命令對當前是 +
號的進程發出 SIGKILL
命令,會發現 +
、-
號的轉移
在背景啟動暫停的作業:bg
● bg
命令:該令令可以將暫停中的作業緩醒,並將該作業歸納到後台運行,bg
命令格式如下
bg [job 編號]
## 如果沒有指定,則依照 +- 號順序
bg
A. 啟動腳本
./job_3.sh
B. 暫停腳本使用 Ctrl + Z
快捷鍵,對腳本發出暫停信號(SIGTSTP
)
可以發現腳本被暫停 (
Stopped
)
C. 使用 bg
命令,來將暫停任務喚醒,並歸納到後台運行,再使用 jobs
查看任務是否真的在後台運行
./job_3.sh
將背景暫停作業切換到前景:fg
● fg
命令:將在暫停中的作業,切換至前景(與使用者交互的進程)繼續運行;指令格式如下
jg [job 編號]
## 如果沒有指定,則依照 +- 號順序
jg
範例如下
A. 啟動耗時 Shell
./job_3.sh
B. 使用 Ctrl + Z
對腳本發出暫停訊號
C. 透過 jobs -l
查看當前 Shell 運行的相關任務
./jobs -l
D. 使用 fg
指令將其切換至當前交互介面繼續訓行
進程謙讓度
系統會根據進程的 謙讓度 來決定 CPU 資源的分配,如果謙讓度越低則分配的的資源越高,反知則越低
● 謙讓度 相關知識
● 範圍是
-20
(資源分配高) ~19
(資源分配低),值越小資源越多● 使用者可以自由調高進程的謙讓度(數字提高),但是 只有 root 使用者可以調低謙讓度(數字降低)
調整謙讓度:nice / renice
● nice
、renice
兩個指令都可以調整腳本的謙讓度,兩者個差別在於 nice
是腳本尚未啟動時就設定,而 renice
則是腳本啟動後再做調整
● nice
命令範例
Options | 功能 |
---|---|
-n , --adjustment | 調整謙讓度(預設為 10) |
# 背景啟動耗時任務,並調整謙讓度到 10
nice -n 10 ./job_3.sh &
# 透過 ps 指令查看謙讓度... 等等訊息
ps -p 120437 -o pid,ppid,ni,cmd
● renice
命令範例
renice
只能調整屬於自身的子進程謙讓度
Options | 功能 |
---|---|
-n , --adjustment | 調整謙讓度(預設為 10) |
-p , --pid | 指定 PID |
# 背景啟動耗時任務,並調整謙讓度到 10
nice -n 10 ./job_3.sh &
# 透過 ps 指令查看謙讓度... 等等訊息
ps -p 120506 -o pid,ppid,ni,cmd
# 指定進程 ID,並調整謙讓度到 19
renice -n 19 -p 120506
# 再次檢查謙讓度... 等等訊息
ps -p 120506 -o pid,ppid,ni,cmd
● 再次提醒,要調低謙讓度(使用更多 CPU 資源)必須使用 root 用戶(或是 sudo 暫時調高權限)
定時運行腳本任務
Linux 系統可以透過特定命令來在固定(規劃好)的時間幫我們執行某些腳本
計畫執行:at 介紹
●
at
命令有些 Linux 發行版中會沒有內建
at
命令,請透過以下命令安裝sudo apt install -y at
● at
命令:它會啟動一個守護進程 atd
在背景每 60s 進行檢查文件作業,而檢查的文件就是使用者排定的作業相關資訊
● 任務訊息文件所在位置
atd
維護的文件通常位於/var/spool/cron/atjobs
目錄之下
● at
命令格式如下:
# timespec 用來指定作業時間
at [Options] timespec
Options | 說明 |
---|---|
-f | 用來指定腳本文件 |
-q | 指定隊列(A to Z, a to z),對列則會影響到執行的優先級 |
-M | 永遠不發送 Mail 給使用者 |
● 如果你指定的 timespec
已經過了, 那它會在隔天的同個時段再去執行任務;而 timespec
有多種指定格式,以下列出幾種,詳細請看文件
A. 小時 & 分鐘
timespec 設定為
17:55
B. AM / PM 指示
timespec 設定為
05:55pm
C. 特殊時間命名:now
, noon
, midnight
, teatime
timespec 設定為
teatime
D. 標準日期格式:月日年
、月/日/年
、月.日.年
timespec 設定為
10/10/23
E. 文本日期:加不加年都可以
timespec 設定為
Dec 25
F. 時間基礎運算 +
號
timespec 設定為
4pm + 3 days
timespec 設定為
10:15AM + 7 days
計畫執行:at 使用、相關命令
● at
執行任務時的輸出
at
命令的 STDOUT
、STDERR
預設會指向作業用戶的電子郵件,所以建議在使用 at
規劃時段時,最好將腳本內的指令重新導向
#!/bin/bash
echo "Hello at."
sleep 3
echo "Finish at."
可以看到 如果正常的腳本透過
at
執行,STDOUT
並不會指向螢幕
●
at
命令也可以在互動式;結束設定時使用ctrl + D
at 12:00 echo "吃飯囉~"
● atq
查看等待的任務隊列
at -f ./at_1.sh tomorrow
at -M -f ./at_1.sh 12:30
at -M -f ./at_1.sh teatime
at -M -f ./at_1.sh now
● atrm
移除排定作業
只能刪除自己提交的作業,無法刪除其他人提交的作業
atq
# 移除任務列表第二個任務
atrm 2
# 移除任務列表第三個任務
atrm 3
atq
定期執行腳本:cron 介紹
● cron
跟 at
的差異:cron
會定期執行,at
則是單次執行
● cron
命令特性如下
A. cron
時間表:時間指定格式如下
min hour dayofmonth month dayofweek command
cron 允許時間使用特定值、範圍取值(eg. 1~5
)、通配符... 等等,cron
的格式範例如下所示:
- 每天
10:15
執行某個任務(指令)
15 10 * * * command
- 每週三
10:15
執行某個任務(指令)
星期日(0)~ 星期六(6)
15 10 * * 3 command
- 每月 5 號
10:15
執行某個任務(指令)
月初(1)~ 月底(31)
15 10 5 * * command
B. 任務指定:任務必需要使用「全路徑」指定
以下指令的含意是,每天 10:15
分執行 cron_1.sh
腳本
15 10 * * * /home/alien/Desktop/shell/chapter_16/cron_1.sh
C. 查看 cron
任務文件:它會放在 /etc
目錄下,並以 cron
開頭取名
ls -laF /etc/cron.*ly
定期執行腳本:crontab 使用
只有系統管理員可以直接使用
cron
命令,一般使用者想使用,就可以透過crontab
命令操作(當然系統管理員也可以使用crontab
命令)
● 使用者 crontab
檔案:編輯設定 crontab 任務
● 每個使用者都可以有自己的
crontab
檔案,通常存在/var/spool/cron/crontabs
目錄下sudo ls -laF /var/spool/cron/crontabs
A. 使用 crontab -e
編輯任務
# 指定使用的編輯系統
export=vim
# 編輯任務
crontab -e
B. 輸入 cron 規範格式去指定任務
15 10 * * * /home/alien/Desktop/shell/chapter_16/cron_1.sh
● 如果需要刪除某個任務,也必須透過
contab -e
編輯
● 使用 crontab -l
命令:查看 cron
任務的時間表
crontab -l
● 系統 corntab 檔案:
系統的 corntab
檔案通常存在 /etc/crontab
檔案中,用它來安排系統任務的執行
從上圖可以看到每天 daily
會透過 run-parts
命令來運行 /etc/cron.daily
目錄下的所有命令(順序運行)
補足 cron 缺失:anacron 命令
●
anacron
命令有些 Linux 發行版中會沒有內建
anacron
命令,請透過以下命令安裝sudo apt install -y anacron
● 如果 cron
在定時時間啟動任務但電源沒開,那在 電源啟動後 cron
也不會去重新執行
● 這時就可以用 anacron
命令,它會盡快運行錯過時間的作業項目
A. anacorn
只會處理 cron
目錄下的程序,它有自己的文件去記錄每個指令應該運行的時機
ls -laF /var/spool/anacorn
B. anacorn
有自己的時間表,來檢查作業目錄
sudo cat /etc/anacrontab
啟動 Shell 即加載
請先複習 Shell 加載順序 這個章節,透過使用者啟動 Shell 時會加載的文件順序來把我們需要的指令(或腳本)加入
腳本插入 .bashrc
● 基本上除了最初在登入系統時一定會加載的 /etc/profile
文件之外,其他 以下文件都不一定會加載(每個發行版可能加載的文件都不同)
● .bash_profile
● .profile
● .bash_login
但基本上這些文件最終基本上都會加載(呼叫)到 .bashrc
文件,所以我們只要編輯該文件,就可以在每個 bash 中插入指令
A. 透過 vim .bashrc
vim .bashrc
B. 插入一行簡單指令,保存並退出
echo "Hello Bash"
C. 重新啟動一個新 bash 介面 就會發現指令被輸出了~
更多 Linux Shell 知識
Linux 環境、服務:用戶、權限管理
● Linux 環境、服務、管理:
在這個主題中,你可以探索各種 Linux 環境、服務和管理相關的重要概念…
● 了解 Linux 組成:內核責任、GNU 工具、桌面環境 | 基礎版到發行版
在這裡,你將了解 Linux 系統的基本組成部分,包括內核、GNU 工具和桌面環境,並了解不同 Linux 發行版之間的差異
● 探索 X Window 服務與桌面環境:Linux 視窗 XWindow 服務、D-Bus 機制
這裡探討了 Linux 系統中 X Window 服務和 D-Bus 機制的工作原理,讓你深入了解桌面環境的背後運作方式
● Linux 系統管理入門:安全性、用戶管理與權限設定指南
在這個指南中,你將學習如何管理 Linux 系統,包括安全性、用戶管理和權限設定,以確保系統的安全和有效運作
● 認識身份驗證與權限管理:UNIX UID、使用者驗證與 PAM | PAM 設定
這裡介紹了 UNIX 系統中的身份驗證機制和權限管理方式,包括 UNIX UID、使用者驗證和 PAM(
Pluggable Authentication Modules
)設定
Linux Shell 相關知識
● Linux Shell 相關知識:
這個主題涵蓋了各種與 Linux Shell 相關的知識,從基礎到進階都有…
● Shell 基礎知識:包括 Shell 的基礎使用以及差異,還有變數以及計算
● 認識命令行:Shell 類型、命令差異 | Sub Shell 關係 | Builtin 命令
這裡介紹了命令行中不同類型的 Shell,以及各種 Shell 命令之間的區別和內建命令的用法
● Shell 全局及區域變數、特殊變數及環境變數 | Shell 啟動順序 | Array 變數
學習如何在 Shell 中使用全局變數、特殊變數和環境變數,以及如何設置和管理這些變數
● 探索腳本與命令:Shell 腳本的必備相關知識 | 腳本的數學運算
這裡介紹了 Shell 腳本的基本知識和常用技巧,包括如何執行腳本和進行數學運算
● Shell 結構化
● Shell 腳本程式中的條件語句和高級特性 | Shell 結構化 & 判斷
該篇文章是介紹結構化腳本的基礎以及特殊的高級技巧,轉著於腳本中的邏輯判斷
● 掌握 Bash 腳本中的迴圈與循環控制技巧 | Shell 結構化 & 循環
接著是腳本中的循環與控制的技巧,它可以讓我們在 Shell 腳本中有更多的判斷與技巧
● 探索 Shell 函數與腳本庫 | Shell 結構化 & 函數
這裡你將會學在到結構化腳本的重要技巧「函數」,它可以讓你建立可重複利用的腳本,以節省我們之後開發的時間
● Shell 掌握參數處理與用戶輸入技巧 | Shell 結構化 &輸入互動
不可互動的腳本有時候相對無趣,這篇文章有分享如何讓腳本與使用者產生交互互動,並依照使用者輸入的參數做讀取
● Shell script 進階
● Shell 命令輸入與輸出指南:掌握標準文件描述符與重定向 | 臨時文件
掌控 Shell、指令的輸出輸入是成為進階使用 CLI 之人必經的一課,透過這篇文章可以了解到輸出輸入、臨時文件等等資訊
● 探索 Linux 訊號與後台進程管理:安排定期啟動腳本 | 運行時啟動腳本
信號可以算是 Shell 腳本與 Linux 系統之間的通訊方式,透過這個文章,我們可以了解到信號與 Shell 腳本的安排時間
Linux 硬體規劃:檔案系統、分區
● Linux 硬體規劃:檔案系統、分區:
最後,這個主題涵蓋了 Linux 系統中硬體結構相關的重要概念…
● Shell 文件和目錄操作的常用命令和技巧 | 尋找檔案
這裡介紹了 Shell 中常用的文件和目錄操作命令,包括如何尋找文件和管理文件系統
● 深入探索 Linux 文件系統與硬體管理 | 分區、檔案系統、邏輯卷 | inode
學習如何管理 Linux 文件系統,包括分區、文件系統和邏輯卷等相關概念,以及文件系統中的 inode 機制
● 理解 Unix/Linux 設備偵測、建立 | 認識與使用 udevd | SCSI 與 Linux 核心
這裡介紹了 Unix/Linux 系統中的設備偵測和管理,包括如何使用 udevd 和 SCSI 相關的 Linux 核心知識