1 Linux程序簡介
核心把程序存放在叫做任務隊列(task list)的雙向循環連結清單中,連結清單中的每一項都是類型為task_struct,名稱叫做程序描述符(process descriptor)的結構,該結構定義在include/linux/sched.h檔案中,它包含了一個具體程序的所有資訊。
程序都是動态建立的,當系統将程式(program)加載到記憶體中後就會産生一個程序(process)。但init程序不同,它總是存在并且由一個靜态的task_struct來表示。
在使用者空間,程序是由程序辨別符(PID)表示的。從使用者的角度來看,一個 PID 是一個數字值,可惟一辨別一個程序。一個 PID 在程序的整個生命期間不會更改,但 PID 可以在程序銷毀後被重新使用。
建立程序的方式:
1. 直接通過執行一個程式來建立一個新的程序;
2. 通過fork()和exec()來建立目前程序的子程序,<code>fork</code> 調用會導緻建立一個子程序,而 <code>exec</code> 調用則會用新程式代替目前程序上下文。Linux下使用了一種叫做寫時拷貝(copy-on-write)頁實作。這種技術原理是:記憶體并不複制整個程序位址空間,而是讓父程序和子程序共享同一拷貝,隻有在需要寫入的時候,資料才會被複制。簡而言之就是資源的複制隻是發生在需要寫入的時候才進行,在此之前,都是以隻讀的方式共享。
父程序和子程序:父程序通過fork()方法産生一個子程序,該子程序與父程序共享同一記憶體空間,當父程序終止時,子程序也随之而終止。但子程序終止,父程序并不一定終止。
程序的分類:程序一般分為三類,互動式程序、批處理程序和守護程序。其中,守護程序是常駐在記憶體中的程序,又被稱為服務,比如Linux中的系統或網絡服務:crond、httpd、mysqld等等。
2 Linux程序管理
2.1 程序的檢視:ps、top、pstree
1. ps:靜态方式檢視目前系統運作的程序
選頃不參數:
-A :所有的process 均顯示出來,與-e 具有同樣的效果;
-a :與terminal無關其他所有 process ;
-u :有效使用者 (effective user) 相關的process ;
x :通常與-a 這個參數一起使用,可列出較完整資訊。
-l:較詳細的列出PID的資訊;
-f:作出一個更為完整的輸出。
ps -l:将目前屬于自己這次登入的 PID與相關資訊列出來(隻與自己的bash 有關)
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 4591 4545 0 80 0 - 2093 - pts/0 00:00:00 su
4 S 0 4632 4591 0 80 0 - 1348 - pts/0 00:00:00 bash
4 R 0 17217 4632 0 80 0 - 1221 - pts/0 00:00:00 ps
0 T 0 26005 4632 0 80 0 - 1099 - pts/0 00:00:00 du
0 T 0 26023 4632 0 80 0 - 3456 - pts/0 00:00:05 du
注解:F:表示此程序的标志(process flags);4表示程序的權限為root,1表示此程序僅進行fork而沒有實際執行exec;
S:表示程序狀态(STAT);主要狀态有:R—Running、S—Sleep、D—不可被喚醒狀态、T—stop、Z—Zombie(程序已經終止但無法被移除至記憶體外)
UID、PID、PPID:表示此程序的使用者ID、程序ID、父程序ID
C:代表CPU使用率,機關為百分比
PRI/NI:Priority/Nice 的縮寫,代表此程序被 CPU 所執行的優先級,數值越小代表該程序越早被 CPU 執行
ADDR/SZ/WCHAN:與記憶體有關
TTY:登入的終端
TIME:使用掉的CPU的時間,表示此程序實際消耗的CPU運作的時間,而不是系統時間
CMD:此程序觸發的程式名
ps aux:檢視系統所有的程序
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 2900 1228 ? Ss Apr01 0:01 /sbin/init
root 2 0.0 0.0 0 0 ? S Apr01 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S Apr01 0:00 [migration/0]
root 4 0.0 0.0 0 0 ? S Apr01 0:05 [ksoftirqd/0]
root 5 0.0 0.0 0 0 ? S Apr01 0:00 [migration/0]
root 6 0.0 0.0 0 0 ? S Apr01 0:00 [watchdog/0]
root 7 0.0 0.0 0 0 ? S Apr01 0:00 [migration/1]
root 8 0.0 0.0 0 0 ? S Apr01 0:00 [migration/1]
root 9 0.0 0.0 0 0 ? S Apr01 0:01 [ksoftirqd/1]
root 10 0.0 0.0 0 0 ? S Apr01 0:00 [watchdog/1]
root 11 0.0 0.0 0 0 ? S Apr01 0:00 [migration/2]
root 12 0.0 0.0 0 0 ? S Apr01 0:00 [migration/2]
root 13 0.0 0.0 0 0 ? S Apr01 0:01 [ksoftirqd/2]
root 14 0.0 0.0 0 0 ? S Apr01 0:00 [watchdog/2]
......
注解:其中很多列都與之前的類似,%MEM表示程序占用記憶體量,START表示程序被觸發啟動的時間。
增加-f選項可以顯示出父子程序間的關系:ps auxf
nagios 3171 0.0 0.0 9828 1500 ? Ss Apr01 0:35 /usr/local/nagi
nagios 3177 0.0 0.0 3308 804 ? S Apr01 0:01 \_ /usr/local/
nagios 3178 0.0 0.0 3308 808 ? S Apr01 0:01 \_ /usr/local/
nagios 3179 0.0 0.0 3308 808 ? S Apr01 0:01 \_ /usr/local/
.....
2. top:動态的檢視程序變化
-d:接秒數,表示程序畫面更新的間隔,預設為5秒;
-n:執行的次數,執行完後退出;
-p:指定監測某些PID
在top執行過程可使用的指令:
? :顯示在 top 當中可以輸入的按鍵指令;
P :以 CPU 的使用資源排序顯示;
M :以 Memory 的使用資源排序顯示;
N :以 PID 來排序
T :由該 Process 使用的CPU 時間累積 (TIME+) 排序。
k :給予某個 PID 一個信号(signal)
r :給予某個 PID 重新制訂一個 nice 值。
q :離開 top 軟體
top -d 2 -n 3 -p 31455
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
Cpu(s): 3.6%us, 0.8%sy, 0.0%ni, 95.2%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 3896172k total, 3460076k used, 436096k free, 475836k buffers
Swap: 2091000k total, 28000k used, 2063000k free, 2138496k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31455 apache 20 0 46244 5960 980 S 0.0 0.2 0:00.00 httpd
3. pgrep:通過程式的名字來查詢程序
常用參數
-l : 列出程式名和程序ID;
<code>-o : 程序起始的ID;</code>
<code>-n : 程序終止的ID;</code>
<code><code>pgrep -lo httpd 31435 httpd</code></code>
<code><code></code></code>
<code><code>4. pstree:以程序樹的方式來顯示程序間連接配接</code></code>
<code><code>選頃不參數: -A : 各程序樹之間的連接配接以 ASCII 字元來連接配接; -U : 各程序樹之間的連接配接以萬國碼的字元來連接配接。在某些終端接口下可能會有錯誤; -p : 同時列出每個 process的PID; -u : 同時列出每個 process 的所屬賬号名稱。</code></code>
<code><code>pstree -A</code></code>
<code><code>init-+-NetworkManager-+-dhclient | `-{NetworkManager} |-abrt-dump-oops |-abrtd |-acpid |-atd |-automount---4*[{automount}] |-avahi-daemon---avahi-daemon |-bonobo-activati---{bonobo-activat} |-certmonger |-clock-applet |-console-kit-dae---63*[{console-kit-da}]</code></code>
<code>......</code>
2.2 程序管理
singal:給予程序一個singal執行相應的動作,singal代号與名稱:
代号 名稱 内容
1 SIGHUP 啟動被終止的程序,讓 PID 重新讀取自己的配置檔案,類似重新啟動
2 SIGINT 相當于用鍵盤輸入 [ctrl]-c 來中斷一個程序的運作
9 SIGKILL 代表強制中斷一個程序的運作
15 SIGTERM 以正常的方式結束程序的運作,對于某些不正常運作的程序,無法用此singal來終止
17 SIGSTOP 相當于用鍵盤輸入 [ctrl]-z 來暫停一個程序的運作
kill -singal PID:傳遞singal給某個程序,一般用來終止程序運作,如kill -9 PID強制終止某程序
killall -singal 指令名稱:管理與某個程式相關的所有程序,如killall -9 httpd強制終止所有以 httpd 啟動的程序
pkill 程序名:以程序名方式殺死指定的正在運作的程序,如pkill httpd
2.3 程序的優先級:Priority、Nice
Priority表示程序之間使用系統資源(cpu、記憶體等)的優先級,PRI優先值越小表示程序越優先,由核心動态調整,無法人為調整,不過可通過Nice值來調整程序的優先執行順序。
PRI(new)=PRI(old)+nice
調整nice值的方式:
1. 程序運作時就給定一個特定的nice值,使用nice指令,數值範圍為-20~19。如:nice -n -8 ls
2. 通過renice指令來調整某個PID的nice值,如:renice 10 3455
3. 使用top執行過程中的r指令來重新調整某個PID的nice值
3 系統資源檢視
3.1 free:檢視記憶體使用情況
-b/-k/-m/-g:free預設以位元組顯示,可以指定以bytes、Kbytes、Mbytes、Gbytes來顯示
-t:在最終結果中顯示實體記憶體和swap總量
free -m
total used free shared buffers cached
Mem: 3804 3375 429 0 469 2092
-/+ buffers/cache: 812 2991
Swap: 2041 27 2014
3.2 uname:檢視系統與核心資訊
-a :所有系統相關的資訊,包括底下的資料都會被列出來;
-s :系統核心名稱
-r :核心的版本
-m :本系統的硬體名稱,例如 i686或 x86_64 等;
-p :CPU 的類型
-i :硬體的平台 (ix86)
uname -a
Linux rango.com2.6.32-431.11.2.el6.i686 #1 SMP Tue Mar 25 17:17:46 UTC 2014 i686 i686 i386 GNU/Linux
3.3 uptime: 檢視系統啟動時間和負載
uptime
21:12:48 up 3 days, 2:12, 2 users, load average: 0.09, 0.07, 0.01
3.4 netstat:網絡監控
選項與參數:
-a :将目前系統上所有的聯機、監聽、Socket 資料都列出來
-t :列出 tcp網絡封包的資料
-u :列出 udp 網絡封包的資料
-n :以端口号 (port number),而不是程序的服務名稱來顯示;
-l :列出目前正在網絡監聽(listen) 的朋務;
-p :列出該網絡的程序 PID
netstat -tlnp:查找目前系統上已在監聽的網絡聯機及其PID
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:32000 0.0.0.0:* LISTEN 2215/java
tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN 2049/rsyslogd
tcp 0 0 127.0.0.1:199 0.0.0.0:* LISTEN 2725/snmpd
檢視某個端口是否正在被監聽:netstat -anl | grep :80
tcp 0 0 :::80 :::* LISTEN
3.5 dmesg:分析核心産生的資訊
dmesg | grep sd:檢視硬碟相關資訊
sd 0:0:0:0: [sda] 976773168 512-byte logical blocks: (500 GB/465 GiB)
sd 0:0:0:0: [sda] 4096-byte physical blocks
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
sda: sda1 sda2 < sda5 sda6 sda7 > sda3 sda4
sd 0:0:0:0: [sda] Attached SCSI disk
EXT4-fs (sda3): mounted filesystem with ordered data mode. Opts:
dracut: Mounted root filesystem /dev/sda3
sd 4:0:0:0: [sdb] Attached SCSI removable disk
sd 0:0:0:0: Attached scsi generic sg0 type 0
sd 4:0:0:0: Attached scsi generic sg2 type 0
Adding 2091000k swap on /dev/sda4. Priority:-1 extents:1 across:2091000k
3.6 vmstat:動态檢測系統資源變化
vmstat 可以檢測 CPU / 記憶體 / 磁盤輸入輸出狀态等等。
統計目前主機 CPU 狀态,每秒一次,共計三次:vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 28000 428940 480996 2141460 0 0 119 52 24 8 4 3 93 1 0
1 0 28000 427468 480996 2143132 0 0 0 0 927 3903 4 1 96 0 0
0 0 28000 427468 480996 2143212 0 0 0 0 981 4040 4 1 96 0 0
注解:
1. procs程序字段:r表示等待運作的程序數量,b表示不可被喚醒的程序數量
2. memory記憶體字段:swpd虛拟記憶體被使用的容量,free空閑記憶體,buff緩沖存儲,cache高速緩存
3. swap交換空間:si:由磁盤中将程序取出的量; so:由于記憶體不足而将沒用到的程式寫入到磁盤的swap 的容量。 如果 si/so 的數值太大,表示記憶體内的資料常常得在磁盤與主存儲器之間傳來傳去,系統效能很差
4. io磁盤讀寫:bi:由磁盤寫入的區塊數量; bo:寫入到磁盤去的區塊數量。如果這部份的值越高,代表系統的I/O越繁忙
5. system系統:in:每秒被中斷的程式次數; cs:每秒鐘進行的事件切換次數;這兩個數值越大,代表系統與接口裝置的溝通越頻繁。 這些接口裝置包括磁盤、網卡、時間鐘等
6. CPU:us:非核心層的 CPU 使用狀态; sy:核心層所使用的 CPU 狀态; id:閑置的狀态; wa:等待I/O 所耗費的 CPU 狀态; st:被虛拟機 (virtual machine) 所盜用的 CPU 使用狀态 (2.6.11 以後才支援)。
以watch來執行vmstat:watch vmstat
4 關于SUID/SGID
SUID:Set UID,稱為SUID的特殊權限,僅對二進制程式有效,且執行者對該程式有x的可執行權限,以及擁有者owner權限。如ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 25980 Feb 22 2012 /usr/bin/passwd
SGID:相應的檔案群組所有者的特殊權限。類似的,SGID 對二進制程式有用;程式執行者對于該程式具備 x 的權限;執行者在執行過程中将會獲得該程式群組的支援
如ls -l /usr/bin/locate
-rwx--s--x 1 root slocate 35548 Oct 10 2012 /usr/bin/locate
5 使用Supervisord來管理程序
Supervisord是用Python實作的類Unix系統程序管理工具。
Supervisor能夠作為跨平台控制者來管理和與程序進行互動,它可以啟動、停止、重新開機其他類Unix系統中的程式,亦可重新開機崩潰的程序。
1.supervisord:守護程序,用于将指定的程式作為子程序來運作。
2.supervisorctl:supervisor服務控制程式
3.supervisord.conf:配置檔案,定義服務名稱以及接口等等
ps:如果supervisord要求管理的程式是非daemon程式,supervisord會幫你把它轉成daemon程式。
4.通過向supervisord.conf添加[program:daemon]來管理daemon子程序。
eg:
[program:hello]
command=python /home/smallfish/hello.py #command是程式的執行路徑
autorstart=true #autorstart是表示自動啟動
stdout_logfile=/home/smallfish/hello.log #stdout_logfile是捕獲标準輸出
5.安裝Supervisor:
easy_install supervisor
或者:
wget http://pypi.python.org/packages/source/s/supervisor/supervisor-3.0b1.tar.gz
tar -zxvf supervisor-3.0b1.tar.gz
cd supervisor-3.0b1
python setup.py install
6.設定supervisor配置檔案:
建立預設的配置檔案:
echo_supervisord_conf >/etc/supervisord.conf
vi /etc/supervisord.conf
取消以下的注釋,并修改IP為0.0.0.0,表示監聽所有主機的9001端口。并添加basic authenrication
[inet_http_server] ; inet (TCP)server disabled by default
port=0.0.0.0:9001 ;(ip_address:port specifier, *:port for all iface)
username=rango ; (defaultis no username (open server))
password=yourkey ;(default is no password (open server))
增加自定義的背景程序(注意程序名之間用一個:分隔)
[program:daemon]
command=python/scripts/python/daemon.py
autorestart=true
stdout_logfile=/tmp/daemon.log
7.設定supervisor啟動檔案:
#!/bin/bash
#
# supervisordStartup script for thesupervisor
# description: Supervisor is aclient/server system that allows its users to # monitor andcontrol a number of processes on UNIX-like #operating systems.
path=/sbin:/bin:/usr/sbin:/usr/bin
prog=supervisord
daemon=/usr/bin/$prog
config=/etc/$prog.conf
pidfile=/tmp/$prog.pid
desc="supervisord daemon"
scriptname=/etc/init.d/$prog
# Gracefully exit if the package hasbeen removed.
test -x $daemon || exit 0
start() {
echo -n "Starting $desc:$prog"
$daemon -c $config
echo "..."
}
stop() {
echo -n "Stoping $desc:$prog"
supervisor_pid=$(cat $pidfile)
kill -15 $supervisor_pid
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
restart)
*)
echo "Usage: $scriptname{start|stop|restart}" >&2
exit 1
esac
exit 0
添加可執行權限:chmod +x /etc/init.d/supervisord
8.編寫相應的python腳本:
vim /scripts/python/daemon.py:
#!/usr/bin/env python
import time
print "Daemon runs 3 secs, then dies"
time.sleep(3)
print "Daemon dies"
啟動supervisor服務,并觀察daemon服務狀态:
/etc/init.d/supervisord start
tail -f /tmp/daemon.log:
Daemon runs 3 secs, then dies
Daemon dies
9.Web界面通路:http://localhost:9001
ps:防火牆開啟服務:
vim /etc/sysconfig/iptables:
-A INPUT -m state --state NEW -m tcp -p tcp --dport 9001 -j ACCEP
——Rango Chen