1. 程式人生 > >Linux系統的進程與終端管理

Linux系統的進程與終端管理

linux 進程 終端 nohup 踢出用戶

原文發表於“網絡安全和信息化”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:所有的身份驗證令牌已經成功更新。

然後在另外一臺Kali系統中(IP地址192.168.80.20)利用hacker賬號遠程登錄Linux服務器(IP地址192.168.80.146):
root@kali:~# ssh [email protected]
登錄成功之後,在Linux服務器中執行who命令查看當前登錄用戶。可以發現有一個可疑用戶正在IP地址為192.168.80.20的客戶端上遠程登錄,其所在終端編號為pts/1。

[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

下面我們將這個可疑用戶踢出系統。
首先需要根據可疑用戶所在終端查找出該終端所對應的進程,可以執行“ps aux | grep pts/1”命令。從命令的執行結果可以看到PID為103707的進程對應的終端為pts/1,而且該進程是由bash啟動的,這正是我們所要找的終端進程。

[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

然後通過kill命令強制終止該進程。
[root@localhost ~]# kill -9 103707
再次執行who命令,發現可疑用戶已經被踢出,而且該用戶啟動的所有進程也將自動關閉(通過nohup命令轉為系統後臺進程的除外)。

[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

Linux系統的進程與終端管理