原文發表于“網絡安全和資訊化”2018年第3期,轉載到部落格。
程序管理是Linux系統運維人員應掌握的一項基本技能,Linux作為典型的多使用者作業系統,允許多個使用者同時從不同的終端進行登入,使用者在相應終端上所啟動的程序與各自的終端之間存在緊密的聯系。本文以CentOS7系統為例,通過兩個具體的執行個體介紹了如何對Linux系統中的程序和終端進行管理。
1. 什麼是Linux系統的終端
通常我們将一套鍵盤滑鼠以及顯示器這樣的輸入輸出裝置稱為一個終端,直接連接配接在電腦主機上的稱為實體終端。在操作安裝有Windows系統的電腦時,通常是隻有一套實體終端并且隻有一個操作界面。而Linux系統支援虛拟終端,在操作安裝有Linux系統的計算機時,使用者雖然面對的也是一套實體終端裝置,但卻可以通過虛拟終端打開多個互不幹擾、獨立工作的界面。
Linux中提供的虛拟終端預設有6個,其中第1個是圖形界面,第2到6個則是字元界面。可以通過Ctrl+Alt+F(1~6)組合鍵在不同的虛拟終端之間進行切換,比如安裝有X Window的Linux系統啟動之後預設就是進入了第1個虛拟終端中的圖形界面,此時按下組合鍵Ctrl+Alt+F2就進入到了第2個虛拟終端,這就是一個字元界面了。
虛拟終端的縮寫為tty,在字元界面下執行“tty”指令就可以顯示使用者目前所在的終端編号。
[root@localhost ~]# tty
/dev/tty2
由于我們通常都是通過網絡遠端對Linux伺服器進行管理,這種通過遠端登入方式所打開的終端稱為僞終端(pts)。比如我們通過Xshell遠端登入到Linux系統,然後同樣執行tty指令,發現顯示的結果為“/dev/pts/0”,表示這是系統啟動的第一個僞終端(僞終端的編号從0開始)。
[root@localhost ~]# tty
/dev/pts/0
另外,如果Linux系統安裝了X Window,那麼在圖形界面中,右鍵單擊桌面空白處然後選擇“在終端中打開”,此時所打開的也是一個pts僞終端。但由于在生産環境中很少有人會這樣操作,是以這種情況可以忽略不計。
因而可以總結一下,對于Linux系統而言,終端主要分為兩類:由使用者在本地所打開的終端稱為虛拟終端tty,由使用者在遠端所打開的終端稱為僞終端pts。由于絕大多數情況下我們都是遠端對Linux伺服器進行管理,因而使用者所使用的終端主要是僞終端pts。每個終端都有相應的編号,執行tty指令就可以檢視到使用者目前所在的終端編号。
2. 程序中的終端資訊
Linux系統中的程序與啟動程序的終端之間是緊密關聯的,比如我們直接執行不帶任何選項的ps指令,将隻顯示目前使用者在目前終端所啟動的程序。
[root@localhost ~]# ps
PID TTY TIME CMD
5290 pts/0 00:00:00 bash
5309 pts/0 00:00:00 ps
可以看到,目前使用者隻啟動了2個程序,分别是“bash”和“ps”。其中“ps”就是剛才執行的ps指令所産生的程序,而“bash”則是目前終端所對應的終端程序,它也是ps程序的父程序。
如果希望檢視系統中所有的程序,就需要為ps指令加上相應的選項,比如常用的選項組合“aux”,其中的選項“a”就表示顯示與目前終端有關的所有程序,選項“x”表示顯示與目前終端無關的所有程序,因而兩個選項結合起來就表示顯示系統中的所有程序了。
比如分屏檢視目前系統中所有程序的詳細資訊。
[root@localhost ~]# ps aux | more
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 193628 4636 ? Ss 00:14 0:06 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
root 2 0.0 0.0 0 0 ? S 00:14 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S 00:14 0:07 [ksoftirqd/0]
……
在詳細的程序資訊中可以看到,很多程序的TTY字段顯示為“?”,這表示該程序不是由使用者在某個終端啟動的,而是由系統核心所啟動。
對于那些由使用者執行指令所啟動的程序都是與終端相關的,當把終端關閉,該終端中的所有程序也都會自動關閉。這是Linux系統一個非常重要的特點,下面的兩個執行個體都是對這個特點的具體應用。
3. 程序的背景啟動
程序就是運作中的程式,我們隻要在Shell指令行下輸入并執行某條指令,就會啟動一個相應的程序。Linux系統中的程序有前台程序和背景程序之分,通常情況下我們執行指令所産生的程序都是前台程序,前台程序的一個重要特點是會占據目前終端,當程序沒有結束的時候,使用者不能在目前終端中再進行其它的操作。
比如我們執行“nc -l -p 8000”指令偵聽TCP8000端口(CentOS7中預設沒有安裝nc,如果已經配置好yum源,可以執行“yum install nc”指令安裝),這條指令執行之後将會一直處于運作狀态,如果使用者不按Ctrl+c鍵強制中止,該程序将一直占據目前終端。
如果在要執行的指令後面加上一個“&”符号,此時程序将轉到背景運作,其執行結果不在螢幕上顯示,該程序也不會占據目前終端,使用者仍可以繼續執行其它的操作。
比如,在背景執行nc指令偵聽TCP8000端口。
[root@localhost ~]# nc -l -p 8000 &
[1] 79878
當然也可以直接執行指令啟動一個前台程序,然後再通過按下Ctrl+z組合鍵,将該程序轉入到背景。隻不過通過這種方式轉入到背景的程序将處于停止狀态,需要再通過執行bg指令使其在背景繼續執行。
[root@localhost ~]# nc -l -p 8000
^Z
[1]+ 已停止 nc -l -p 8000
[root@localhost ~]# jobs -l
[1]+ 102964 停止 nc -l -p 8000
[root@localhost ~]# bg 1
[1]+ nc -l -p 8000 &
[root@localhost ~]# jobs -l
[1]+ 102964 運作中 nc -l -p 8000 &
無論是通過在指令後面加“&”符号在背景執行的程序,還是通過Ctrl+z組合鍵而轉往背景的程序,它們都與目前終端相關。如果将目前終端關閉,那麼這些在背景運作的程序也将全部關閉。這樣如果我們希望能夠通過nc指令在系統中始終監聽TCP8000端口,這就很難實作了。
因而如果希望某些程序能夠始終在背景運作,那麼可以通過nohup指令解除其與目前終端之間的關系。比如我們希望無論目前終端是否關閉,始終都在背景執行nc指令監聽本機的TCP6000端口。那麼可以執行下面的指令:
[root@localhost ~]# nohup nc -l -p 6000 &
[2] 103240
[root@localhost ~]# nohup: 忽略輸入并把輸出追加到"nohup.out"
指令執行之後,将目前終端關閉,然後再次打開一個新的終端,執行“ps aux | grep nc”指令查找nc指令所産生的程序,可以看到由“nc -l -p 6000”指令産生的程序所對應的終端已經變為了“?”,即由系統核心啟動,而不再與任何終端關聯。
[root@localhost ~]# ps aux | grep nc
……
root 103240 0.0 0.1 43512 1808 ? S 15:55 0:00 nc -l -p 6000
root 103304 0.0 0.0 112668 968 pts/0 R+ 15:57 0:00 grep --color=auto nc
這樣這條指令所産生的程序就成為了系統的背景程序,如果管理者不用kill指令強制終止的話,這個程序将一直運作下去。
4. 踢出系統中的可疑使用者
下面再通過一個執行個體進一步說明程序和終端之間的關系。
由于Linux是一個多使用者的作業系統,作為管理者就需要随時了解目前正在有哪些使用者在登入系統。通過執行who指令可以檢視目前正在登入系統的使用者以及其相關資訊。
[root@localhost ~]# who
root :0 2017-10-14 15:20 (:0)
root pts/0 2017-12-28 15:57 (192.168.80.1)
root tty2 2017-12-28 16:11
從who指令的執行結果可以發現,有3個使用者正在以root使用者的身份登入系統。其中第一行資訊沒有顯示終端,表明root使用者是在本地登入,由于是本地登入,因而未顯示IP位址。第二行資訊表明root使用者在遠端的僞終端pts/0上登入,并顯示了登入IP。第三行資訊表明root使用者在本地的虛拟終端tty2上登入,同樣不顯示IP位址。
下面我們在系統中建立一個名為hacker的賬号,并利用該賬号在某個終端上遠端登入。
建立賬号并設定密碼:
[root@localhost ~]# useradd hacker
[root@localhost ~]# echo "123" | passwd --stdin hacker
更改使用者 hacker 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。
[root@localhost ~]# who
root :0 2017-10-14 15:20 (:0)
hacker pts/1 2017-12-28 16:19 (192.168.80.20)
root pts/0 2017-12-28 15:57 (192.168.80.1)
root tty2 2017-12-28 16:11
[root@localhost ~]# ps aux | grep pts/1
hacker 103706 0.0 0.2 142916 2224 ? S 16:19 0:00 sshd: hacker@pts/1
hacker 103707 0.0 0.2 116168 2740 pts/1 Ss+ 16:19 0:00 -bash
root 103801 0.0 0.0 112664 972 pts/0 S+ 16:25 0:00 grep --color=auto pts/1
[root@localhost ~]# who
root :0 2017-10-14 15:20 (:0)
root pts/0 2017-12-28 15:57 (192.168.80.1)
root tty2 2017-12-28 16:11