1. 程式人生 > >18.系統進程和性能管理,計劃任務

18.系統進程和性能管理,計劃任務

當前時間 問題 sigstop fresh 希望 proc remove 知識 由於

進程概念
  1. 內核功用:進程管理、文件系統、網絡功能、內存管理、驅動程序、 安全功能等
  2. Process: 運行中的程序的一個副本,是被載入內存的一個指令集合
    進程ID(Process ID,PID)號碼被用來標記各個進程
    UID、 GID、和SELinux語境決定對文件系統的存取和訪問權限
    通常從執行進程的用戶來繼承
    它存在生命周期
    • task struct:Linux內核存儲進程信息的數據結構格式
    • task list:多個任務的的task struct組成的鏈表
  3. 進程創建:
    init:第一個進程
    進程:都由其父進程創建,父子關系,CoW,fork(), clone()

註意:

  1. 進程和不是程序,它是程序加載到內存中之後進行運行的各種指令操作的集合
  2. 程序運行時先將它加載到內核空間內存中,然後再將它分配到用戶空間內存中中,此時相當於系統分配給它一個獨立的內存空間。這時候它便成為了進程,並且和其他的進程相互隔離。它認為自己獨占了整個內存空間(虛擬出來的內存,並非真實的內存空間),並在此基礎上進行操作。實際上它占用的只是系統給它分配的一小塊內存空間而已。
  3. 進程運行時會隨機分配一個進程編號,運行結束之後會被會被回收。它運行時就相當於一個資源的集合,有自己的獨立的內存,能讀取數據進去,有自己的二進制執行程序命令,包括很多縣城等等。
  4. 進程內部真正執行操作計算的是線程,一個線程就是各種指令的集合。一個進程內至少有一個線程,可以有多個。
  5. 進程的生命周期有長期的(後臺進程),有一次性短期運行的(前臺進程)。比如說開機就開始運行的init進程,還有cat ls等程序的進程。
  6. task struct : 一個數據結構,包含了進程的各種元數據。
  7. 創建子進程如果用clone()函數,就會產生CoW(寫時復制)方式,類似邏輯卷中的快照:只有子進程中對數據進行修改了,才會重新創建一個不同的數據存放於子進程中。而數據並未更改時它和父進程指向同一個數據,共用此數據。(最開始學習中的小括號開啟子進程,小括號內局部變量如果不賦值,仍然和父進程的變量內容一樣就是這個原因)
  8. 協程就是多個命令的集合代碼塊(類似函數),多個協程組成一個線程。進程中線程的執行順序的優先級是由操作系統內核來調度的,而CPU在同一時間只能運行一個線程。我們人看到進程的執行感覺它是同時執行的,其實它只是利用CPU的時間頻率分成了多個時間段,然後一個時間段執行一個線程,由內核調度,不論是否完成這個線程,只要時間段一到,它就會切換到另一個線程進行運行,保存當前線程的狀態,這也就是所謂的上下文切換(註意,線程切換可以是不同進程的線程,也就相當於切換了不同的進程)。因為CPU頻率極快,因此我們看起來它貌似是同步執行了多個進程。
  9. 上下文切換會造成CPU內的當前線程(或進程)緩存數據(L1,L2,L3)失效,相比於CPU的運算時間,這個代價非常巨大,因此要盡量避免上下文切換進行優化。

進程,線程和協程

技術分享圖片

進程相關概念

  • Page Frame: 頁框,用存儲頁面數據,存儲Page 4k (也就是進程使用的內存空間,類似磁盤的塊block)
  • 物理地址空間和線性地址空間:物理上的實際內存和應用程序使用時認為的虛擬內存(相當於偏移地址)
  • MMU:Memory Management Unit 負責轉換線性和物理地址,CPU內的內存管理單元
  • TLB:Translation Lookaside Buffer 翻譯後備緩沖器,用於保存虛擬地址和物理地址映射關系的緩存
  • LRU:Least Recently Used :內存保存數據的算法,被叫做近期最少使用算法,用於釋放內存,它的工作原理就是把最新使用的數據存放到內存空間靠前的位置。
    比如說一個數據存入內存,如果內存中已經存在此數據,則把它的位置提前到內存空間起始位置,如果沒有,則存入,並把內存空間終止位置保存的的數據給丟棄(類似堆棧)。

用戶和內核空間

技術分享圖片

進程的基本狀態和轉換

技術分享圖片

進程的基本狀態

  1. 創建狀態:進程在創建時需要申請一個空白PCB(process control block進程控制塊),向其中填寫控制和管理進程的信息,完成資源分配。如果創建工作無法完成,比如資源無法滿足,就無法被調度運行,把此時進程所處狀態稱為創建狀態
  2. 就緒狀態:進程已準備好,已分配到所需資源,只要分配到CPU就能夠立即運行
  3. 執行狀態:進程處於就緒狀態被調度後,進程進入執行狀態
  4. 阻塞狀態:正在執行的進程由於某些事件(I/O請求,申請緩存區失敗)而暫時無法運行,進程受到阻塞。在滿足請求時進入就緒狀態等待系統調用
  5. 終止狀態:進程結束,或出現錯誤,或被系統終止,進入終止狀態。無法再執行

狀態之間轉換情況

  1. 運行——>就緒:1,主要是進程占用CPU的時間過長,而系統分配給該進程占用CPU的時間是有限的;2,在采用搶先式優先級調度算法的系統中,當有更高優先級的進程要運行時,該進程就被迫讓出CPU,該進程便由執行狀態轉變為就緒狀態
  2. 就緒——>運行:運行的進程的時間片用完,調度就轉到就緒隊列中選擇合適的進程分配CPU
  3. 運行——>阻塞:正在執行的進程因發生某等待事件而無法執行,則進程由執行狀態變為阻塞狀態,如發生了I/O請求
  4. 阻塞——>就緒:進程所等待的事件已經發生,就進入就緒隊列
    • 以下兩種狀態是不可能發生的:
  5. 阻塞——>運行:即使給阻塞進程分配CPU,也無法執行,操作系統在進行調
    度時不會從阻塞隊列進行挑選,而是從就緒隊列中選取
  6. 就緒——>阻塞:就緒態根本就沒有執行,談不上進入阻塞態

IPC進程間通信

IPC: Inter Process Communication

同一主機:

pipe 管道
socket 套接字文件
signal 信號
shm shared memory
semaphore 信號量,一種計數器

不同主機:

socket IP和端口號
RPC remote procedure call
MQ 消息隊列,如:Kafka,RabbitMQ,ActiveMQ

  • 單一主機通訊用socket文件,全雙工;跨網絡通訊用socket套接字協議。

進程優先級

技術分享圖片

技術分享圖片

  • 系統優先級:數字越小,優先級越高
    0-139:各有140個運行隊列和過期隊列
    實時優先級: 99-0 值最大優先級最高
    nice值:-20到19,對應系統優先級100-139
  • Big O:時間復雜度,用時和規模的關系
    O(1), O(logn), O(n)線性, O(n^2)拋物線, O(2^n)

O(1)比較優先級大小的方式:

  1. 通過140個編號的優先級隊列以及140個過時優先級隊列,將優先級編號相同的進程放在對應的優先級棧中(一個優先級棧可以放多個進程,從左往右執行),然後從最小值(最高優先級)的隊列開始執行。
  2. 當時間片到而此運行隊列中的正在執行的進程沒有執行完畢時,便會保存當前進程狀態並將此進程放入相同優先級編號過期隊列中,然後繼續執行當前優先級隊列中的剩余進程(一個進程在時間片內執行完了就釋放,沒有執行完同樣放入過期優先級隊列中),直到此隊列的所有進程全部執行一遍,將此隊列清空
  3. 此時查看此隊列相同編號的過時優先級隊列,裏面如果有進程,則將此隊列的與過期優先級隊列互換身份,此運行隊列變成過期優先級隊列,而過期優先級隊列變成正在執行的運行隊列。然後重復2中步驟直到此隊列的所有進程全部執行完畢並且釋放
  4. 接下來就是執行下一個最高優先級隊列裏面的進程了,重復1-4步驟。

進程狀態

Linux內核:搶占式多任務

  • 進程類型:
    守護進程: daemon,在系統引導過程中啟動的進程,和終端無關進程
    前臺進程:跟終端相關,通過終端啟動的進程
    註意:兩者可相互轉化
  • 進程狀態:
    運行態:running
    就緒態:ready
    睡眠態:
    可中斷:interruptable :可中斷睡眠狀態是系統中進程最多的狀態
    不可中斷:uninterruptable
    停止態:stopped,暫停於內存,但不會被調度,除非手動啟動
    僵死態:zombie,結束進程,父進程結束前,子進程不關閉
  • 註意僵死態的進程已經結束了,但是仍然占用部分資源,kill命令無法再次關閉它,最好的方法就是殺掉父進程或者重啟系統。

系統管理工具

進程的分類:

CPU-Bound:CPU密集型,非交互 :比如編譯
IO-Bound:IO密集型,交互 :網絡吞吐,磁盤讀寫

Linux系統狀態的查看及管理工具:pstree, ps, pidof, pgrep, top, htop,glance, pmap, vmstat, dstat, kill, pkill, job, bg, fg, nohup

  • pstree命令:
    pstree display a tree of processes

查看進程進程ps

  • ps: process state
    ps report a snapshot of the current processes :查看ps命令執行時的進程快照
    Linux系統各進程的相關信息均保存在/proc/PID目錄下的各文件中
  • ps [OPTION]...
    支持三種選項:
    UNIX選項 如-A -e
    BSD選項 如a
    GNU選項 如--help
  • 選項:不加選項時,默認顯示鏈接到當前終端中的進程,無法顯示別的終端中進程
    a 選項包括鏈接到所有終端中的進程
    x 選項包括不鏈接終端的進程
    u 選項顯示進程所有者的信息
    f 選項顯示進程樹,相當於 --forest
    k|--sort 屬性 對屬性排序,屬性前加- 表示倒序 : 比如 ps aux k -%cpu ,註意後面的關鍵字要小寫不能大寫
    o 屬性… 選項顯示定制的信息 pid、 cmd、 %cpu、 %mem
    L 顯示支持的屬性列表

短格式(unix)特有選項

-C cmdlist 指定命令,多個命令用逗號,分隔 :也可以查看腳本,但要註意用 bash XXX.sh 方式運行的腳本無法查看, 同時如果腳本中沒有 #!/bin/bash 就算是直接運行的腳本也無法查看了。
-L 顯示線程 : pstree中花括號內就是線程,如果沒有花括號代表進程只有一個線程(此命令就會顯示進程了)
-e: 顯示所有進程,相當於-A
-f: 顯示完整格式程序信息
-F: 顯示更完整格式的進程信息
-H: 以進程層級格式顯示進程相關信息
-u userlist 指定有效的用戶ID或名稱
-U userlist 指定真正的用戶ID或名稱
-g gid或groupname 指定有效的gid或組名稱
-G gid或groupname 指定真正的gid或組名稱
-p pid 顯示指pid的進程
--ppid pid 顯示屬於pid的子進程
-M 顯示SELinux信息,相當於Z

  • 註意:有效用戶和真正用戶區別,真正用戶是指執行此進程的用戶realuser,而有效用戶代表此進程執行的的權限用戶,比如普通用戶執行passwd命令,真正用戶為普通用戶但有效用戶為root。(組類似)
    ps axo pid,cmd,user,ruser,euser ,其中 user和euser 相同意義,代表有效權限用戶 ,ruser代表真正執行用戶

ps 輸出屬性

VSZ: Virtual memory SiZe,虛擬內存集,線性內存

  • 進程向操作系統申請的內存,它的數值可以很大,但並非全部都使用,是個虛擬內存,按照進程自己定義的地址方式來尋址使用
    RSS: ReSident Size, 常駐內存集
  • 內核真正分配的內存大小,常駐內存
    STAT:進程狀態
    R:running
    S: interruptable sleeping
    D: uninterruptable sleeping
    T: stopped
    Z: zombie
    +: 前臺進程
    l: 多線程進程
    L:內存分頁並帶鎖
    N:低優先級進程
    \<\: 高優先級進程
    s: session leader,會話(子進程)發起者
    START:進程啟動的時間,和date相關
    TIME:此進程啟動後運行所占的時間片累計總時間

PS中優先級類別

ni(或者nice): nice值
pri: priority 優先級
psr: processor CPU編號
rtprio: 實時優先級

  • 附加知識:renice -n -10(優先級-20~19) 8814(PID),修改進程nice優先級
  • nice -n -5 ping 1.1.1.1 :直接指定命令的nice優先級,(默認為0改為-5)
  • 附加知識:chrt 修改實時優先級,不過一般不調整它,它是系統自動分配設置的,一般只修改nice用戶級別的優先級
  • 註意: pri優先級應該是和前面圖中系統優先級剛好相反;不過有一個特例就是當realtime優先級為0時,它也為0,而不是40,其他的都還符合。
    示例:
    ps axo pid,cmd,psr,ni,pri,rtprio
    常用組合:
    aux
    -ef
    -eFH
    -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,comm
    axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm

示例:

  1. 查詢你擁有的所有進程
    ps -x
  2. 顯示指定用戶名(RUID)或用戶ID的進程
    ps -fU apache
    ps -fU 48
  3. 顯示指定用戶名(EUID)或用戶ID的進程
    ps -fu wang
    ps -fu 1000
  4. 查看以root用戶權限(實際和有效ID)運行的每個進程
    ps -U root -u root
  5. 列出某個組擁有的所有進程(實際組ID:RGID或名稱)
    ps -fG nginx
  6. 列出有效組名稱(或會話)所擁有的所有進程
    ps -fg mysql
    ps -fg 27
  7. 顯示指定的進程ID對應的進程
    ps -fp 1234
  8. 以父進程ID來顯示其下所有的進程,如顯示父進程為1234的所有進程
    ps -f --ppid 1234
  9. 顯示指定PID的多個進程
    ps -fp 1204,1239,1263
  10. 要按tty顯示所屬進程
    ps -ft pts/0
  11. 以進程樹顯示系統中的進程如何相互鏈接
    ps -e --forest
  12. 以進程樹顯示指定的進程
    ps -f --forest -C sshd
    ps -ef --forest | grep -v grep | grep sshd
  13. 要顯示一個進程的所有線程,將顯示LWP(輕量級進程)以及NLWP(輕量級進程數)列
    ps -fL -C nginx
  14. 要列出所有格式說明符
    ps L
  15. 查看進程的PID,PPID,用戶名和命令
    ps -eo pid,ppid,user,cmd
  16. 自定義格式顯示文件系統組,ni值開始時間和進程的時間
    ps -p 1234 -o pid,ppid,fgroup,ni,lstart,etime
  17. 使用其PID查找進程名稱:
    ps -p 1244 -o comm=
  18. 要以其名稱選擇特定進程,顯示其所有子進程
    ps -C sshd,bash
  19. 查找指定進程名所有的所屬PID,在編寫需要從std輸出或文件讀取PID的腳本時這個參數很有用
    ps -C httpd,sshd -o pid=
  20. 檢查一個進程的執行時間
    ps -eo comm,etime,user | grep nginx
  21. 查找占用最多內存和CPU的進程
    ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head
    ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%cpu | head
  22. 顯示安全信息
    ps -eM
    ps --context
  23. 使用以下命令以用戶定義的格式顯示安全信息
    ps -eo euser,ruser,suser,fuser,f,comm,label
  24. 使用watch實用程序執行重復的輸出以實現對就程進行實時的監視,如下面的命令顯示每秒鐘的監視
    watch -n 1 ‘ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head‘

進程優先級

  • 進程優先級調整
    靜態優先級:100-139
    進程默認啟動時的nice值為0,優先級為120
    只有根用戶才能降低nice值(提高優先性)
  • nice命令
    nice [OPTION] [COMMAND [ARG]...]
  • renice命令
    renice [-n] priority pid...
  • 查看
    ps axo pid,comm,ni

搜索進程

  1. 最靈活方式:ps 選項 | 其它命令
  2. 按預定義的模式:pgrep
    pgrep [options] pattern
    -u uid: effective user,生效者
    -U uid: real user,真正發起運行命令者
    -t terminal: 與指定終端相關的進程
    -l: 顯示進程名
    -a: 顯示完整格式的進程名
    -P pid: 顯示指定進程的子進程
    • 更多詳細內容查看幫助即可
  3. 按確切的程序名稱:/sbin/pidof
    pidof bash
    • 註意它和lsof區別,lsof跟的是被打開的文件(或者程序,因為程序也是文件),pidof跟的就是進程名(程序如果沒運行不是進程)
      例子:
pgrep -lU zhang
pgrep -aU zhang
pgrep -P 1
pgrep -at pts/1
pgrep -f sshd

poidof bash

Pidof更多用法

pidof 進程名 :
通過查看上面命令的$? 值可以判斷進程是否停止運行了,因此就可以編寫腳本監測必須運行的進程,一旦發現停止立馬重新啟動(配合計劃任務使用極佳,當然也可以用killall 0 的方式也可)

例如:如果ping命令沒有執行,則ping 127.0.0.1,如果ping命令已經執行(不管ping的IP地址是什麽),則不執行ping 127.0.0.1

pidof ping &> /dev/null || ping 127.0.0.1

系統工具

  1. /proc/uptime 包括兩個值,單位 s秒
    系統啟動時長,空閑進程的總時長(按總的CPU核心數計算)
  2. uptime 和 w
    顯示當前時間,系統已啟動的時間、當前上線人數,系統平均負載(當前時間往前1、 5、 10分鐘的平均負載,一般不會超過1)
  3. 系統平均負載:
    指在特定時間間隔內運行隊列中的平均進程數
    • 通常每個CPU內核的當前活動進程數不大於3,那麽系統的性能良好。 如果每個CPU內核的任務數大於5,那麽此主機的性能有嚴重問題
    • 如果linux主機是1個雙核CPU,當Load Average 為6的時候說明機器已經被充分使用

進程管理工具

top:有許多內置命令

  • 排序:
    P:以占據的CPU百分比,%CPU
    M:占據內存百分比,%MEM
    T:累積占據CPU時長,TIME+
  • 首部信息顯示:
    uptime信息:l命令
    tasks及cpu信息:t命令
    cpu分別顯示:1 (數字)

memory信息:m命令
退出命令:q
修改刷新時間間隔:s
終止指定進程:k
保存文件:W

  • 欄位信息簡介:
    us:用戶空間
    sy:內核空間
    ni:調整nice時間
    id:空閑
    wa:等待IO時間
    hi:硬中斷
    si:軟中斷(模式切換)
    st:虛擬機偷走的時間(虛擬化技術不成熟時期,不知道CPU的時間片執行了什麽進程)

  • 選項:
    -d # 指定刷新時間間隔,默認為3秒
    -b 全部顯示所有進程
    -n # 刷新多少次後退出
    -H 線程模式,示例:top -H -p `pidof mysqld`

htop命令:EPEL源

  • 選項:
    -d #: 指定延遲時間;
    -u UserName: 僅顯示指定用戶的進程
    -s COLUME: 以指定字段進行排序

  • 子命令:
    s:跟蹤選定進程的系統調用
    l:顯示選定進程打開的文件列表
    a:將選定的進程綁定至某指定CPU核心
    t:顯示進程樹

內存空間

內存空間使用狀態:free [OPTION]

-b 以字節為單位
-m 以MB為單位
-g 以GB為單位
-h 易讀格式
-o 不顯示-/+buffers/cache行
-t 顯示RAM + swap的總和
-s n 刷新間隔為n秒
-c n 刷新n次後即退出

註意bufer和cache區別

  1. 簡單來說一個註重寫一個註重讀,不過後期因為有相同的部分它倆區別越來越小
  2. 註意磁盤掛載的時候有選項可直接寫入硬盤 mount -o sync ,同時TCP協議中報頭數據psh位置也是表示內存是否立即取走。

vmstat命令:虛擬內存信息

vmstat [options] [delay [count]]
vmstat 2 5

  • procs:
    r:可運行(正運行或等待運行)進程的個數,和核心數有關
    b:處於不可中斷睡眠態的進程個數(被阻塞的隊列的長度),比如正在讀取磁盤文件的進程(IO接口速度慢,需要耗費時間)
  • memory:
    swpd: 交換內存的使用總量
    free:空閑物理內存總量
    buffer:用於buffer的內存總量
    cache:用於cache的內存總量
  • swap:(註意是相對於內存的進和出來說的,磁盤進出下同)
    si:從磁盤交換進內存的數據速率(kb/s)
    so:從內存交換至磁盤的數據速率(kb/s)
    -io:
    bi:從塊設備讀入數據到系統的速率(kb/s)
    bo: 保存數據至塊設備的速率
dd if=/dev/zero of=/dev/null bs=2G :則swap中 so先漲,然後si再漲
dd if=/dev/sda of=/dev/null  :則io中的bi 漲 ,bo不變
dd if=/dev/zero of=/dev/sda1/bigfile :則io中的bi不變 ,bo漲
  • system:
    in: interrupts 中斷速率,包括時鐘
    cs: context switch 進程切換速率
  • cpu:
    us:Time spent running non-kernel code
    sy: Time spent running kernel code
    id: Time spent idle. Linux 2.5.41前,包括IO-wait time.
    wa: Time spent waiting for IO. 2.5.41前,包括in idle.
    st: Time stolen from a virtual machine. 2.6.11前, unknown.
  • 選項:
    -s: 顯示內存的統計數據

系統監控工具

iostat:統計CPU和設備IO信息

示例:iostat 1 10

iftop:顯示帶寬使用情況,EPEL源

示例:iftop -n -i eth1

pmap命令:進程對應的內存映射(占用了哪些內存空間,地址從哪到哪,以及一些調用的庫函數)

pmap [options] pid [...]
-x: 顯示詳細格式的信息
示例:pmap 1

  • 另外一種實現
    cat /proc/PID/maps

用pmap來判斷內存問題,看某個程序的內存占用是否一直增長判斷它內存泄露

  • 內存泄露:進程執行完畢不釋放所占的內存空間
  • 內存溢出:進程申請執行時所用的內存空間不夠,直接霸占更多的內存空間進行使用(可能影響其他進程,如果多霸占的內存空間正好被其他進程使用中)

glances命令:EPEL源

glances [-bdehmnrsvyz1] [-B bind] [-c server] [-C conffile] [-p port] [-P password] [--password] [-t refresh] [-f file] [-o output]

  • 內建命令:
    a Sort processes automatically
    c Sort processes by CPU%
    m Sort processes by MEM%
    p Sort processes by name
    i Sort processes by I/O rate
    d Show/hide disk I/O stats
    f Show/hide file system stats
    n Show/hide network stats
    s Show/hide sensors stats
    y Show/hide hddtemp stats
    l Show/hide logs
    b Bytes or bits for network I/O
    w Delete warning logs
    x Delete warning and critical logs
    1 Global CPU or per-CPU stats
    h Show/hide this help screen
    t View network I/O as combination
    u View cumulative network I/O
    q Quit (Esc and Ctrl-C also work)

  • 常用選項:
    -b: 以Byte為單位顯示網卡數據速率
    -d: 關閉磁盤I/O模塊
    -f /path/to/somefile: 設定輸入文件位置
    -o {HTML|CSV}:輸出格式
    -m: 禁用mount模塊
    -n: 禁用網絡模塊
    -t #: 延遲時間間隔
    -1:每個CPU的相關數據單獨顯示

C/S模式下運行glances命令

  • 服務器模式:
    glances -s -B IPADDR
    IPADDR: 指明監聽的本機哪個地址
  • 客戶端模式:
    glances -c IPADDR
    IPADDR:要連入的服務器端地址
  • 註意兩個主機上都要裝有glances工具,並且版本要一致(6和6,7和7),然後開啟服務器的監聽功能之後,客戶機就可以隨時連接監聽服務器端了。

dstat命令:系統資源統計,代替vmstat,iostat

dstat [-afv] [options..] [delay [count]]

-c 顯示cpu相關信息
-C #,#,...,total
-d 顯示disk相關信息
-D total,sda,sdb,...
-g 顯示page相關統計數據
-m 顯示memory相關統計數據
-n 顯示network相關統計數據
-p 顯示process相關統計數據
-r 顯示io請求相關的統計數據
-s 顯示swapped相關的統計數據
--tcp
--udp
--unix
--raw
--socket
--ipc
--top-cpu:顯示最占用CPU的進程
--top-io: 顯示最占用io的進程
--top-mem: 顯示最占用內存的進程
--top-latency: 顯示延遲最大的進程

iotop

iotop命令是一個用來監視磁盤I/O使用狀況的top類工具iotop具有與top相似的UI,其中包括PID、用戶、I/O、進程等相關信息,可查看每個進程是如何使用IO

  • iotop輸出
    第一行:Read和Write速率總計
    第二行:實際的Read和Write速率
    第三行:參數如下:
    線程ID(按p切換為進程ID)
    優先級
    用戶
    磁盤讀速率
    磁盤寫速率
    swap交換百分比
    IO等待所占的百分比
    線程/進程命令

iotop常用參數

-o, --only只顯示正在產生I/O的進程或線程,除了傳參,可以在運行過程中按o生效
-b, --batch非交互模式,一般用來記錄日誌
-n NUM, --iter=NUM設置監測的次數,默認無限。在非交互模式下很有用
-d SEC, --delay=SEC設置每次監測的間隔,默認1秒,接受非×××數據例如1.1
-p PID, --pid=PID指定監測的進程/線程
-u USER, --user=USER指定監測某個用戶產生的I/O
-P, --processes僅顯示進程,默認iotop顯示所有線程
-a, --accumulated顯示累積的I/O,而不是帶寬
-k, --kilobytes使用kB單位,而不是對人友好的單位。在非交互模式下,腳本編程有用
-t, --time 加上時間戳,非交互非模式
-q, --quiet 禁止頭幾行,非交互模式,有三種指定方式
-q 只在第一次監測時顯示列名
-qq 永遠不顯示列名
-qqq 永遠不顯示I/O匯總

交互按鍵

left和right方向鍵:改變排序
r:反向排序
o:切換至選項--only
p:切換至--processes選項
a:切換至--accumulated選項
q:退出
i:改變線程的優先級

nload 查看網絡實時吞吐量

  • nload是一個實時監控網絡流量和帶寬使用情況,以數值和動態圖展示進出的流量情況
  • 安裝:yum -y install nload (EPEL源)
  • 界面操作
    上下方向鍵、左右方向鍵、 enter鍵或者tab鍵都就可以切換查看多個網卡的流量情況
    按 F2 顯示選項窗口
    按 q 或者 Ctrl+C 退出 nload

  • 示例:
    nload:默認只查看第一個網絡的流量進出情況
    nload eth0 eth1:在nload後面指定網卡,可以指定多個
  • 設置刷新間隔:默認刷新間隔是100毫秒,可通過-t命令設置刷新時間(單位是毫秒)
    nload -t 500 eth0
  • 設置單位:顯示兩種單位一種是顯示Bit/s、一種是顯示Byte/s,默認是以Bit/s,也可不顯示/s
    -u h|b|k|m|g|H|B|K|M|G 表示的含義: h: auto, b: Bit/s, k: kBit/s, m: MBit/s, H:auto, B: Byte/s, K: kByte/s, M: MByte/s
  • 例子: nload -u M eth0

lsof

lsof:list open files 查看當前系統文件的工具。在linux環境下,一切皆文件,用戶通過文件不僅可以訪問常規數據,還可以訪問網絡連接和硬件如傳輸控制協議(TCP)和用戶數據報協議(UDP)套接字等,系統在後臺都為該應用程序分配了一個文件描述符

  • 命令參數
    -a:列出打開文件存在的進程
    -c<進程名>:列出指定進程所打開的文件
    -g:列出GID號進程詳情
    -d<文件號>:列出占用該文件號的進程
    +d<目錄>:列出目錄下被打開的文件
    +D<目錄>:遞歸列出目錄下被打開的文件
    -n<目錄>:列出使用NFS的文件
    -i<條件>:列出符合條件的進程(4、 6、協議、 :端口、 @ip )
    -p<進程號>:列出指定進程號所打開的文件
    -u:列出UID號進程詳情
    -h:顯示幫助信息
    -v:顯示版本信息。
    -n: 不反向解析網絡名字

lsof示例

進程管理

  1. 查看由登陸用戶啟動而非系統啟動的進程
    lsof /dev/pts/1
  2. 指定進程號,可以查看該進程打開的文件
    lsof -p 9527

文件管理

  1. 查看指定程序打開的文件
    lsof -c httpd
  2. 查看指定用戶打開的文件
    lsof -u root | more
  3. 查看指定目錄下被打開的文件
    lsof +D /var/log/
    lsof +d /var/log/
    • 參數+D為遞歸列出目錄下被打開的文件,參數+d為列出目錄下被打開的文件
  4. 查看所有網絡連接
    lsof -i –n
    lsof [email protected]
    通過參數-i查看網絡連接的情況,包括連接的ip、端口等以及一些服務的連接情況,例如:sshd等。也可以通過指定ip查看該ip的網絡連接情況
  5. 查看端口連接情況
    lsof -i :80 -n
    通過參數-i:端口可以查看端口的占用情況,-i參數還有查看協議,ip的連接情況等
  6. 查看指定進程打開的網絡連接
    lsof -i –n -a -p 9527
    參數-i、 -a、 -p等,-i查看網絡連接情況,-a查看存在的進程,-p指定進程
  7. 查看指定狀態的網絡連接
    lsof -n -P -i TCP -s TCP:ESTABLISHED
    -n:no host names, -P:no port names,-i TCP指定協議,-s指定協議狀態通過多個參數可以清晰的查看網絡連接情況、協議連接情況等
    8. 恢復刪除文件(前提是這個刪除文件仍然被進程占用著還在內存中)
    lsof |grep /var/log/messages
    rm -f /var/log/messages
    lsof |grep /var/log/messages 或者 grep delede :這一步找到它的進程編號,下一步進入進程編號文件夾
    cat /proc/653/fd/6
    cat /proc/653/fd/6 > /var/log/messages

進程管理工具

kill命

  • 向進程發送控制信號,以實現對進程管理,每個信號對應一個數字,信號名稱以SIG開、頭(可省略),不區分大小寫
  • 顯示當前系統可用信號: kill –l 或者 trap -l
  • 常用信號:man 7 signal
    (1) SIGHUP 無須關閉進程而讓其重讀配置文件
    (2) SIGINT 中止正在運行的進程;相當於Ctrl+c 例如kill -2 `pidof ping`
    (3) SIGQUIT 相當於ctrl+\ :,有些命令用它退出,可用 kill -QUIT `pidof bc`或者 kill -3
    (9) SIGKILL 強制殺死正在運行的進程:強制退出
    (15) SIGTERM 終止正在運行的進程:正常退出
    (18) SIGCONT 繼續運行
    (19) SIGSTOP 後臺休眠
  • 指定信號的方法 :
    (1) 信號的數字標識:1, 2, 9
    (2) 信號完整名稱:SIGHUP
    (3) 信號的簡寫名稱:HUP

例子:kill -1

cd /var/www/html
echo welcome to my web >index.html
curl 192.168.20.100

vim /etc/httpd/conf/httpd.conf :其中的頁面文件位置修改為newhtml
mkdir newhtml
cd newhtml
vim index.html :重新寫一個新的頁面文件

ps auxf 或者 ps -ef 或者 pidof httpd|apache 或者 pstree -p
kill -1 apache的父進程pid(由root啟動的那個pid)
kill -n 1 pid :註意一個帶-一個不帶-

例子:kill -15 (默認)

ps aux |grep mingetty
kill mingettypid :此命令執行後發現pid號雖然沒了,但是會生成一個新的pid號把它重新掛起
pstree -p :查看是哪一個父進程拉起mingetty,發現是1進程
kill 1 :殺不死1進程,但是此時再次執行 kill pidmingetty 發現它無法再自動起來了,說明此命令對於1進程還是有影響的
因此不要隨便用kill殺進程,比如殺掉sshd服務,則遠程將無法再次連接,必須在硬件主機上面重啟sshd :systemctl start sshd 才可以再次使用,這將有可能出現嚴重問題
  • 按PID:
    kill [-SIGNAL] pid …
    kill –n SIGNAL pid
    kill –s SIGNAL pid
  • 按名稱:killall [-SIGNAL] comm… :它可以一次性殺掉對應名字進程包含的所有pid ,而kill 一次只能殺掉一個
  • 按模式:pkill [options] pattern (正則表達式)

-SIGNAL :
-u uid: effective user,生效者
-U uid: real user,真正發起運行命令者
-t terminal: 與指定終端相關的進程
-l: 顯示進程名(pgrep可用)
-a: 顯示完整格式的進程名(pgrep可用)
-P pid: 顯示指定進程的子進程

例子:

pkill -9 -t pts/1 :把終端上全部進程殺掉包括bash shell
pkill pin.* :正則表達式模式法殺掉ping(或者pin開頭的任意進程))

killall -0 cmdname 的用法

此命令不進行進程管理,但是會檢查cmd名進程是否正常運行,類似於pidof ,把返回值存入$?中,用於判斷cmd進程是否正常運行。

任務作業管理

  1. Linux的作業控制
    前臺作業:通過終端啟動,且啟動後一直占據終端
    後臺作業:可通過終端啟動,但啟動後即轉入後臺運行(釋放終端)
  2. 讓作業運行於後臺
    (1) 運行中的作業: Ctrl+z ,它會放入後端但是讓它處於stop休眠狀態
    (2) 尚未啟動的作業: COMMAND &
    • 註意:後臺作業雖然被送往後臺運行,但其依然與終端相關;退出當前終端,將關閉後臺作業。如果希望送往後臺後,剝離與終端的關系,有以下兩種方式:
    • nohup COMMAND &> /dev/null &
    • screen;COMMAND
  3. 查看當前終端所有作業:jobs
  4. 作業控制:
    fg [[%]JOB_NUM]:把指定的後臺作業調回前臺
    bg [[%]JOB_NUM]:讓送往後臺的作業在後臺繼續運行
    kill [%JOB_NUM]: 終止指定的作業

易混淆點:

  1. killall -18 手動開啟休眠狀態的進程 ,killall -19 手動停止正在運行的進程。這兩個命令和前端,後端沒有任何關系,和終端也沒有關系,只要能找到進程,就可用它操作(也可用pstree -p 或則 pidof 或者 ps aux 找到進程編號然後kill -18 -19也可)
  2. 進程和終端相關是因為它是在終端內開了個子shell來運行的,只要終端關閉(比如遠程sshd服務終端關閉),父進程都關閉了那麽它下面的無論是前端還是後端任務都將會關閉,例如關閉終端相當於關閉6681進程,則ping命令當然會關閉,無論前端後端。
├─sshd(6994)─┬─sshd(6681)───bash(6683)───ping(6773)
           │            └─sshd(129671)───bash(129673)───pstree(6808)
  • 上面都是centos7中的邏輯,但是centos6中,如果終端關閉,則它下面的子進程會自動掛載到init上繼續運行,註意區分。
  1. 因此用nohup將命令運行之後,當終端關閉它會掛載到systemd上繼續運行。或者還可用screen程序,則終端掉了也不會影響命令的執行。
  2. 註意,command & 和 ctrl z 的區別,一個已經運行調到後端不運行,一個沒有運行調到後端運行。
  3. 註意fg會把後端的進城調回到前端並運行,不管它在後端否運行還是不運行。同樣的bg也是讓進程調回到後端進行運行,只不過因為進程前段運行的時候無法操作,同時也沒有jobs編號,所以已經運行進程要用ctrl+z調到後端停止運行,然後再用bg 啟動運行。

並行運行

  • 同時運行多個進程,提高效率(相當於同時啟動多個後臺程序)
    1. 方法1
      vi all.sh
      f1.sh &
      f2.sh &
      f3.sh &
      然後運行此腳本
    2. 方法2
      (f1.sh &);(f2.sh &);(f3.sh &)
    3. 方法3:註意中括號邊上有空格
      { f1.sh & f2.sh & f3.sh & }

任務計劃

Linux任務計劃、周期性任務執行

未來的某時間點執行一次任務

at 指定時間點,執行一次性任務
batch 系統自行選擇空閑時間去執行此處指定的任務

周期性運行某任務

cron

at任務

包:at
at 命令:at [option] TIME
常用選項:

-V 顯示版本信息
-t time 時間格式 [[CC]YY]MMDDhhmm[.ss]
-l 列出指定隊列中等待運行的作業;相當於atq
-d 刪除指定的作業;相當於atrm
-c #(編號) :查看具體作業任務
-f /path/file 指定的文件中讀取任務
-m 當任務被完成之後,將給用戶發送郵件,即使沒有標準輸出

  • 註意:作業執行命令的結果中的標準輸出和錯誤以郵件通知給相關用戶

TIME格式:定義出什麽時候進行 at 這項任務的時間

HH:MM [YYYY-mm-dd]
noon, midnight, teatime(4pm)
tomorrow
now+#{minutes,hours,days, OR weeks}

  1. HH:MM 02:00
    在今日的 HH:MM 進行,若該時刻已過,則明天此時執行任務
  2. HH:MM YYYY-MM-DD 02:00 2016-09-20
    規定在某年某月的某一天的特殊時刻進行該項任務
  3. HH:MM[am|pm] [Month] [Date]
    04pm March 17
    17:20 tomorrow
  4. HH:MM[am|pm] + number [minutes|hours|days|weeks]
    在某個時間點再加幾個時間後才進行該項任務
    now + 5 min
    02pm + 3 days
    • 註意:測試中發現如果設置的時間小於當前時間點(比如現在時間3點,執行命令2點)則它會明天執行(即使此時把時間改為1點59分它也不會馬上執行了,因為還有日期的關系,別忘記了)需要註意這一點(crontab中也是這個原理)。

執行方式:

(1)交互式 (2)輸入重定向(多行)(3)管道| (4)at –f 文件
它依賴於atd服務,需要啟動才能實現at任務

rpm -ql at
systemctl status|start atd.service

at DATE<<EOF   :一行一個任務
xxx
xxx
EOF

at -l 
  • 註意at交互式的話需要用ctrl+d結束。

at隊列存放在/var/spool/at目錄中
/etc/at.{allow,deny}控制用戶是否能執行at任務

  • 白名單:/etc/at.allow 默認不存在,只有該文件中的用戶才能執行at命令
  • 黑名單:/etc/at.deny 默認存在,拒絕該文件中用戶執行at命令,而沒有在at.deny 文件中的使用者則可執行

註意點:

  1. 如果存在了白名單,則黑名單無效了,如果兩個文件都不存在,只有 root 可以執行 at 命令。
  2. 直接用at命令寫的計劃任務重啟後丟失。
  3. at 中的計劃任務命令中的標準輸出不會在屏幕上打印,它會自動寫入郵件中發送。用-m可以讓沒有標準輸出的命令也發郵件,為了證明此at任務確實執行了

周期性任務計劃cron

周期性任務計劃:cron
相關的程序包:
cronie:主程序包,提供crond守護進程及相關輔助工具
cronie-anacron:cronie的補充程序,用於監控cronie任務執行狀況,如cronie中的任務在過去該運行的時間點未能正常運行,則anacron會隨後啟動一次此任務
crontabs:包含CentOS提供系統維護任務

  1. 確保crond守護處於運行狀態:
    CentOS 7:
    systemctl status crond
    CentOS 6:
    service crond status
  2. 計劃周期性執行的任務提交給crond,到指定時間會自動運行系統cron任務:系統維護作業
    /etc/crontab :盡量不要改這個系統級定義的計劃任務文件,而是自己定義,用命令crontab -e (參照格式寫,其中user-name無需再寫)
  3. 用戶cron任務:
    crontab命令
    日誌:/var/log/cron ,其中記錄了計劃任務是否執行
    • 註意rpm -ql cronie 或者 rpn -qf /usr/bin/crontab,查看信息。然後ll /usr/bin/crontab 可以看到它有suid權限,因此用戶可以定義計劃任務。

系統cron任務:/etc/crontab
註釋行以 # 開頭
詳情參見 man 5 crontab
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * user-name command to be executed

例如:晚上9點10分運行echo命令
10 21 * wang /bin/echo "Howdy!"

時間表示法:

(1) 特定值
給定時間點有效取值範圍內的值
(2) *
給定時間點上有效取值範圍內的所有值
表示“每...”
(3) 離散取值
#,#,#
(4) 連續取值
#-#
(5) 在指定時間範圍上,定義步長
/#: #即為步長

對應時間格式

@形式 時間形式
@reboot Run once after reboot
@yearly 0 0 1 1 *
@annually 0 0 1 1 *
@monthly 0 0 1
@weekly 0 0 0
@daily 0 0 *
@hourly 0

示例:每3小時echo和wall命令
0 /3 centos /bin/echo “howdy”; wall “welcome to Magedu!”

系統的計劃任務:

/etc/crontab 配置文件
/etc/cron.d/ 文件夾內的配置文件
/etc/cron.hourly/ 腳本
/etc/cron.daily/ 腳本
/etc/cron.weekly/ 腳本
/etc/cron.monthly/ 腳本

anacron系統

運行計算機關機時cron不運行的任務,CentOS6以後版本取消anacron服務,由crond服務管理
對筆記本電腦、臺式機、工作站、偶爾要關機的服務器及其它不一直開機的系統很重要對很有用

  • 配置文件:/etc/anacrontab,負責執行/etc/ cron.daily /etc/cron.weekly /etc/cron.monthly中系統任務
    字段1:如果在這些日子裏沒有運行這些任務……
    字段2:在重新引導後等待這麽多分鐘後運行它
    字段3:任務識別器,在日誌文件中標識
    字段4:要執行的任務

由/etc/cron.hourly/0anacron執行
當執行任務時,更新/var/spool/anacron/cron.daily文件的時間戳

管理臨時文件

CentOS7使用systemd-tmpfiles-setup服務實現
CentOS6使用/etc/cron.daily/tmpwatch定時清除臨時文件

  • 配置文件:
    /etc/tmpfiles.d/.conf
    /run/tmpfiles.d/
    .conf
    /usr/lib/tmpfiles/*.conf

  • /usr/lib/tmpfiles.d/tmp.conf
    d /tmp 1777 root root 10d
    d /var/tmp 1777 root root 30d

  • 主要清除 /tmp (以及/usr/tmp) 和 /var/tmp 中的文件
    命令:
    systemd-tmpfiles –clean|remove|create configfile

用戶計劃任務

crontab命令定義
每個用戶都有專用的cron任務文件:/var/spool/cron/USERNAME
crontab命令:
crontab [-u user] [-l | -r | -e] [-i]
-l 列出所有任務
-e 編輯任務 :誰執行就是以誰為用戶來執行,因此user-name這項不用再寫。同時在執行它的時候會有一個臨時文件,執行完之後便會消除掉它。
-r 移除所有任務
-i 同-r一同使用,以交互式模式移除指定任務
-u user 僅root可運行,指定用戶管理cron任務
控制用戶執行計劃任務:
/etc/cron.{allow,deny}

總結at和crontab

  • 一次性作業使用 at
  • 重復性作業使用crontab
操作 at命令 crontab命令
Create at time crontab -e
List at -l crontab -l
Details at -c jobnum crontab -l
Remove at -d jobnum crontab -r
Edit N/A crontab -e
  • 沒有被重定向的輸出會被郵寄給用戶
  • root能夠修改其它用戶的作業

註意:運行結果的標準輸出和錯誤以郵件通知給相關用戶
(1) COMMAND > /dev/null
(2) COMMAND &> /dev/null

對於cron任務來講,%有特殊用途;如果在命令中要使用%,則需要轉義,或者將%放置於單引號中,則可不用轉義.如果需要%(比如date命令中),則要把它寫入腳本中,然後執行腳本即可

註意:

  1. at 和crontab在 測試中發現如果設置的時間小於當前時間點(比如現在時間3點,執行命令2點)則它會明天執行(即使此時把時間改為1點59分它也不會馬上執行了,因為還有日期的關系,別忘記了)需要註意這一點
  2. 寫入計劃任務的命令的標準輸出盡量都扔到垃圾箱裏面,因為它都會以郵件方式進行保存,如果執行的次數過多也會造成垃圾文件。所以都重定向到垃圾箱內比較好(當然 at命令可以不用這樣設置,因為它僅僅執行一次,甚至用-m 強行發送郵件判斷它是否執行)
  3. 腳本或者命令最好寫全路徑。
  4. 註意一點,如果時間格式如下所示,則代表的日子和星期並非是與的關系,而是或的關系,它表示每月的1 10 20日和每周的星期1 5 都會進行計劃任務。
    • 如果非要是與的關系,則只能在後面的CMD中進行判斷了,比如下面的判斷是否是周日
30 23 1,10,20 * 1,5 CMD
30 23 1,10,20 * * [ `date +%w` -eq  0 ] && cmd 

例子:計劃任務來重啟httpd服務

cat /etc/crontab
crontab -e

* * * * * /usr/bin/killall -0 httpd &> /dev/null || systemctl start httpd

crontab -l
cat /var/spool/cron/root
cat /var/log/cron

思考:

(1) 如何在秒級別運行任務?

          • for min in 0 1 2; do echo "hi"; sleep 20; done
            (2) 如何實現每7分鐘運行一次任務?

sleep命令:

sleep NUMBER[SUFFIX]...
SUFFIX:
s: 秒, 默認
m: 分
h: 小時
d: 天

usleep:標準單位為1us,微秒

usleep 1000000 :此為1秒

18.系統進程和性能管理,計劃任務