## 16.3 程序管理
本章一開始就提到所謂的“程序”的概念,包括程序的觸發、子程序與父程序的相關性等等, 此外,還有那個“程序的相依性”以及所謂的“僵尸程序”等等需要說明的呢!為什么程序管理這么重要呢?這是因為:
* 首先,本章一開始就談到的,我們在操作系統時的各項工作其實都是經過某個 PID 來達成的 (包括你的 bash 環境), 因此,能不能進行某項工作,就與該程序的權限有關了。
* 再來,如果您的 Linux 系統是個很忙碌的系統,那么當整個系統資源快要被使用光時, 您是否能夠找出最耗系統的那個程序,然后刪除該程序,讓系統恢復正常呢?
* 此外,如果由于某個程序寫的不好,導致產生一個有問題的程序在內存當中,您又該如何找出他,然后將他移除呢?
* 如果同時有五六項工作在您的系統當中運行,但其中有一項工作才是最重要的, 該如何讓那一項重要的工作被最優先執行呢?
所以啰,一個稱職的系統管理員,必須要熟悉程序的管理流程才行,否則當系統發生問題時,還真是很難解決問題呢! 下面我們會先介紹如何觀察程序與程序的狀態,然后再加以程序控制啰!
### 16.3.1 程序的觀察
既然程序這么重要,那么我們如何查閱系統上面正在運行當中的程序呢?很簡單啊! 利用靜態的 ps 或者是動態的 top,還能以 pstree 來查閱程序樹之間的關系喔!
* ps :將某個時間點的程序運行情況擷取下來
```
[root@study ~]# ps aux <==觀察系統所有的程序數據
[root@study ~]# ps -lA <==也是能夠觀察所有系統的數據
[root@study ~]# ps axjf <==連同部分程序樹狀態
選項與參數:
-A :所有的 process 均顯示出來,與 -e 具有同樣的效用;
-a :不與 terminal 有關的所有 process ;
-u :有效使用者 (effective user) 相關的 process ;
x :通常與 a 這個參數一起使用,可列出較完整信息。
輸出格式規劃:
l :較長、較詳細的將該 PID 的的信息列出;
j :工作的格式 (jobs format)
-f :做一個更為完整的輸出。
```
鳥哥個人認為 ps 這個指令的 man page 不是很好查閱,因為很多不同的 Unix 都使用這個 ps 來查閱程序狀態, 為了要符合不同版本的需求,所以這個 man page 寫的非常的龐大!因此,通常鳥哥都會建議你,直接背兩個比較不同的選項, 一個是只能查閱自己 bash 程序的“ ps -l ”一個則是可以查閱所有系統運行的程序“ ps aux ”!注意,你沒看錯,是“ ps aux ”沒有那個減號 (-) !先來看看關于自己 bash 程序狀態的觀察:
* 僅觀察自己的 bash 相關程序: ps -l
```
范例一:將目前屬于您自己這次登陸的 PID 與相關信息列示出來(只與自己的 bash 有關)
[root@study ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14830 13970 0 80 0 - 52686 poll_s pts/0 00:00:00 sudo
4 S 0 14835 14830 0 80 0 - 50511 wait pts/0 00:00:00 su
4 S 0 14836 14835 0 80 0 - 29035 wait pts/0 00:00:00 bash
0 R 0 15011 14836 0 80 0 - 30319 - pts/0 00:00:00 ps
# 還記得鳥哥說過,非必要不要使用 root 直接登陸吧?從這個 ps -l 的分析,你也可以發現,
# 鳥哥其實是使用 sudo 才轉成 root 的身份~否則連測試機,鳥哥都是使用一般帳號登陸的!
```
系統整體的程序運行是非常多的,但如果使用 ps -l 則僅列出與你的操作環境 (bash) 有關的程序而已, 亦即最上層的父程序會是你自己的 bash 而沒有延伸到 systemd (后續會交待!) 這支程序去!那么 ps -l 秀出來的數據有哪些呢? 我們就來觀察看看:
* F:代表這個程序旗標 (process flags),說明這個程序的總結權限,常見號碼有:
* 若為 4 表示此程序的權限為 root ;
* 若為 1 則表示此子程序僅進行[復制(fork)而沒有實際執行(exec)](../Text/index.html#fork_and_exec)。
* S:代表這個程序的狀態 (STAT),主要的狀態有:
* R (Running):該程序正在運行中;
* S (Sleep):該程序目前正在睡眠狀態(idle),但可以被喚醒(signal)。
* D :不可被喚醒的睡眠狀態,通常這支程序可能在等待 I/O 的情況(ex>打印)
* T :停止狀態(stop),可能是在工作控制(背景暫停)或除錯 (traced) 狀態;
* Z (Zombie):僵尸狀態,程序已經終止但卻無法被移除至內存外。
* UID/PID/PPID:代表“此程序被該 UID 所擁有/程序的 PID 號碼/此程序的父程序 PID 號碼”
* C:代表 CPU 使用率,單位為百分比;
* PRI/NI:Priority/Nice 的縮寫,代表此程序被 CPU 所執行的優先順序,數值越小代表該程序越快被 CPU 執行。詳細的 PRI 與 NI 將在[下一小節](../Text/index.html#priority)說明。
* ADDR/SZ/WCHAN:都與內存有關,ADDR 是 kernel function,指出該程序在內存的哪個部分,如果是個 running 的程序,一般就會顯示“ - ” / SZ 代表此程序用掉多少內存 / WCHAN 表示目前程序是否運行中,同樣的, 若為 - 表示正在運行中。
* TTY:登陸者的終端機位置,若為遠端登陸則使用動態終端接口 (pts/n);
* TIME:使用掉的 CPU 時間,注意,是此程序實際花費 CPU 運行的時間,而不是系統時間;
* CMD:就是 command 的縮寫,造成此程序的觸發程序之指令為何。
所以你看到的 ps -l 輸出訊息中,他說明的是:“bash 的程序屬于 UID 為 0 的使用者,狀態為睡眠 (sleep), 之所以為睡眠因為他觸發了 ps (狀態為 run) 之故。此程序的 PID 為 14836,優先執行順序為 80 , 下達 bash 所取得的終端接口為 pts/0 ,運行狀態為等待 (wait) 。”這樣已經夠清楚了吧? 您自己嘗試解析一下那么 ps 那一行代表的意義為何呢? ^_^
接下來讓我們使用 ps 來觀察一下系統內所有的程序狀態吧!
* 觀察系統所有程序: ps aux
```
范例二:列出目前所有的正在內存當中的程序:
[root@study ~]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 60636 7948 ? Ss Aug04 0:01 /usr/lib/systemd/systemd ...
root 2 0.0 0.0 0 0 ? S Aug04 0:00 [kthreadd]
.....(中間省略).....
root 14830 0.0 0.1 210744 3988 pts/0 S Aug04 0:00 sudo su -
root 14835 0.0 0.1 202044 2996 pts/0 S Aug04 0:00 su -
root 14836 0.0 0.1 116140 2960 pts/0 S Aug04 0:00 -bash
.....(中間省略).....
root 18459 0.0 0.0 123372 1380 pts/0 R+ 00:25 0:00 ps aux
```
你會發現 ps -l 與 ps aux 顯示的項目并不相同!在 ps aux 顯示的項目中,各字段的意義為:
* USER:該 process 屬于那個使用者帳號的?
* PID :該 process 的程序識別碼。
* %CPU:該 process 使用掉的 CPU 資源百分比;
* %MEM:該 process 所占用的實體內存百分比;
* VSZ :該 process 使用掉的虛擬內存量 (KBytes)
* RSS :該 process 占用的固定的內存量 (KBytes)
* TTY :該 process 是在那個終端機上面運行,若與終端機無關則顯示 ?,另外, tty1-tty6 是本機上面的登陸者程序,若為 pts/0 等等的,則表示為由網絡連接進主機的程序。
* STAT:該程序目前的狀態,狀態顯示與 ps -l 的 S 旗標相同 (R/S/T/Z)
* START:該 process 被觸發啟動的時間;
* TIME :該 process 實際使用 CPU 運行的時間。
* COMMAND:該程序的實際指令為何?
一般來說,ps aux 會依照 PID 的順序來排序顯示,我們還是以 14836 那個 PID 那行來說明!該行的意義為“ root 執行的 bash PID 為 14836,占用了 0.1% 的內存容量百分比,狀態為休眠 (S),該程序啟動的時間為 8 月 4 號,因此啟動太久了, 所以沒有列出實際的時間點。且取得的終端機環境為 pts/0 。”與 ps aux 看到的其實是同一個程序啦!這樣可以理解嗎? 讓我們繼續使用 ps 來觀察一下其他的信息吧!
```
范例三:以范例一的顯示內容,顯示出所有的程序:
[root@study ~]# ps -lA
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 15159 ep_pol ? 00:00:01 systemd
1 S 0 2 0 0 80 0 - 0 kthrea ? 00:00:00 kthreadd
1 S 0 3 2 0 80 0 - 0 smpboo ? 00:00:00 ksoftirqd/0
....(以下省略)....
# 你會發現每個字段與 ps -l 的輸出情況相同,但顯示的程序則包括系統所有的程序。
范例四:列出類似程序樹的程序顯示:
[root@study ~]# ps axjf
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 2 0 0 ? -1 S 0 0:00 [kthreadd]
2 3 0 0 ? -1 S 0 0:00 \_ [ksoftirqd/0]
.....(中間省略).....
1 1326 1326 1326 ? -1 Ss 0 0:00 /usr/sbin/sshd -D
1326 13923 13923 13923 ? -1 Ss 0 0:00 \_ sshd: dmtsai [priv]
13923 13927 13923 13923 ? -1 S 1000 0:00 \_ sshd: dmtsai@pts/0
13927 13928 13928 13928 pts/0 18703 Ss 1000 0:00 \_ -bash
13928 13970 13970 13928 pts/0 18703 S 1000 0:00 \_ bash
13970 14830 14830 13928 pts/0 18703 S 0 0:00 \_ sudo su -
14830 14835 14830 13928 pts/0 18703 S 0 0:00 \_ su -
14835 14836 14836 13928 pts/0 18703 S 0 0:00 \_ -bash
14836 18703 18703 13928 pts/0 18703 R+ 0 0:00 \_ ps axjf
.....(后面省略).....
```
看出來了吧?其實鳥哥在進行一些測試時,都是以網絡連線進虛擬機來測試的,所以啰,你會發現其實程序之間是有相關性的啦! 不過,其實還可以使用 pstree 來達成這個程序樹喔!以上面的例子來看,鳥哥是通過 sshd 提供的網絡服務取得一個程序, 該程序提供 bash 給我使用,而我通過 bash 再去執行 ps axjf !這樣可以看的懂了嗎?其他各字段的意義請 man ps (雖然真的很難 man 的出來!) 啰!
```
范例五:找出與 cron 與 rsyslog 這兩個服務有關的 PID 號碼?
[root@study ~]# ps aux | egrep '(cron|rsyslog)'
root 742 0.0 0.1 208012 4088 ? Ssl Aug04 0:00 /usr/sbin/rsyslogd -n
root 1338 0.0 0.0 126304 1704 ? Ss Aug04 0:00 /usr/sbin/crond -n
root 18740 0.0 0.0 112644 980 pts/0 S+ 00:49 0:00 grep -E --color=auto (cron|rsyslog)
# 所以號碼是 742 及 1338 這兩個啰!就是這樣找的啦!
```
除此之外,我們必須要知道的是“僵尸 (zombie) ”程序是什么? 通常,造成僵尸程序的成因是因為該程序應該已經執行完畢,或者是因故應該要終止了, 但是該程序的父程序卻無法完整的將該程序結束掉,而造成那個程序一直存在內存當中。 如果你發現在某個程序的 CMD 后面還接上 <defunct> 時,就代表該程序是僵尸程序啦,例如:
```
apache 8683 0.0 0.9 83384 9992 ? Z 14:33 0:00 /usr/sbin/httpd <defunct>
```
當系統不穩定的時候就容易造成所謂的僵尸程序,可能是因為程序寫的不好啦,或者是使用者的操作習慣不良等等所造成。 如果你發現系統中很多僵尸程序時,記得啊!要找出該程序的父程序,然后好好的做個追蹤,好好的進行主機的環境最優化啊! 看看有什么地方需要改善的,不要只是直接將他 kill 掉而已呢!不然的話,萬一他一直產生,那可就麻煩了! @_@
事實上,通常僵尸程序都已經無法控管,而直接是交給 systemd 這支程序來負責了,偏偏 systemd 是系統第一支執行的程序, 他是所有程序的父程序!我們無法殺掉該程序的 (殺掉他,系統就死掉了!),所以啰,如果產生僵尸程序, 而系統過一陣子還沒有辦法通過核心非經常性的特殊處理來將該程序刪除時,那你只好通過 reboot 的方式來將該程序抹去了!
* top:動態觀察程序的變化
相對于 ps 是擷取一個時間點的程序狀態, top 則可以持續偵測程序運行的狀態!使用方式如下:
```
[root@study ~]# top [-d 數字] | top [-bnp]
選項與參數:
-d :后面可以接秒數,就是整個程序畫面更新的秒數。默認是 5 秒;
-b :以批次的方式執行 top ,還有更多的參數可以使用喔!
通常會搭配數據流重導向來將批次的結果輸出成為文件。
-n :與 -b 搭配,意義是,需要進行幾次 top 的輸出結果。
-p :指定某些個 PID 來進行觀察監測而已。
在 top 執行過程當中可以使用的按鍵指令:
? :顯示在 top 當中可以輸入的按鍵指令;
P :以 CPU 的使用資源排序顯示;
M :以 Memory 的使用資源排序顯示;
N :以 PID 來排序喔!
T :由該 Process 使用的 CPU 時間累積 (TIME+) 排序。
k :給予某個 PID 一個訊號 (signal)
r :給予某個 PID 重新制訂一個 nice 值。
q :離開 top 軟件的按鍵。
```
其實 top 的功能非常多!可以用的按鍵也非常的多!可以參考 man top 的內部說明文檔! 鳥哥這里僅是列出一些鳥哥自己常用的選項而已。接下來讓我們實際觀察一下如何使用 top 與 top 的畫面吧!
```
范例一:每兩秒鐘更新一次 top ,觀察整體信息:
[root@study ~]# top -d 2
top - 00:53:59 up 6:07, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 179 total, 2 running, 177 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839140 free, 353712 used, 723536 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318680 avail Mem
<==如果加入 k 或 r 時,就會有相關的字樣出現在這里喔!
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
18804 root 20 0 130028 1872 1276 R 0.5 0.1 0:00.02 top
1 root 20 0 60636 7948 2656 S 0.0 0.3 0:01.70 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0
```
top 也是個挺不錯的程序觀察工具!但不同于 ps 是靜態的結果輸出, top 這個程序可以持續的監測整個系統的程序工作狀態。 在默認的情況下,每次更新程序資源的時間為 5 秒,不過,可以使用 -d 來進行修改。 top 主要分為兩個畫面,上面的畫面為整個系統的資源使用狀態,基本上總共有六行,顯示的內容依序是:
* 第一行(top...):這一行顯示的信息分別為:
* 目前的時間,亦即是 00:53:59 那個項目;
* 開機到目前為止所經過的時間,亦即是 up 6:07, 那個項目;
* 已經登陸系統的使用者人數,亦即是 3 users, 項目;
* 系統在 1, 5, 15 分鐘的平均工作負載。我們在[第十五章談到的 batch](../Text/index.html#batch) 工作方式為負載小于 0.8 就是這個負載啰!代表的是 1, 5, 15 分鐘,系統平均要負責運行幾個程序(工作)的意思。 越小代表系統越閑置,若高于 1 得要注意你的系統程序是否太過繁復了!
* 第二行(Tasks...):顯示的是目前程序的總量與個別程序在什么狀態(running, sleeping, stopped, zombie)。 比較需要注意的是最后的 zombie 那個數值,如果不是 0 !好好看看到底是那個 process 變成僵尸了吧?
* 第三行(%Cpus...):顯示的是 CPU 的整體負載,每個項目可使用 ? 查閱。需要特別注意的是 wa 項目,那個項目代表的是 I/O wait, 通常你的系統會變慢都是 I/O 產生的問題比較大!因此這里得要注意這個項目耗用 CPU 的資源喔! 另外,如果是多核心的設備,可以按下數字鍵“1”來切換成不同 CPU 的負載率。
* 第四行與第五行:表示目前的實體內存與虛擬內存 (Mem/Swap) 的使用情況。 再次重申,要注意的是 swap 的使用量要盡量的少!如果 swap 被用的很大量,表示系統的實體內存實在不足!
* 第六行:這個是當在 top 程序當中輸入指令時,顯示狀態的地方。
至于 top 下半部分的畫面,則是每個 process 使用的資源情況。比較需要注意的是:
* PID :每個 process 的 ID 啦!
* USER:該 process 所屬的使用者;
* PR :Priority 的簡寫,程序的優先執行順序,越小越早被執行;
* NI :Nice 的簡寫,與 Priority 有關,也是越小越早被執行;
* %CPU:CPU 的使用率;
* %MEM:內存的使用率;
* TIME+:CPU 使用時間的累加;
top 默認使用 CPU 使用率 (%CPU) 作為排序的重點,如果你想要使用內存使用率排序,則可以按下“M”, 若要回復則按下“P”即可。如果想要離開 top 則按下“ q ”吧!如果你想要將 top 的結果輸出成為文件時, 可以這樣做:
```
范例二:將 top 的信息進行 2 次,然后將結果輸出到 /tmp/top.txt
[root@study ~]# top -b -n 2 > /tmp/top.txt
# 這樣一來,嘿嘿!就可以將 top 的信息存到 /tmp/top.txt 文件中了。
```
這玩意兒很有趣!可以幫助你將某個時段 top 觀察到的結果存成文件,可以用在你想要在系統背景下面執行。 由于是背景下面執行,與終端機的屏幕大小無關,因此可以得到全部的程序畫面!那如果你想要觀察的程序 CPU 與內存使用率都很低,結果老是無法在第一行顯示時,該怎辦?我們可以僅觀察單一程序喔!如下所示:
```
范例三:我們自己的 bash PID 可由 $$ 變量取得,請使用 top 持續觀察該 PID
[root@study ~]# echo $$
14836 <==就是這個數字!他是我們 bash 的 PID
[root@study ~]# top -d 2 -p 14836
top - 01:00:53 up 6:14, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.1 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839264 free, 353424 used, 723700 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318848 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14836 root 20 0 116272 3136 1848 S 0.0 0.1 0:00.07 bash
```
看到沒!就只會有一支程序給你看!很容易觀察吧!好,那么如果我想要在 top 下面進行一些動作呢? 比方說,修改 NI 這個數值呢?可以這樣做:
```
范例四:承上題,上面的 NI 值是 0 ,想要改成 10 的話?
# 在范例三的 top 畫面當中直接按下 r 之后,會出現如下的圖樣!
top - 01:02:01 up 6:15, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.0 sy, 0.0 ni, 99.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1839140 free, 353576 used, 723672 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318724 avail Mem
PID to renice [default pid = 14836] 14836
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14836 root 20 0 116272 3136 1848 S 0.0 0.1 0:00.07 bash
```
在你完成上面的動作后,在狀態列會出現如下的信息:
```
Renice PID 14836 to value 10 <==這是 nice 值
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
```
接下來你就會看到如下的顯示畫面!
```
top - 01:04:13 up 6:17, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 2916388 total, 1838676 free, 354020 used, 723692 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 2318256 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
14836 root 30 10 116272 3136 1848 S 0.0 0.1 0:00.07 bash
```
看到不同處了吧?底線的地方就是修改了之后所產生的效果!一般來說,如果鳥哥想要找出最損耗 CPU 資源的那個程序時,大多使用的就是 top 這支程序啦!然后強制以 CPU 使用資源來排序 (在 top 當中按下 P 即可), 就可以很快的知道啦! ^_^。多多愛用這個好用的東西喔!
* pstree
```
[root@study ~]# pstree [-A|U] [-up]
選項與參數:
-A :各程序樹之間的連接以 ASCII 字符來連接;
-U :各程序樹之間的連接以萬國碼的字符來連接。在某些終端接口下可能會有錯誤;
-p :并同時列出每個 process 的 PID;
-u :并同時列出每個 process 的所屬帳號名稱。
范例一:列出目前系統上面所有的程序樹的相關性:
[root@study ~]# pstree -A
systemd-+-ModemManager---2*[{ModemManager}] # 這行是 ModenManager 與其子程序
|-NetworkManager---3*[{NetworkManager}] # 前面有數字,代表子程序的數量!
....(中間省略)....
|-sshd---sshd---sshd---bash---bash---sudo---su---bash---pstree <==我們指令執行的相依性
....(下面省略)....
# 注意一下,為了節省版面,所以鳥哥已經刪去很多程序了!
范例二:承上題,同時秀出 PID 與 users
[root@study ~]# pstree -Aup
systemd(1)-+-ModemManager(745)-+-{ModemManager}(785)
| `-{ModemManager}(790)
|-NetworkManager(870)-+-{NetworkManager}(907)
| |-{NetworkManager}(911)
| `-{NetworkManager}(914)
....(中間省略)....
|-sshd(1326)---sshd(13923)---sshd(13927,dmtsai)---bash(13928)---bash(13970)---
....(下面省略)....
# 在括號 () 內的即是 PID 以及該程序的 owner 喔!一般來說,如果該程序的所有人與父程序同,
# 就不會列出,但是如果與父程序不一樣,那就會列出該程序的擁有者!看上面 13927 就轉變成 dmtsai 了
```
如果要找程序之間的相關性,這個 pstree 真是好用到不行!直接輸入 pstree 可以查到程序相關性,如上表所示,還會使用線段將相關性程序鏈接起來哩! 一般鏈接符號可以使用 ASCII 碼即可,但有時因為語系問題會主動的以 Unicode 的符號來鏈接, 但因為可能終端機無法支持該編碼,或許會造成亂碼問題。因此可以加上 -A 選項來克服此類線段亂碼問題。
由 pstree 的輸出我們也可以很清楚的知道,所有的程序都是依附在 systemd 這支程序下面的! 仔細看一下,這支程序的 PID 是一號喔!因為他是由 Linux 核心所主動調用的第一支程序!所以 PID 就是一號了。 這也是我們剛剛提到[僵尸程序](../Text/index.html#zombie)時有提到,為啥發生僵尸程序需要重新開機? 因為 systemd 要重新啟動,而重新啟動 systemd 就是 reboot 啰!
如果還想要知道 PID 與所屬使用者,加上 -u 及 -p 兩個參數即可。我們前面不是一直提到, 如果子程序掛點或者是老是砍不掉子程序時,該如何找到父程序嗎?呵呵!用這個 pstree 就對了! ^_^
### 16.3.2 程序的管理
程序之間是可以互相控制的!舉例來說,你可以關閉、重新啟動服務器軟件,服務器軟件本身是個程序, 你既然可以讓她關閉或啟動,當然就是可以控制該程序啦!那么程序是如何互相管理的呢?其實是通過給予該程序一個訊號 (signal) 去告知該程序你想要讓她作什么!因此這個訊號就很重要啦!
我們也在本章之前的 [bash 工作管理](../Text/index.html#background)當中提到過, 要給予某個已經存在背景中的工作某些動作時,是直接給予一個訊號給該工作號碼即可。那么到底有多少 signal 呢? 你可以使用 kill -l (小寫的 L ) 或者是 man 7 signal 都可以查詢到!主要的訊號代號與名稱對應及內容是:
| 代號 | 名稱 | 內容 |
| --- | --- |
| 1 | SIGHUP | 啟動被終止的程序,可讓該 PID 重新讀取自己的配置文件,類似重新啟動 |
| 2 | SIGINT | 相當于用鍵盤輸入 [ctrl]-c 來中斷一個程序的進行 |
| 9 | SIGKILL | 代表強制中斷一個程序的進行,如果該程序進行到一半, 那么尚未完成的部分可能會有“半產品”產生,類似 vim會有 .filename.swp 保留下來。 |
| 15 | SIGTERM | 以正常的結束程序來終止該程序。由于是正常的終止, 所以后續的動作會將他完成。不過,如果該程序已經發生問題,就是無法使用正常的方法終止時, 輸入這個 signal 也是沒有用的。 |
| 19 | SIGSTOP | 相當于用鍵盤輸入 [ctrl]-z 來暫停一個程序的進行 |
上面僅是常見的 signal 而已,更多的訊號信息請自行 man 7 signal 吧!一般來說,你只要記得“1, 9, 15”這三個號碼的意義即可。那么我們如何傳送一個訊號給某個程序呢?就通過 kill 或 killall 吧!下面分別來看看:
* kill -signal PID
kill 可以幫我們將這個 signal 傳送給某個工作 (%jobnumber) 或者是某個 PID (直接輸入數字)。 要再次強調的是: kill 后面直接加數字與加上 %number 的情況是不同的! 這個很重要喔!因為工作控制中有 1 號工作,但是 PID 1 號則是專指“ systemd ”這支程序!你怎么可以將 systemd 關閉呢? 關閉 systemd ,你的系統就當掉了啊!所以記得那個 % 是專門用在工作控制的喔! 我們就活用一下 kill 與剛剛上面提到的 ps 來做個簡單的練習吧!
例題:以 ps 找出 rsyslogd 這個程序的 PID 后,再使用 kill 傳送訊息,使得 rsyslogd 可以重新讀取配置文件。答:由于需要重新讀取配置文件,因此 signal 是 1 號。至于找出 rsyslogd 的 PID 可以是這樣做:
> ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}'
接下來則是實際使用 kill -1 PID,因此,整串指令會是這樣:
> kill -SIGHUP $(ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}')
如果要確認有沒有重新啟動 syslog ,可以參考登錄文件的內容,使用如下指令查閱:
> tail -5 /var/log/messages
如果你有看到類似“Aug 5 01:25:02 study rsyslogd: [origin software="rsyslogd" swVersion="7.4.7" x-pid="742" x-info="http://www.rsyslog.com"] rsyslogd was HUPed”之類的字樣,就是表示 rsyslogd 在 8/5 有重新啟動 (restart) 過了!
了解了這個用法以后,如果未來你想要將某個莫名其妙的登陸者的連線刪除的話,就可以通過使用 pstree -p 找到相關程序, 然后再以 kill -9 將該程序刪除,該條連線就會被踢掉了!這樣很簡單吧!
* killall -signal 指令名稱
由于 kill 后面必須要加上 PID (或者是 job number),所以,通常 kill 都會配合 [ps](../Text/index.html#ps), [pstree](../Text/index.html#pstree) 等指令,因為我們必須要找到相對應的那個程序的 ID 嘛!但是,如此一來,很麻煩~有沒有可以利用“下達指令的名稱”來給予訊號的?舉例來說,能不能直接將 rsyslogd 這個程序給予一個 SIGHUP 的訊號呢?可以的!用 killall 吧!
```
[root@study ~]# killall [-iIe] [command name]
選項與參數:
-i :interactive 的意思,互動式的,若需要刪除時,會出現提示字符給使用者;
-e :exact 的意思,表示“后面接的 command name 要一致”,但整個完整的指令
不能超過 15 個字符。
-I :指令名稱(可能含參數)忽略大小寫。
范例一:給予 rsyslogd 這個指令啟動的 PID 一個 SIGHUP 的訊號
[root@study ~]# killall -1 rsyslogd
# 如果用 ps aux 仔細看一下,若包含所有參數,則 /usr/sbin/rsyslogd -n 才是最完整的!
范例二:強制終止所有以 httpd 啟動的程序 (其實并沒有此程序在系統內)
[root@study ~]# killall -9 httpd
范例三:依次詢問每個 bash 程序是否需要被終止運行!
[root@study ~]# killall -i -9 bash
Signal bash(13888) ? (y/N) n <==這個不殺!
Signal bash(13928) ? (y/N) n <==這個不殺!
Signal bash(13970) ? (y/N) n <==這個不殺!
Signal bash(14836) ? (y/N) y <==這個殺掉!
# 具有互動的功能!可以詢問你是否要刪除 bash 這個程序。要注意,若沒有 -i 的參數,
# 所有的 bash 都會被這個 root 給殺掉!包括 root 自己的 bash 喔! ^_^
```
總之,要刪除某個程序,我們可以使用 PID 或者是啟動該程序的指令名稱, 而如果要刪除某個服務呢?呵呵!最簡單的方法就是利用 killall , 因為他可以將系統當中所有以某個指令名稱啟動的程序全部刪除。 舉例來說,上面的范例二當中,系統內所有以 httpd 啟動的程序,就會通通的被刪除啦! ^_^
### 16.3.3 關于程序的執行順序
我們知道 Linux 是多用戶多任務的環境,由 [top](../Text/index.html#topm) 的輸出結果我們也發現, 系統同時間有非常多的程序在運行中,只是絕大部分的程序都在休眠 (sleeping) 狀態而已。 想一想,如果所有的程序同時被喚醒,那么 CPU 應該要先處理那個程序呢?也就是說,那個程序被執行的優先序比較高? 這就得要考慮到程序的優先執行序 (Priority) 與 CPU 調度啰!

**Tips** CPU 調度與前一章的例行性工作調度并不一樣。 CPU 調度指的是每支程序被 CPU 運行的演算規則, 而例行性工作調度則是將某支程序安排在某個時間再交由系統執行。 CPU 調度與操作系統較具有相關性!
* Priority 與 Nice 值
我們知道 CPU 一秒鐘可以運行多達數 G 的微指令次數,通過核心的 CPU 調度可以讓各程序被 CPU 所切換運行, 因此每個程序在一秒鐘內或多或少都會被 CPU 執行部分的指令碼。如果程序都是集中在一個佇列中等待 CPU 的運行, 而不具有優先順序之分,也就是像我們去游樂場玩熱門游戲需要排隊一樣,每個人都是照順序來! 你玩過一遍后還想再玩 (沒有執行完畢),請到后面繼續排隊等待。情況有點像下面這樣:
圖16.3.1、并沒有優先順序的程序佇列示意圖
上圖中假設 pro1, pro2 是緊急的程序, pro3, pro4 是一般的程序,在這樣的環境中,由于不具有優先順序, 唉啊!pro1, pro2 還是得要繼續等待而沒有優待呢!如果 pro3, pro4 的工作又臭又長!那么緊急的 pro1, pro2 就得要等待個老半天才能夠完成!真麻煩啊!所以啰,我們想要將程序分優先順序啦!如果優先序較高則運行次數可以較多次, 而不需要與較慢優先的程序搶位置!我們可以將程序的優先順序與 CPU 調度進行如下圖的解釋:
圖16.3.2、具有優先順序的程序佇列示意圖
如上圖所示,具高優先權的 pro1, pro2 可以被取用兩次,而較不重要的 pro3, pro4 則運行次數較少。 如此一來 pro1, pro2 就可以較快被完成啦!要注意,上圖僅是示意圖,并非較優先者一定會被運行兩次啦! 為了要達到上述的功能,我們 Linux 給予程序一個所謂的“優先執行序 (priority, PRI)”, 這個 PRI 值越低代表越優先的意思。不過這個 PRI 值是由核心動態調整的, 使用者無法直接調整 PRI 值的。先來瞧瞧 PRI 曾在哪里出現?
```
[root@study ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 90 10 - 29068 wait pts/0 00:00:00 bash
0 R 0 19848 14836 0 90 10 - 30319 - pts/0 00:00:00 ps
# 你應該要好奇,怎么我的 NI 已經是 10 了?還記得剛剛 top 的測試嗎?我們在那邊就有改過一次喔!
```
由于 PRI 是核心動態調整的,我們使用者也無權去干涉 PRI !那如果你想要調整程序的優先執行序時,就得要通過 Nice 值了!Nice 值就是上表的 NI 啦!一般來說, PRI 與 NI 的相關性如下:
> PRI(new) = PRI(old) + nice
不過你要特別留意到,如果原本的 PRI 是 50 ,并不是我們給予一個 nice = 5 ,就會讓 PRI 變成 55 喔! 因為 PRI 是系統“動態”決定的,所以,雖然 nice 值是可以影響 PRI ,不過, 最終的 PRI 仍是要經過系統分析后才會決定的。另外, nice 值是有正負的喔,而既然 PRI 越小越早被執行, 所以,當 nice 值為負值時,那么該程序就會降低 PRI 值,亦即會變的較優先被處理。此外,你必須要留意到:
* nice 值可調整的范圍為 -20 ~ 19 ;
* root 可隨意調整自己或他人程序的 Nice 值,且范圍為 -20 ~ 19 ;
* 一般使用者僅可調整自己程序的 Nice 值,且范圍僅為 0 ~ 19 (避免一般用戶搶占系統資源);
* 一般使用者僅可將 nice 值越調越高,例如本來 nice 為 5 ,則未來僅能調整到大于 5;
這也就是說,要調整某個程序的優先執行序,就是“調整該程序的 nice 值”啦!那么如何給予某個程序 nice 值呢?有兩種方式,分別是:
* 一開始執行程序就立即給予一個特定的 nice 值:用 nice 指令;
* 調整某個已經存在的 PID 的 nice 值:用 renice 指令。
* nice :新執行的指令即給予新的 nice 值
```
[root@study ~]# nice [-n 數字] command
選項與參數:
-n :后面接一個數值,數值的范圍 -20 ~ 19。
范例一:用 root 給一個 nice 值為 -5 ,用于執行 vim ,并觀察該程序!
[root@study ~]# nice -n -5 vim &
[1] 19865
[root@study ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 90 10 - 29068 wait pts/0 00:00:00 bash
4 T 0 19865 14836 0 85 5 - 37757 signal pts/0 00:00:00 vim
0 R 0 19866 14836 0 90 10 - 30319 - pts/0 00:00:00 ps
# 原本的 bash PRI 為 90 ,所以 vim 默認應為 90。不過由于給予 nice 為 -5 ,
# 因此 vim 的 PRI 降低了!RPI 與 NI 各減 5 !但不一定每次都是正好相同喔!因為核心會動態調整
[root@study ~]# kill -9 %1 <==測試完畢將 vim 關閉
```
就如同前面說的, nice 是用來調整程序的執行優先順序!這里只是一個執行的范例罷了! 通常什么時候要將 nice 值調大呢?舉例來說,系統的背景工作中, 某些比較不重要的程序之進行:例如備份工作!由于備份工作相當的耗系統資源, 這個時候就可以將備份的指令之 nice 值調大一些,可以使系統的資源分配的更為公平!
* renice :已存在程序的 nice 重新調整
```
[root@study ~]# renice [number] PID
選項與參數:
PID :某個程序的 ID 啊!
范例一:找出自己的 bash PID ,并將該 PID 的 nice 調整到 -5
[root@study ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 90 10 - 29068 wait pts/0 00:00:00 bash
0 R 0 19900 14836 0 90 10 - 30319 - pts/0 00:00:00 ps
[root@study ~]# renice -5 14836
14836 (process ID) old priority 10, new priority -5
[root@study ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 14836 14835 0 75 -5 - 29068 wait pts/0 00:00:00 bash
0 R 0 19910 14836 0 75 -5 - 30319 - pts/0 00:00:00 ps
```
如果要調整的是已經存在的某個程序的話,那么就得要使用 renice 了。使用的方法很簡單, renice 后面接上數值及 PID 即可。因為后面接的是 PID ,所以你務必要以 ps 或者其他程序觀察的指令去找出 PID 才行啊!
由上面這個范例當中我們也看的出來,雖然修改的是 bash 那個程序,但是該程序所觸發的 ps 指令當中的 nice 也會繼承而為 -5 喔!了解了吧!整個 nice 值是可以在父程序 --> 子程序之間傳遞的呢! 另外,除了 renice 之外,其實那個 [top](../Text/index.html#topm) 同樣的也是可以調整 nice 值的!
### 16.3.4 系統資源的觀察
除了系統的程序之外,我們還必須就系統的一些資源進行檢查啊!舉例來說,我們使用 top 可以看到很多系統的資源對吧!那么,還有沒有其他的工具可以查閱的? 當然有啊!下面這些工具指令可以玩一玩!
* free :觀察內存使用情況
```
[root@study ~]# free [-b|-k|-m|-g|-h] [-t] [-s N -c N]
選項與參數:
-b :直接輸入 free 時,顯示的單位是 KBytes,我們可以使用 b(Bytes), m(MBytes)
k(KBytes), 及 g(GBytes) 來顯示單位喔!也可以直接讓系統自己指定單位 (-h)
-t :在輸出的最終結果,顯示實體內存與 swap 的總量。
-s :可以讓系統每幾秒鐘輸出一次,不間斷的一直輸出的意思!對于系統觀察挺有效!
-c :與 -s 同時處理~讓 free 列出幾次的意思~
范例一:顯示目前系統的內存容量
[root@study ~]# free -m
total used free shared buff/cache available
Mem: 2848 346 1794 8 706 2263
Swap: 1023 0 1023
```
仔細看看,我的系統當中有 2848MB 左右的實體內存,我的 swap 有 1GB 左右, 那我使用 free -m 以 MBytes 來顯示時,就會出現上面的信息。Mem 那一行顯示的是實體內存的量, Swap 則是內存交換空間的量。 total 是總量, used 是已被使用的量, free 則是剩余可用的量。 后面的 shared/buffers/cached 則是在已被使用的量當中,用來作為緩沖及高速緩存的量,這些 shared/buffers/cached 的用量中,在系統比較忙碌時, 可以被釋出而繼續利用!因此后面就有一個 available (可用的) 數值! 。
請看上頭范例一的輸出,我們可以發現這部測試機根本沒有什么特別的服務,但是竟然有 706MB 左右的 cache 耶! 因為鳥哥在測試過程中還是有讀/寫/執行很多的文件嘛!這些文件就會被系統暫時高速緩存下來,等待下次運行時可以更快速的取出之意! 也就是說,系統是“很有效率的將所有的內存用光光”,目的是為了讓系統的存取性能加速啦!
很多朋友都會問到這個問題“我的系統明明很輕松,為何內存會被用光光?”現在瞭了吧? 被用光是正常的!而需要注意的反而是 swap 的量。一般來說, swap 最好不要被使用,尤其 swap 最好不要被使用超過 20% 以上, 如果您發現 swap 的用量超過 20% ,那么,最好還是買實體內存來插吧! 因為, Swap 的性能跟實體內存實在差很多,而系統會使用到 swap , 絕對是因為實體內存不足了才會這樣做的!如此,了解吧!

**Tips** Linux 系統為了要加速系統性能,所以會將最常使用到的或者是最近使用到的文件數據高速緩存 (cache) 下來, 這樣未來系統要使用該文件時,就直接由內存中搜尋取出,而不需要重新讀取硬盤,速度上面當然就加快了! 因此,實體內存被用光是正常的喔!
* uname:查閱系統與核心相關信息
```
[root@study ~]# uname [-asrmpi]
選項與參數:
-a :所有系統相關的信息,包括下面的數據都會被列出來;
-s :系統核心名稱
-r :核心的版本
-m :本系統的硬件名稱,例如 i686 或 x86_64 等;
-p :CPU 的類型,與 -m 類似,只是顯示的是 CPU 的類型!
-i :硬件的平臺 (ix86)
范例一:輸出系統的基本信息
[root@study ~]# uname -a
Linux study.centos.vbird 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015
x86_64 x86_64 x86_64 GNU/Linux
```
這個咚咚我們前面使用過很多次了喔!uname 可以列出目前系統的核心版本、 主要硬件平臺以及 CPU 類型等等的信息。以上面范例一的狀態來說,我的 Linux 主機使用的核心名稱為 Linux,而主機名稱為 study.centos.vbird,核心的版本為 3.10.0-229.el7.x86_64 ,該核心版本創建的日期為 2015-3-6,適用的硬件平臺為 x86_64 以上等級的硬件平臺喔。
* uptime:觀察系統啟動時間與工作負載
這個指令很單純呢!就是顯示出目前系統已經開機多久的時間,以及 1, 5, 15 分鐘的平均負載就是了。還記得 [top](../Text/index.html#topm) 吧?沒錯啦!這個 uptime 可以顯示出 top 畫面的最上面一行!
```
[root@study ~]# uptime
02:35:27 up 7:48, 3 users, load average: 0.00, 0.01, 0.05
# [top](../Text/index.html#topm) 這個指令已經談過相關信息,不再聊!
```
* netstat :追蹤網絡或插槽檔
這個 netstat 也是挺好玩的,其實這個指令比較常被用在網絡的監控方面,不過,在程序管理方面也是需要了解的啦! 這個指令的執行如下所示:基本上, netstat 的輸出分為兩大部分,分別是網絡與系統自己的程序相關性部分:
```
[root@study ~]# netstat -[atunlp]
選項與參數:
-a :將目前系統上所有的連線、監聽、Socket 數據都列出來
-t :列出 tcp 網絡封包的數據
-u :列出 udp 網絡封包的數據
-n :不以程序的服務名稱,以埠號 (port number) 來顯示;
-l :列出目前正在網絡監聽 (listen) 的服務;
-p :列出該網絡服務的程序 PID
范例一:列出目前系統已經創建的網絡連線與 unix socket 狀態
[root@study ~]# netstat
Active Internet connections (w/o servers) <==與網絡較相關的部分
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 172.16.15.100:ssh 172.16.220.234:48300 ESTABLISHED
Active UNIX domain sockets (w/o servers) <==與本機的程序自己的相關性(非網絡)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ] DGRAM 1902 @/org/freedesktop/systemd1/notify
unix 2 [ ] DGRAM 1944 /run/systemd/shutdownd
....(中間省略)....
unix 3 [ ] STREAM CONNECTED 25425 @/tmp/.X11-unix/X0
unix 3 [ ] STREAM CONNECTED 28893
unix 3 [ ] STREAM CONNECTED 21262
```
在上面的結果當中,顯示了兩個部分,分別是網絡的連線以及 linux 上面的 socket 程序相關性部分。 我們先來看看網際網絡連線情況的部分:
* Proto :網絡的封包協定,主要分為 TCP 與 UDP 封包,相關數據請參考[服務器篇](http://linux.vbird.org/linux_server);
* Recv-Q:非由使用者程序鏈接到此 socket 的復制的總 Bytes 數;
* Send-Q:非由遠端主機傳送過來的 acknowledged 總 Bytes 數;
* Local Address :本地端的 IP:port 情況
* Foreign Address:遠端主機的 IP:port 情況
* State :連線狀態,主要有創建(ESTABLISED)及監聽(LISTEN);
我們看上面僅有一條連線的數據,他的意義是:“通過 TCP 封包的連線,遠端的 172.16.220.234:48300 連線到本地端的 172.16.15.100:ssh ,這條連線狀態是創建 (ESTABLISHED) 的狀態!”至于更多的網絡環境說明, 就得到[鳥哥的另一本服務器篇](http://linux.vbird.org/linux_server)查閱啰!
除了網絡上的連線之外,其實 Linux 系統上面的程序是可以接收不同程序所發送來的信息,那就是 Linux 上頭的插槽檔 (socket file)。我們在[第五章的文件種類](../Text/index.html#filepermission_type)有稍微提到 socket 文件, 但當時未談到程序的概念,所以沒有深入談論。socket file 可以溝通兩個程序之間的信息,因此程序可以取得對方傳送過來的數據。 由于有 socket file,因此類似 X Window 這種需要通過網絡連接的軟件,目前新版的 distributions 就以 socket 來進行窗口接口的連線溝通了。上表中 socket file 的輸出字段有:
* Proto :一般就是 unix 啦;
* RefCnt:連接到此 socket 的程序數量;
* Flags :連線的旗標;
* Type :socket 存取的類型。主要有確認連線的 STREAM 與不需確認的 DGRAM 兩種;
* State :若為 CONNECTED 表示多個程序之間已經連線創建。
* Path :連接到此 socket 的相關程序的路徑!或者是相關數據輸出的路徑。
以上表的輸出為例,最后那三行在 /tmp/.xx 下面的數據,就是 X Window 窗口接口的相關程序啦! 而 PATH 指向的就是這些程序要交換數據的插槽文件啰!好!那么 netstat 可以幫我們進行什么任務呢? 很多喔!我們先來看看,利用 netstat 去看看我們的哪些程序有啟動哪些網絡的“后門”呢?
```
范例二:找出目前系統上已在監聽的網絡連線及其 PID
[root@study ~]# netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1326/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 2349/master
tcp6 0 0 :::22 :::* LISTEN 1326/sshd
tcp6 0 0 ::1:25 :::* LISTEN 2349/master
udp 0 0 0.0.0.0:123 0.0.0.0:* 751/chronyd
udp 0 0 127.0.0.1:323 0.0.0.0:* 751/chronyd
udp 0 0 0.0.0.0:57808 0.0.0.0:* 743/avahi-daemon: r
udp 0 0 0.0.0.0:5353 0.0.0.0:* 743/avahi-daemon: r
udp6 0 0 :::123 :::* 751/chronyd
udp6 0 0 ::1:323 :::* 751/chronyd
# 除了可以列出監聽網絡的接口與狀態之外,最后一個字段還能夠顯示此服務的
# PID 號碼以及程序的指令名稱喔!例如上頭的 1326 就是該 PID
范例三:將上述的 0.0.0.0:57808 那個網絡服務關閉的話?
[root@study ~]# kill -9 743
[root@study ~]# killall -9 avahi-daemon
```
很多朋友常常有疑問,那就是,我的主機目前到底開了幾個門(ports)!其實,不論主機提供什么樣的服務, 一定必須要有相對應的 program 在主機上面執行才行啊!舉例來說,我們鳥園的 Linux 主機提供的就是 WWW 服務,那么我的主機當然有一個程序在提供 WWW 的服務啊!那就是 Apache 這個軟件所提供的啦! ^_^。 所以,當我執行了這個程序之后,我的系統自然就可以提供 WWW 的服務了。那如何關閉啊? 就關掉該程序所觸發的那個程序就好了!例如上面的范例三所提供的例子啊!不過,這個是非正規的作法喔! 正規的作法,請查閱下一章的說明呦!
* dmesg :分析核心產生的訊息
系統在開機的時候,核心會去偵測系統的硬件,你的某些硬件到底有沒有被捉到,那就與這個時候的偵測有關。 但是這些偵測的過程要不是沒有顯示在屏幕上,就是很飛快的在屏幕上一閃而逝!能不能把核心偵測的訊息捉出來瞧瞧? 可以的,那就使用 dmesg 吧!
所有核心偵測的訊息,不管是開機時候還是系統運行過程中,反正只要是核心產生的訊息,都會被記錄到內存中的某個保護區段。 dmesg 這個指令就能夠將該區段的訊息讀出來的!因為訊息實在太多了,所以執行時可以加入這個管線指令“ | more ”來使畫面暫停!
```
范例一:輸出所有的核心開機時的信息
[root@study ~]# dmesg | more
范例二:搜尋開機的時候,硬盤的相關信息為何?
[root@study ~]# dmesg | grep -i vda
[ 0.758551] vda: vda1 vda2 vda3 vda4 vda5 vda6 vda7 vda8 vda9
[ 3.964134] XFS (vda2): Mounting V4 Filesystem
....(下面省略)....
```
由范例二就知道我這部主機的硬盤的格式是什么了吧!
* vmstat :偵測系統資源變化
如果你想要動態的了解一下系統資源的運行,那么這個 vmstat 確實可以玩一玩!vmstat 可以偵測“ CPU / 內存 / 磁盤輸入輸出狀態 ”等等,如果你想要了解一部繁忙的系統到底是哪個環節最累人, 可以使用 vmstat 分析看看。下面是常見的選項與參數說明:
```
[root@study ~]# vmstat [-a] [延遲 [總計偵測次數]] <==CPU/內存等信息
[root@study ~]# vmstat [-fs] <==內存相關
[root@study ~]# vmstat [-S 單位] <==設置顯示數據的單位
[root@study ~]# vmstat [-d] <==與磁盤有關
[root@study ~]# vmstat [-p 分區] <==與磁盤有關
選項與參數:
-a :使用 inactive/active(活躍與否) 取代 buffer/cache 的內存輸出信息;
-f :開機到目前為止,系統復制 (fork) 的程序數;
-s :將一些事件 (開機至目前為止) 導致的內存變化情況列表說明;
-S :后面可以接單位,讓顯示的數據有單位。例如 K/M 取代 Bytes 的容量;
-d :列出磁盤的讀寫總量統計表
-p :后面列出分區,可顯示該分區的讀寫總量統計表
范例一:統計目前主機 CPU 狀態,每秒一次,共計三次!
[root@study ~]# vmstat 1 3
procs ------------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 1838092 1504 722216 0 0 4 1 6 9 0 0 100 0 0
0 0 0 1838092 1504 722200 0 0 0 0 13 23 0 0 100 0 0
0 0 0 1838092 1504 722200 0 0 0 0 25 46 0 0 100 0 0
```
利用 vmstat 甚至可以進行追蹤喔!你可以使用類似“ vmstat 5 ”代表每五秒鐘更新一次,且無窮的更新!直到你按下 [ctrl]-c 為止。如果你想要實時的知道系統資源的運行狀態,這個指令就不能不知道!那么上面的表格各項字段的意義為何? 基本說明如下:
* 程序字段 (procs) 的項目分別為:
r :等待運行中的程序數量;b:不可被喚醒的程序數量。這兩個項目越多,代表系統越忙碌 (因為系統太忙,所以很多程序就無法被執行或一直在等待而無法被喚醒之故)。
* 內存字段 (memory) 項目分別為:
swpd:虛擬內存被使用的容量; free:未被使用的內存容量; buff:用于緩沖內存; cache:用于高速緩存內存。 這部份則與 [free](../Text/index.html#free) 是相同的。
* 內存交換空間 (swap) 的項目分別為:
si:由磁盤中將程序取出的量; so:由于內存不足而將沒用到的程序寫入到磁盤的 swap 的容量。 如果 si/so 的數值太大,表示內存內的數據常常得在磁盤與內存之間傳來傳去,系統性能會很差!
* 磁盤讀寫 (io) 的項目分別為:
bi:由磁盤讀入的區塊數量; bo:寫入到磁盤去的區塊數量。如果這部份的值越高,代表系統的 I/O 非常忙碌!
* 系統 (system) 的項目分別為:
in:每秒被中斷的程序次數; cs:每秒鐘進行的事件切換次數;這兩個數值越大,代表系統與周邊設備的溝通非常頻繁! 這些周邊設備當然包括磁盤、網卡、時間鐘等。
* CPU 的項目分別為:
us:非核心層的 CPU 使用狀態; sy:核心層所使用的 CPU 狀態; id:閑置的狀態; wa:等待 I/O 所耗費的 CPU 狀態; st:被虛擬機 (virtual machine) 所盜用的 CPU 使用狀態 (2.6.11 以后才支持)。
由于鳥哥的機器是測試機,所以并沒有什么 I/O 或者是 CPU 忙碌的情況。如果改天你的服務器非常忙碌時, 記得使用 vmstat 去看看,到底是哪個部分的資源被使用的最為頻繁!一般來說,如果 I/O 部分很忙碌的話,你的系統會變的非常慢! 讓我們再來看看,那么磁盤的部分該如何觀察:
```
范例二:系統上面所有的磁盤的讀寫狀態
[root@study ~]# vmstat -d
disk- ------------reads------------ ------------writes----------- -----IO------
total merged sectors ms total merged sectors ms cur sec
vda 21928 0 992587 47490 7239 2225 258449 13331 0 26
sda 395 1 3168 213 0 0 0 0 0 0
sr0 0 0 0 0 0 0 0 0 0 0
dm-0 19139 0 949575 44608 7672 0 202251 16264 0 25
dm-1 336 0 2688 327 0 0 0 0 0 0
md0 212 0 1221 0 14 0 4306 0 0 0
dm-2 218 0 9922 565 54 0 4672 128 0 0
dm-3 179 0 957 182 11 0 4306 68 0 0
```
詳細的各字段就請諸位大德查閱一下 man vmstat 啰!反正與讀寫有關啦!這樣了解乎!
- 鳥哥的Linux私房菜:基礎學習篇 第四版
- 目錄及概述
- 第零章、計算機概論
- 0.1 電腦:輔助人腦的好工具
- 0.2 個人電腦架構與相關設備元件
- 0.3 數據表示方式
- 0.4 軟件程序運行
- 0.5 重點回顧
- 0.6 本章習題
- 0.7 參考資料與延伸閱讀
- 第一章、Linux是什么與如何學習
- 1.1 Linux是什么
- 1.2 Torvalds的Linux發展
- 1.3 Linux當前應用的角色
- 1.4 Linux 該如何學習
- 1.5 重點回顧
- 1.6 本章習題
- 1.7 參考資料與延伸閱讀
- 第二章、主機規劃與磁盤分區
- 2.1 Linux與硬件的搭配
- 2.2 磁盤分區
- 2.3 安裝Linux前的規劃
- 2.4 重點回顧
- 2.5 本章習題
- 2.6 參考資料與延伸閱讀
- 第三章、安裝 CentOS7.x
- 3.1 本練習機的規劃--尤其是分區參數
- 3.2 開始安裝CentOS 7
- 3.3 多重開機安裝流程與管理(Option)
- 3.4 重點回顧
- 3.5 本章習題
- 3.6 參考資料與延伸閱讀
- 第四章、首次登陸與線上求助
- 4.1 首次登陸系統
- 4.2 文字模式下指令的下達
- 4.3 Linux系統的線上求助man page與info page
- 4.4 超簡單文書編輯器: nano
- 4.5 正確的關機方法
- 4.6 重點回顧
- 4.7 本章習題
- 4.8 參考資料與延伸閱讀
- 第五章、Linux 的文件權限與目錄配置
- 5.1 使用者與群組
- 5.2 Linux 文件權限概念
- 5.3 Linux目錄配置
- 5.4 重點回顧
- 5.5 本章練習
- 5.6 參考資料與延伸閱讀
- 第六章、Linux 文件與目錄管理
- 6.1 目錄與路徑
- 6.2 文件與目錄管理
- 6.3 文件內容查閱
- 6.4 文件與目錄的默認權限與隱藏權限
- 6.5 指令與文件的搜尋
- 6.6 極重要的復習!權限與指令間的關系
- 6.7 重點回顧
- 6.8 本章習題:
- 6.9 參考資料與延伸閱讀
- 第七章、Linux 磁盤與文件系統管理
- 7.1 認識 Linux 文件系統
- 7.2 文件系統的簡單操作
- 7.3 磁盤的分區、格式化、檢驗與掛載
- 7.4 設置開機掛載
- 7.5 內存交換空間(swap)之創建
- 7.6 文件系統的特殊觀察與操作
- 7.7 重點回顧
- 7.8 本章習題 - 第一題一定要做
- 7.9 參考資料與延伸閱讀
- 第八章、文件與文件系統的壓縮,打包與備份
- 8.1 壓縮文件的用途與技術
- 8.2 Linux 系統常見的壓縮指令
- 8.3 打包指令: tar
- 8.4 XFS 文件系統的備份與還原
- 8.5 光盤寫入工具
- 8.6 其他常見的壓縮與備份工具
- 8.7 重點回顧
- 8.8 本章習題
- 8.9 參考資料與延伸閱讀
- 第九章、vim 程序編輯器
- 9.1 vi 與 vim
- 9.2 vi 的使用
- 9.3 vim 的額外功能
- 9.4 其他 vim 使用注意事項
- 9.5 重點回顧
- 9.6 本章練習
- 9.7 參考資料與延伸閱讀
- 第十章、認識與學習BASH
- 10.1 認識 BASH 這個 Shell
- 10.2 Shell 的變量功能
- 10.3 命令別名與歷史命令
- 10.4 Bash Shell 的操作環境:
- 10.5 數據流重導向
- 10.6 管線命令 (pipe)
- 10.7 重點回顧
- 10.8 本章習題
- 10.9 參考資料與延伸閱讀
- 第十一章、正則表達式與文件格式化處理
- 11.1 開始之前:什么是正則表達式
- 11.2 基礎正則表達式
- 11.3 延伸正則表達式
- 11.4 文件的格式化與相關處理
- 11.5 重點回顧
- 11.6 本章習題
- 11.7 參考資料與延伸閱讀
- 第十二章、學習 Shell Scripts
- 12.1 什么是 Shell scripts
- 12.2 簡單的 shell script 練習
- 12.3 善用判斷式
- 12.4 條件判斷式
- 12.5 循環 (loop)
- 12.6 shell script 的追蹤與 debug
- 12.7 重點回顧
- 12.8 本章習題
- 第十三章、Linux 帳號管理與 ACL 權限設置
- 13.1 Linux 的帳號與群組
- 13.2 帳號管理
- 13.3 主機的細部權限規劃:ACL 的使用
- 13.4 使用者身份切換
- 13.5 使用者的特殊 shell 與 PAM 模塊
- 13.6 Linux 主機上的使用者訊息傳遞
- 13.7 CentOS 7 環境下大量創建帳號的方法
- 13.8 重點回顧
- 13.9 本章習題
- 13.10 參考資料與延伸閱讀
- 第十四章、磁盤配額(Quota)與進階文件系統管理
- 14.1 磁盤配額 (Quota) 的應用與實作
- 14.2 軟件磁盤陣列 (Software RAID)
- 14.3 邏輯卷軸管理員 (Logical Volume Manager)
- 14.4 重點回顧
- 14.5 本章習題
- 14.6 參考資料與延伸閱讀
- 第十五章、例行性工作調度(crontab)
- 15.1 什么是例行性工作調度
- 15.2 僅執行一次的工作調度
- 15.3 循環執行的例行性工作調度
- 15.4 可喚醒停機期間的工作任務
- 15.5 重點回顧
- 15.6 本章習題
- 第十六章、程序管理與 SELinux 初探
- 16.1 什么是程序 (process)
- 16.2 工作管理 (job control)
- 16.3 程序管理
- 16.4 特殊文件與程序
- 16.5 SELinux 初探
- 16.6 重點回顧
- 16.7 本章習題
- 16.8 參考資料與延伸閱讀
- 第十七章、認識系統服務 (daemons)
- 17.1 什么是 daemon 與服務 (service)
- 17.2 通過 systemctl 管理服務
- 17.3 systemctl 針對 service 類型的配置文件
- 17.4 systemctl 針對 timer 的配置文件
- 17.5 CentOS 7.x 默認啟動的服務簡易說明
- 17.6 重點回顧
- 17.7 本章習題
- 17.8 參考資料與延伸閱讀
- 第十八章、認識與分析登錄文件
- 18.1 什么是登錄文件
- 18.2 rsyslog.service :記錄登錄文件的服務
- 18.3 登錄文件的輪替(logrotate)
- 18.4 systemd-journald.service 簡介
- 18.5 分析登錄文件
- 18.6 重點回顧
- 18.7 本章習題
- 18.8 參考資料與延伸閱讀
- 第十九章、開機流程、模塊管理與 Loader
- 19.1 Linux 的開機流程分析
- 19.2 核心與核心模塊
- 19.3 Boot Loader: Grub2
- 19.4 開機過程的問題解決
- 19.5 重點回顧
- 19.6 本章習題
- 19.7 參考資料與延伸閱讀
- 第二十章、基礎系統設置與備份策略
- 20.1 系統基本設置
- 20.2 服務器硬件數據的收集
- 20.3 備份要點
- 20.4 備份的種類、頻率與工具的選擇
- 20.5 鳥哥的備份策略
- 20.6 災難復原的考慮
- 20.7 重點回顧
- 20.8 本章習題
- 20.9 參考資料與延伸閱讀
- 第二十一章、軟件安裝:源代碼與 Tarball
- 20.1 開放源碼的軟件安裝與升級簡介
- 21.2 使用傳統程序語言進行編譯的簡單范例
- 21.3 用 make 進行宏編譯
- 21.4 Tarball 的管理與建議
- 21.5 函數庫管理
- 21.6 檢驗軟件正確性
- 21.7 重點回顧
- 21.8 本章習題
- 21.9 參考資料與延伸閱讀
- 第二十二章、軟件安裝 RPM, SRPM 與 YUM
- 22.1 軟件管理員簡介
- 22.2 RPM 軟件管理程序: rpm
- 22.3 YUM 線上升級機制
- 22.4 SRPM 的使用 : rpmbuild (Optional)
- 22.5 重點回顧
- 22.6 本章習題
- 22.7 參考資料與延伸閱讀
- 第二十三章、X Window 設置介紹
- 23.1 什么是 X Window System
- 23.2 X Server 配置文件解析與設置
- 23.3 顯卡驅動程序安裝范例
- 23.4 重點回顧
- 23.5 本章習題
- 23.6 參考資料與延伸閱讀
- 第二十四章、Linux 核心編譯與管理
- 24.1 編譯前的任務:認識核心與取得核心源代碼
- 24.2 核心編譯的前處理與核心功能選擇
- 24.3 核心的編譯與安裝
- 24.4 額外(單一)核心模塊編譯
- 24.5 以最新核心版本編譯 CentOS 7.x 的核心
- 24.6 重點回顧
- 24.7 本章習題
- 24.8 參考資料與延伸閱讀