uptime
uptime命令顯示了load avg,它其實是讀取的/proc/uptime文件:
- /proc/uptime 文件
cat /proc/uptime
9592411.58 9566042.33
第一個是系統啟動了多久(單位s),第二個意思是系統啟動以來,cpu idle花費的時間(單位s)。多核機器上,第二個可能大于第一個,因為他是每個核心idle的總和。
怎么才能知道uptime 真的是讀取這個文件呢?想辦法查看一下,這里可以用strace :
[root@localhost ~]# strace uptime 2>&1 | grep open
open("/proc/uptime", O_RDONLY) = 3
open("/var/run/utmp", O_RDONLY|O_CLOEXEC) = 4
open("/proc/loadavg", O_RDONLY) = 4
strace 命令在stderr上打印了uptime的系統調用情況,在stdout上打印命令的原始輸出。strace -e open uptime
可以起到和grep open
相同的作用。uptime只是格式化輸出了/proc的內容。如果是腳本里想要uptime值,自己讀取/proc/uptime或許更方便一些。
Load average
[root@localhost ~]# cat /proc/loadavg
0.00 0.01 0.05 2/374 40656
前三列沒什么好說的,第四列是當前有多少個進程,和多少個進程處于running或者runable,最后一列是最新的被分配的pid。running的意思是,當前進程正在物理cpu上運行;runable的意思是,它在等系統給他分配cpu時間片。
[root@localhost ~]# sleep 10 &
[1] 40674
[root@localhost ~]# sleep 10 &
[2] 40675
[root@localhost ~]# sleep 10 &
[3] 40676
[root@localhost ~]# cat /proc/loadavg
0.00 0.01 0.05 2/375 40677
可以看到,每運行一次,pid就+1,cat /proc/loadavg
最后一列值可以證明。
證明第四列是當前正在運行的進程數:
[root@localhost ~]# cat /proc/loadavg
0.05 0.04 0.05 2/374 40717
當前有兩個進程在運行(其中一個是當前的cat,另一個是vmware的vm-tool進程)
[root@localhost ~]# cat /dev/urandom > /dev/null &
[1] 40718
[root@localhost ~]# cat /proc/loadavg
0.09 0.04 0.05 3/375 40719
創建一個無意義,但不斷運行的進程(隨機生產些數據,然后寫入/dev/null),第四列 正在運行的進程數+1(另外兩個運行中的進程和上面同理)。
load數量指進程狀態處在 :正在運行、等待運行、和不可中斷(后面對這個狀態做解釋)的進程數。load avg就是過去1min,5min,15min load數量的平均數,但這個解析是簡化版本,其實并不太對。直接引用維基百科上的解釋:
Mathematically speaking, all three values always average all the system load since the system started up. They all decay exponentially, but they decay at different speed. Hence, the 1-minute load average will add up 63% of the load from last minute, plus 37% of the load since start up excluding the last minute. Therefore, it's not technically accurate that the 1-minute load average only includes the last 60 seconds activity (since it still includes 37% activity from the past), but that includes mostly the last minute.
關于不可中斷狀態:
進程 struct task_struct
的 state 字段為TASK_UNINTERRUPTIBLE,進程陷入了不能被中斷的阻塞操作,無視信號。 What is an uninterruptable process?
http://stackoverflow.com/questions/223644/what-is-an-uninterruptable-process
另外一個關于不可中斷狀態的解釋還不錯:https://yq.aliyun.com/articles/8902
內核的某些處理流程是不能被打斷的。如果響應異步信號,程序的執行流程中就會被插入一段用于處理異步信號的流程(這個插入的流程可能只存在于內核態,也可能延伸到用戶態),于是原有的流程就被中斷了
如果是單核cpu的話,loadavg是1(同一時間運行一個進程),就說明cpu利用率是100%。如果是雙核cpu,loadavg為2(同一時間運行兩個進程)說明cpu利用率是100%。htop左上角和nproc命令可以看系是幾核cpu。
load數量包括了不可中斷的進程數,但是處于這個狀態的進程并不怎么影響cpu運行(可以認為不使用cpu時間)。所以從loadavg推斷cpu使用率不太準,這也能解釋一些為什么load很高,但是實際cpu使用率不高。
mpstat可以查看瞬時cpu使用情況,要安裝sysstat(這是個牛逼的工具)。
[root@localhost ~]# yum install sysstat -y
[root@localhost ~]# mpstat 1
Linux 3.10.0-327.el7.x86_64 (localhost.virthost) 02/26/17 _x86_64_ (1 CPU)
17:38:41 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
17:38:42 all 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
17:38:43 all 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
^C
Average: all 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
進程
htop默認顯示用戶進程和用戶線程。
shift+H打開關閉用戶線程
shift+K打開關閉內核線程
F5顯示進程繼承關系(類似ps -f)
/proc/<pid>/{pwd,exe,cmdline} 里包含了進程當前工作目錄的鏈接,可執行程序的鏈接和命令行。可以通過讀取procfs里的內容,從內核獲取信息。
/proc/<pid>/status 包含當前進程的許多信息(內存分配情況,父進程id等),uid指明了當前進程所屬用戶:
[root@localhost htop]# cat /proc/47937/status | grep Uid
Uid: 0 0 0 0
id <uid>
命令可以找到這個用戶的相關信息。其實id也是讀取/etc/passwd和/etc/group文件獲取用戶信息:
[root@localhost]# strace -e open id 0
...
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
uid=0(root) gid=0(root) groups=0(root)
+++ exited with 0 +++
為什么會去找/etc/passwd 呢?這個是讀取了/etc/nsswitch.conf 配置。
[root@localhost htop]# cat /etc/nsswitch.conf
...
passwd: files sss
shadow: files sss
group: files sss
...
關于這個配置文件,可以參考這里:<http://www.cnblogs.com/cute/archive/2012/05/17/2506342.html>,總之就是/lib64/libnss_files.so 加載了這個文件,其他的一系列的name service和這個文件有關(比如dns),還可以配置成從ldap中獲取用戶名密碼。
unix用戶的密碼保存在/etc/shadow:
[root@localhost]# cat /etc/shadow
root:$6$eS1H0Kk/$MPOOjZyuhc14tzBl.2O2VoLoXxkirzIdKKw41tP/cEjfEPe58VcQB3LLlGoJzuHRrE.WIjii9nalKWl/GJMoR/:17153:0:99999:7:::
第二列開頭的$6$表示加密算法是sha512,后面緊接著是鹽和鹽+密碼的hash。
用戶運行可執行文件時,進程所屬用戶一般是當前用戶自己,而不是可執行文件本身的屬主(這點應該很好理解)。
使用sudo -u 運行程序可以切換進程屬主。sudo權限在 /etc/sudoers
配置,最好使用visudo編輯配置文件,它會對文件格式做驗證。
/etc/passwd是非常敏感的文件,passwd在普通用戶權限下運行,也能更改密碼,說明passwd肯定是以root身份運行的,否則它沒發修改passwd文件。當二進制程序有x權限后,可以設置setuid權限:
sudo chmod u+s /usr/bin/passwd
[root@localhost]# ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 27832 Jun 10 2014 /usr/bin/passwd
這樣,二進制文件運行時,進程屬主就是二進制文件的屬主。
其他的特殊權限還有sticky bit和setgid。下面的命令可以找到權限類似passwd這樣的命令:
[root@localhost]# find /usr/bin -user root -perm -u+s
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/su
/usr/bin/sudo
/usr/bin/mount
/usr/bin/umount
/usr/bin/staprun
/usr/bin/crontab
/usr/bin/pkexec
/usr/bin/passwd
進程狀態
- R 在運行隊列里
- S 可中斷的休眠(等待事件發生)
- D 不可中斷的休眠,發生頁面錯誤時,發生的IO不可以被中斷,進程此時不能處理信號,處理信號可能會造成另外一個頁面錯誤。如果有太多進程處于這個狀態,意味著有可能大量進程發生頁面錯誤,也許應該看下swap。
- Z 僵尸狀態,子進程退出后,相關的資源已經釋放,父進程應該在收到SIGCHL信號后D收尸,不應該把子進程隨便亂扔。
- T 被任務控制信號停止,ctrl+z終止后臺進程可以看到這種狀態。
- t 被debugger停止(調試),gdb -p <pid> attach的進程,可以看到這個狀態。
- X 應該永遠看不見
F9 htop 發送信號快捷鍵
可以制造一個處于uninterruptible狀態的進程。使用NFS掛在遠程目錄的時候,如果遠程目錄不存在,進程就會被掛起。我們使用google的DNS 8.8.8.8 試試,因為它沒有打開NFS:
[root@localhost ~]# mount 8.8.8.8:/tmp /tmp &
[1] 48642
[root@localhost ~]# ps aux | grep mount
root 48642 0.0 0.0 125628 924 pts/1 S 22:03 0:00 mount 8.8.8.8:/tmp /tmp
root 48643 0.0 0.1 42468 1608 pts/1 D 22:03 0:00 /sbin/mount.nfs 8.8.8.8:/tmp /tmp -o rw
root 48645 0.0 0.0 112616 700 pts/1 R+ 22:03 0:00 grep --color=auto mount
使用strace看看它到底在哪個調用上掛起了:
[root@localhost ~]# sudo strace /sbin/mount.nfs 8.8.8.8:/tmp /tmp -o rw
...
mount("8.8.8.8:/tmp", "/tmp", "nfs", 0, "vers=4,addr=8.8.8.8,clientaddr=1"...
進程運行的時間
linux的時間片大約在幾毫秒(搞清楚linux上時間片到底多長也挺有意思的)。loadavg在單核機器上小于1,意味這cpu在過去一段時間什么事情都沒做。
進程優先級
- NI 用戶空間優先級,最低-20到最高19。經驗是升一級優先級通常可以獲得10%的更多cpu時間。
- PRI 內核空間優先級,0-139。0-99是實時優先級,100-139才是給用戶進程用的,這映射到用戶優先級的-20到19。
內存
編寫用戶空間的程序員或者程序,會感覺自己的程序擁有全部內存,這是幻覺。
用戶態程序不會直接訪問物理內存,只能訪問虛擬內存空間,內核會把虛擬地址映射到物理內存或者磁盤上。
htop/top內存的含義:
- VIRT/VSZ 虛擬內存,包括二進制的代碼,數據,共享庫,換出的頁,映射了但是還沒使用的頁。
- RES/RSS 進程實際在物理內存中的空間,不包括換出的內存,但是包括和其他進程共享的。
- SHR 共享的內存
htop/top內存使用率是指RES/RSS內存占總物理內存的百分比。