進程管理與SELinux初探

每一個進程都會獲得一個PID,系統就是通過這個PID來判斷這個進程是否有權限進行工作的。在Linux下執行一個指令時,系統會將相關的權限、屬性、程序代碼與數據等加載到內存中,並給予這個單元一個進程標識符(PID),該指令可以進行的任務就與這個PID有關


當用bash提供的接口去執行另一個指令時,這個新的指令也會被觸發形成新的進程(所以也會獲得PID),這就是子進程,它父進程的PID是PPID(Parent PID)

Linux中進程之間的調用稱爲fork-and-exec流程,進程會通過父進程以複製(fork)的方式產生一個一模一樣的進程,然後被複製出來的進程再以exec的方式來執行實際要進行的進程,最終成爲一個子進程,流程如下:

1. 系統以fork的方式複製一個與父進程相同的暫存進程,這個進程與父進程唯一的差別就是PID不同,並且會增加一個PPID參數

2. 暫存進程開始以exec的方式加載實際要執行的進程,最終子進程的代碼就會變成這個要執行的進程的代碼



啓動在背景中一直運作的進程就是常駐內存的進程,他們通常提供一些系統功能以服務用戶,因此這些常駐進程就被稱爲服務(daemon)


在指令最後添加" &"可以將其放置到背景執行,終端接口同時可以進行其他工作,系統會顯示這個指令的job number和PID,當背景進程完成後會在終端接口顯示完成的消息。放入背景執行的工作必須是不能與用戶進行互動的(如vim),並且放入背景後不能用ctrl+c來終止。雖然一個指令被丟到背景中執行,但數據依舊會輸出到當前終端中而影響操作,所以最好將數據通過流傳送到一個檔案中(包括錯誤信息)

工作管理(job control)是用在bash環境下的,指登入系統取得bash shell後在單一終端機接口下同時進行多個任務的管理。所有被管理的任務都是當前bash的子進程,所以無法以job control的方式由tty1的環境去管理其他終端的bash。要進行job control有以下限制:

1. 這些工作所觸發的進程必須來自於自己shell的子進程(只管理自己的bash),即使是root也不能將別人bash下的job拿來執行

2. 前景:可以控制與下達指令的環境成爲前景

3. 背景:可以自行運作的工作,可使用bg/fg呼叫該工作。工作的狀態可以分爲暫停(stop)和運行中(running)

4. 背景中執行的進程不能等待terminal/shell的輸入


將當前工作暫停並放到背景中:ctrl+z

屏幕上會顯示這個工作的序號,有"+"則表示這是最近一個被放到背景中的工作,是使用fg指令默認會被取用的工作;同時會顯示這個工作的狀態,一般情況下使用ctrl+z放到背景中的工作都會處於暫停狀態(Stopped)


觀察當前背景工作的狀態:jobs

jobs [-lrs]

-l:除了job number和指令串外還列出PID

-r:僅列出正在背景中運行(running)的工作

-s:僅列出正在背景中暫停(stopped)的工作

有"+"代表使用fg指令時預設的取用工作


將背景工作拿到前景處理:fg

fg %jobnumber

"%"可以不加

啓動背景中暫停的工作:bg

bg %jobnumber


管理背景中的工作:kill

kill -signal [PID/%jobnumber]

kill -l

-l:列出目前kill能使用的signal有哪些,signal代表如何處理後面的工作,常用的有:

   -1:重新讀取參數的配置文件(類似重載reload)

   -2:等於ctrl+c

   -9:強制終止一個工作

   -15:以正常的方式終止工作

kill之後默認接PID,如果要接job number要加%


脫機管理

之前提到的“背景”是指在終端機模式下可以避免ctrl+c中斷的一個情景,並不是放到系統的背景去執行,所以工作管理的背景依舊和終端機有關。例如用遠程登陸聯到Linux主機,如果以"&"的方式將工作放到背景中,如果脫機則工作也會中斷。要解決這個問題可以使用at指令,或者nohup指令。nohup可以讓工作在脫機或系統註銷登陸後還可以繼續工作,但它不支持bash內建指令,所以指令必須是外部指令纔行

在終端機前景中工作:nohup [指令參數]

在終端機背景中工作:nohup [指令參數] &

例:nohup ./check.sh &

此時指令的輸出會被導向到~/nohup.out


ps:查看某個時間點的進程運作情況

ps aux:觀察系統所有的進程數據

ps -lA:也是觀察所有的進程數據,顯示的字段與ps -l相同,但包括了系統的所有程序

ps axjf:同時顯示進程樹狀態

-A:顯示所有進程,與-e效果相同

-a:不顯示與terminal有關的進程

-u:有效使用者(effective user)相關的進程

-Z:查閱進程的安全上下文(security context),參見SELinux部分

x:通常與a合用,可列出完整信息

輸出格式設置:

l:詳細的將PID信息列出

j:工作的格式(jobs format)

-f:做一個更爲完整的輸出

僅使用ps的話只會列出與當前用戶操作環境(bash)有關的進程,最上層的父進程將只是用戶的bash而不會延伸到init去。

使用ps -l所列出的各項的含義爲:

F:進程標識符(process flag),說明這個進程的總結權限,常見的有:"4"表示權限爲root;"1"表示此進程只能進行復制(fork)而沒有實際執行(exec)

S:代表進程的當前狀態

      R(Running):運行中

      S(Sleep):該進程正在睡眠狀態(idle),可以被喚醒(signal)

      D:不可被喚醒的睡眠狀態,通常可能在等待IO

      T:停止狀態(stop),可能是在工作控制(背景暫停)或除錯(traced)狀態

      Z(Zombie):殭屍狀態,程序已經終止但卻不法被移除內存

UID/PID/PPID:進程的擁有者/進程號/父進程號

C:CPU使用率,爲百分比

PRI/NI:Priority/Nice的縮寫,表示此進程被CPU執行的優先級,數值越小優先級越高

ADDR/SZ/WCHAN:均與內存有關。ADDR是kernel function,指出該進程在內存的哪個部分,如果是正在running的程序一般會顯示"-";SZ代表進程用掉了多少內存;WCHAN表示該進程是否在運行中,若是則顯示"-"

TTY:登入者的終端機位置

TIME:使用掉的CPU時間,注意是實際消耗的CPU運行時間,而不是系統時間

CMD:command,此進程的觸發指令


ps aux指令顯示的項目:

USER:進程所屬的使用者;

VSZ:該進程使用的虛擬內存(KB)

RSS:該進程使用的固定內存(KB)

TIME:該進程實際使用的CPU運行時間


殭屍進程通常的成因是進程已經執行完畢或應因故終止了,但該進程的父進程卻無法完整的將該進程結束,導致它一直存在於內存中。當某個進程的CMD後接<defunct>時,就代表該進程是殭屍進程。通常殭屍進程已經無法管控,直接交給init進程來處理;而init進程是系統第一支執行的進程,是所有進程的父進程,所以無法殺掉該進程,只能重啓


top:動態觀察進程

top [-d 數字]

top [-bnp]

-d:後接數字,表示每隔多少秒更新結果,預設是5秒

-b:以批次的方式執行top

-n:與-b搭配,表示需要進行幾次top結果輸出

-p:指定某個PID進行觀察

top執行過程中的指令:

?:顯示可輸入的指令

P:以CPU的使用率排序

M:以memory的使用排序

N:以PID排序

T:以使用的CPU累計時間(TIME+)排序

k:給某個PID一個信號(signal)

r:給某個PID新的nice值

q:離開top


top顯示的內容:

第一行:當前時間,已開機時間,登入系統的用戶人數,系統在1、5、15分中的平均負載(平均要同時運行幾個進程,如果大於1要注意)

第二行:當前所有進程的統計信息

第三行:CPU的整體負載,每個項目可用"?"查閱。特別注意%wa,它代表IO wait,IO通常會影響系統速度。如果是多核心設備可以按下"1"來切換不同的CPU負載

第四行與第五行:物理內存與虛擬內存的使用情況。如果swap被大量使用表明系統物理內存不足

第六行:輸入指令時顯示狀態的地方

top預設使用%CPU進行排序

例:將top信息進行兩次,將結果輸出到/tmp/top.txt

top -b -n 2 > /tmp/top.txt


pstree [-A/U] [-up]

-A:進程樹之間以ASCII字符連接

-U:進程樹之間以萬國碼字符連接,在某些終端下可能會有錯誤(預設)

-p:同時列出每個進程的PID

-u:同時列出每個進程所屬的用戶名

由pstree可以看到,所有進程都是由init進程產生的,它的PID是1。如果一個子進程掛點或是總是無法殺掉,則可以用pstree尋找到它的父進程


進程管理

進程之間的相互管理是通過信號(signal)去表明要進行什麼操作


常用的是1,9,15,要傳遞signal要使用kill或killall指令


kill -signal PID/%jobnumber

用進程號或job number向進程傳遞signal


killall [-iIe] [command name]

-i:interactive,互動模式,進行刪除會出現提示

-e:exact,表示與後接的command name要一致,但完整指令不能超過15個字符

-I:忽略指令名稱大小寫


Linux會給進程一個優先級(priority,PRI),PRI值越低代表優先級越高。PRI是由核心動態調整的,用戶無法直接改變PRI的值。如果想要調整進程的優先級可以改變nice值NI。一般PRI與NI的關係是PRI(new) = PRI(old) + NI,但新的PRI需要經過系統分析決定。NI可正可負。

1. NI的值可調整的範圍爲-20~19

2. root可以隨意調整自己或其他人的NI值,範圍爲-20 ~ 19

3. 一般用戶只能調整自己進程的NI值,且範圍僅爲0 ~ 19(避免一般用戶搶佔系統資源)

4. 一般使用者僅能將NI值調高,例如NI原值爲5,則未來僅能調整到大於5

可以將系統背景工作中不重要進程的NI值調高以更合理的分配系統資源


調整NI值的方法:

1. 一開始執行程序就立即給予一個特定的NI值:用nice指令

2. 調整某個已存在進程的NI值:用renice指令

top指令也可以調整NI值


nice [-n 數字] command

renice [數字] PID

修改父進程的NI值時,子進程的NI值也會被改變,NI值是在父進程到子進程傳遞的


free:觀察內存使用

free [-b/k/m/g] [-t]

-b:直接輸入free時顯示的單位是KB,一使用b,k,m,g來調整

-t:在輸出結果中顯示物理內存與swap的總量

即使系統未進行太多工作,物理內存也會被大量使用,這是正常的,因爲部分作爲buffer,部分作爲cache,也就是說系統在有效率的使用內存,目的是提高系統效能。而swap一般最好不要被使用,最好不要超過20%,否則表示物理內存不足,而且swap的效能比較差。


uname:查閱系統與核心相關的信息

-a:顯示所有的系統相關信息

-s:顯示系統核心名稱

-r:顯示系統和新版本

-m:顯示系統的硬件名

-p:顯示CPU的類型

-i:顯示硬件平臺


uptime:觀察系統啓動時間與工作負載(其實就是top的第一行)


netstat:追蹤網絡或插槽文件

netstat [-atunlp]

-a:將目前系統上所有的聯機、監聽、socket數據都列出來

-t:列出tcp網絡封包的數據

-u:列出udp網絡封包的數據

-n:使用端口號(port number)而非進程服務名稱來顯示

-l:列出目前正在網絡監聽(listen)的服務

-p:列出該網絡服務進程的PID

netstat現實的結果分爲兩個部分,上面是網絡的聯機部分,下面是Linux上的socket程序部分

網絡聯機情況的字段:

Proto:網絡的封包協議,主要是TCP或UDP封包

Recv-Q:由非用戶程序連接到此socket複製的總byte數

Send-Q:由非遠程主機傳送過來的acknowledge總byte數

Local Address:本地IP:port情況

Foreign Address:遠程主機的IP:port情況

State:聯機狀態,主要有建立(ESTABLISHED)和監聽(LISTEN)


Linux系統上的進程可以接受不同進程發來的信息,這就是Linux上的socket file。socket file可以溝通兩個進程之間的信息。netstat第二個部分socket部分字段:

Proto:一般是unix

RefCnt:連接到此socket的進程數

Flags:聯機的標識符

Type:socket存取的類型,主要有需要確認聯機的STREAM和不需要確認的DGRAM兩種

State:若爲CONNECTED則表示多個進程之間已經建立聯機

Path:連接到此socket相關的進程路徑或是相關數據的輸出路徑


dmesg:分析核心產生的信息

在系統開機時,核心會去偵測系統硬件,但過程會一閃而過。通過dmesg指令可以顯示核心偵測的信息。核心偵測的所有信息都會被記錄到內存中的保護區段,dmesg就是將這個區段的信息讀取出來


vmstat:偵測系統資源變化,可以偵測CPU/內存/磁盤輸入輸出狀態等

vmstat [-a] [延遲 [總偵測次數]] :CPU/內存等信息

-a:使用inactive/active取代buffer/cache的內存輸出信息

-f:開機到目前爲止系統複製(fork)的進程數

-s:將開機到目前爲止一些事件導致的內存變化情況列表說明

-S:後接單位,如K/M

-d:列出磁盤的讀寫總量統計表

-p:後接分割槽,顯示該分割槽的讀寫總量統計表

例:統計當前主機的CPU狀態,每秒一次,共三次:vmstat 1 3


各字段的含義:

procs:"r"表示等待運行的進程數,"b"表示不可被喚醒的進程數。這兩個項目越多表明系統越忙碌

memory:"swpd"表示虛擬內存的使用量,"free"表示未被使用的內存量,"buff"表示用作buffer的量,"cache"表示用於cache的量

swap:"si"表示從磁盤中取出的進程量,"so"表示由於內存不足而將沒用的程序寫入swap的量。如果si/so的值太大,表示內存中的數據常在磁盤和主存間傳遞,系統的效能會比較差

io(磁盤讀寫):"bi"表示從硬盤讀取的block數,"bo"表示寫入硬盤的block數,二者的值越高表示系統的IO越忙碌

system:"in"表示每秒的中斷數,"cs"表示每秒進行的時間切換次數,這兩個值越大表示系統與結構設備的溝通越頻繁

cpu:"us"表示執行非核心代碼的時間,"sy"表示執行核心代碼的時間,"id"表示idle的時間,"wa"表示等待IO花費的時間,"st"表示被虛擬機盜用的時間

當系統非常忙碌時,可以用vmstat查看哪部分的資源被使用的最爲頻繁


具有SUID權限的進程被觸發後,會取得一個新的進程和PID,該PID產生時通過SUID來給予該PID特殊的權限設定


/proc目錄

進程都是在內存中的,而內存中的數據會被寫入到/proc目錄下,基本上當前主機上的各個進程的PID都是以目錄的形態存在於/proc中。在每個進程的對應目錄下,會有一些相關檔案,其中比較重要的是"cmdline"中包含進程被啓動的指令串,"environ"中則包括了這個進程環境變量的內容。針對整個Linux系統的參數就在/proc目錄下,相關內容,具體內容如下:



fuser:通過檔案或文件系統找出正在使用該檔案的進程

fuser [-umv] [-k [i] [-signal]] file/directory

-u:除了進程的PID外還列出該進程的擁有者

-m:後接的檔名會提到該文件系統的最頂層,對umount不成功很有效

-v:列出每個檔案與進程還有指令的完整相關性

-k:找出使用該檔案/目錄的PID,並試圖以SIGKILL這個信號給該進程

-i:必須與-k合用,在結束進程之前會進行詢問

-signal:例如-1~15,若不加則預設爲SIGKILL (-9)

fuser所列出項目中ACCESS的含義:

c:此進程在當前的目錄下(非子目錄)

e:可被觸發爲執行狀態

f:是一個被開啓的檔案

r:代表頂層目錄(/)

F:該檔案已被開啓,不過在等待迴應中

m:可能爲分享的動態函數庫


lsof:列出被進程開啓的檔案文件名

lsof [-aUu] [+d]

-a:多項數據需要同時成立才能被列出

-U:僅列出Unix-like系統的socket文件類型

-u:後接username,列出該用戶相關進程開啓的檔案

+d:後接目錄,找出某個目錄下已被開啓的檔案


pidof:找出某支正在執行的程序的PID

pidof [-sx] 進程名

-s:僅列出一個PID

-x:同時列出該進程可能的PPID哪個進程的PID



SELinux(Security Enhanced Linux)

之前提到的文件系統存取方式稱爲"自主式訪問控制(Discretionary Access Control,DAC)",基本上就是依靠進程的擁有者與檔案資源的rwx權限來決定有無存取能力。它無法限制root的權限,並且一旦某個目錄的權限被設爲777,該目錄就可以被任何人任意存取。SELinux引入了"委任式訪問控制(Mandatory Access Control,MAC)",它可以針對特定的進程與特定的檔案進行權限管理,這樣權限控制的對象就變成了進程而不是用戶。並且,一個進程也不能任意使用系統檔案資源,因爲每個檔案資源也有針對該進程設定的權限。

SELinux通過MAC方式來控制管理進程,控制的主體是進程,目標是該進程要處理的檔案資源

主體(Subject):SELinux的主要管理對象

目標(Object):主體進程能否存取的目標資源,一般是文件系統

政策(Policy):SELinux會根據某些服務來制定基本的存取政策,這些政策內還會有詳細的規則(rule)來指定不同的服務是否開放某些資源的存取

安全上下文(security context):主體能不能存取目標除了政策的規定之外,主體與目標的安全上下文必須一致才能順利存取,有點類似文件系統的rwx


主體進程必須通過SELinux的政策規定後,纔可以與目標資源的安全上下文進行比對,比對成功才能開始存取,並且最終能否存取目標還要看文件系統的rwx權限設定


安全上下文

安全上下文存在於主體進程與目標資源檔案中。由於進程在內存中,所以安全上下文可以存入;對檔案來說,安全上下文是存放在檔案的inode內的,因此主體進程想要讀取目標檔案的資源時需要讀取inode,然後才能比對安全上下文和rwx等權限設定是否正確。安全上下文可以通過【ls -Z】進行觀察,主要有三個字段:

identify:role:type

1. 身份識別(identify)

相當於賬號方面的身份識別,主要的身份識別有以下三種類型:

root:表示root的賬號身份

system_u:表示系統方面的識別

user_u:代表一般使用者賬號的相關身份

2. 角色(role)

通過角色字段,可以知道這個數據屬於進程、檔案資源還是代表使用者。一般有:

object_r:代表檔案或者目錄等檔案資源

system_r:代表進程,不過一般使用者也會被指定爲system_r

3. 類型(type)

這個字段比較重要,一個主體進程能不能讀取檔案資源就與這個字段有關,它在進程和檔案上的定義不一樣,分別是:

domain:在主體程序(subject)上稱爲領域(domain)

type:在檔案資源(object)上稱爲類型(type)


主體進程取得的domain和目標檔案資源type的相互關係:

1. 首先,觸發一個可執行的目標檔案

2. 該檔案的類型會讓這個檔案所產生的主體進程(subject)具有一個領域(domain),政策(policy)針對這個領域已經指定了許多規則(rule),包括這個領域可以讀取的目標資源類型

3. 如果進程的domain被設定爲可以讀取某個類型(type)的目標檔案(object),並且rwx符合規範則可以進行文件讀取


目前SELinux支持三種模式:

enforcing:強制模式,代表SELinux運行中,並且已經開始限制domain/type了

permissive:寬容模式,代表SELinux運行中,不過只會有警告信息,不會實際限制domain/type的存取。這種模式可以用來進行debug

disabled:關閉,SELinux沒有運行

getenforce可以查詢當前SELinux的狀態


sestatus:查詢SELinux的policy

sestatus [-vb]

-v:檢查位於/etc/sestatus.conf內檔案與進程的安全上下文內容

-b:將目前policy的bool值列出,即某些規則(rule)是否啓動


SELinux的配置文件是/etc/selinux/config

要啓動SELinux,需要將上述檔案中的SELINUX一項設爲enforcing或permissive;然後到/boot/grub/menu.lst檔案中"kernel"字段後的"selinux=0"刪除,因爲它會使kernel自動忽略/etc/selinux/config的設定值而跳過SELinux加載

通過指令setenforce [0/1]可以在enforcing(1)和permissive(0)之間切換(不能在disabled模式下進行)


chcon:修改SELinux安全上下文

chcon [-R] [-t type] [-u user] [-r role] 檔案

chcon [-R] --reference=範例文件 檔案

-R:遞歸修改子目錄

-t:後接安全上下文的類型

-u:後接身份識別,如system_u

-r:後接角色,如system_r

--reference=範例文件:以某個檔案作爲範例來修改後接的檔案


restorecon:重置安全上下文

restorecon [-Rv] 檔案或目錄

-R:連同子目錄一起修改

-v:將過程顯示到屏幕上


SELinux所需的服務

setroubleshoot:錯誤信息寫入/var/log/messages

該服務會將SELinux的錯誤信息與修正方法記錄到/var/log/messages中

啓動:chkconfig setroubleshoot on

列出執行等級:chkconfig --list setroubleshoot

只要3、5是on即可(on表示開機自啓動)


auditd:詳細資料寫入/var/log/audit/audit.log

該服務會將SELinux發生的錯誤信息寫入/var/log/audit/audit.log中,而且不僅僅會記錄錯誤信息,啓動和查看方法與setroubleshoot相同(把名字換成auditd)即可

audit2why:檢查錯誤信息的彙報

audit2why < /var/log/audit/audit.log

信息中AVC是access vector cache的縮寫,目的是記錄所有與SELinux有關的存取統計資料


seinfo:政策查詢

seinfo [-Atrub]

-A:列出SELinux的狀態、規則布爾值、身份識別、角色、類別等所有信息

-t:列出SELinux的所有類別(type)種類

-r:列出SELinux的所有角色(role)種類

-u:列出SELinux的所有身份是被(user)種類

-b:列出所有規則的種類(布爾值)


sesearch:查詢詳細規則

sesearch [-a] [-s  主體類別] [-t 目標類別] [-b 布爾值]

-a:列出該類別或布爾值的所有相關信息

-t:後接類別

-b:後接布爾值的規則

結果有三個字段:allow;主體進程安全上下文類別;目標檔案安全上下文類別


實際規範規則的是布爾值的項目,查詢布爾值:

getsebool [-a] [布爾值條款]

-a:列出目前系統上的所有布爾值條款

關閉布爾值:

setsebool [-P] 布爾值=0/1

-P:將設定寫入配置文件,一定要加


查詢默、修改認安全上下文:

semanage {login/user/port/interface/fcontext/translation} -l

semanage fcontext -{a/d/m} [-first] file_spec

fcontext:主要用在安全上下文方面,-l是查詢的意思

-a:增加,可以增加一些目錄的默認安全上下文類型設定

-m:修改

-d:刪除

例:給/srv/samba目錄增加新的安全上下文public_content_t

semanage fcontext -a -t public_content_t "/srv/samba(/.*)?"


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章