简单进程监控程序
簡(jiǎn)單進(jìn)程監(jiān)控程序
文章目錄
- 簡(jiǎn)單進(jìn)程監(jiān)控程序
- 題目描述
- 解題思路
- 詳細(xì)編碼實(shí)現(xiàn)
- 1.判斷進(jìn)程
- 2.檢查文件
- 3.處理注釋
- 4.函數(shù)封裝
- 5.整體代碼
- 運(yùn)行腳本
- 參考文章
題目描述
作業(yè)題目:寫(xiě)一個(gè) Shell 腳本來(lái)進(jìn)行進(jìn)程的死活監(jiān)控
作業(yè)描述:此 Shell 腳本能檢查配置文件中記錄的進(jìn)程是否在系統(tǒng)中運(yùn)行。如果在系統(tǒng)中運(yùn)行則顯示進(jìn)程ID(PID),如果不在運(yùn)行則顯示 DOWN 文字。
配置文件(check_procs.conf):
systemd smbd nmbd #logd sshd腳本命名為check_proc.sh, 執(zhí)行腳本后的輸出結(jié)果:
systemd: 1 5241 31842 smbd: DOWN nmbd: DOWN sshd: 5025 31840 31857要求:
- 考慮各種錯(cuò)誤場(chǎng)景的出錯(cuò)處理
- 關(guān)鍵代碼要有合理注釋
- 進(jìn)行合理的函數(shù)功能封裝
解題思路
題目的意圖很明顯,就是讓我們讀入配置文件,然后挨個(gè)判斷文件中記錄的進(jìn)程是否在系統(tǒng)中運(yùn)行,運(yùn)行則給出 PID,否則顯示 DOWN。根據(jù)輸入和輸出結(jié)果可以看出,注釋掉的進(jìn)程是不用判斷的,直接略過(guò)。
核心的功能就是三步,讀取文件、跳過(guò)注釋、判斷進(jìn)程,最后將功能合理封裝為函數(shù)運(yùn)行即可。
詳細(xì)編碼實(shí)現(xiàn)
在編寫(xiě)代碼之前,有一個(gè)非常重要的注意事項(xiàng),Shell中的變量賦值是不能有空格的。比如我們要將給變量 a 賦值為5,應(yīng)該寫(xiě)為 a=5,而不能是 a = 5。雖然加了空格會(huì)更美觀,但是代碼就不能按照預(yù)期運(yùn)行了,所以賦值等號(hào)兩邊一定不要加空格!
1.判斷進(jìn)程
判斷進(jìn)程是程序最核心的功能,我們可以先進(jìn)行進(jìn)程判斷,再將其他的功能加上。
使用非常典型的通過(guò) grep 獲取進(jìn)程ID的方法,判斷systemd 這個(gè)進(jìn)程是否在運(yùn)行。
program="systemd" # 進(jìn)程名稱#獲取進(jìn)程PID,為空則進(jìn)程未啟動(dòng) pid=`ps -ef | grep $program | grep -v grep |awk '{print $2}'` if [ "${pid}" == "" ] thenecho "${program}: DOWN" elseecho -ne "${program}: " # echo默認(rèn)換行,-ne表示當(dāng)前輸出不換行echo ${pid} fi- ps -ef ,顯示所有的進(jìn)程,e顯示結(jié)果,f 顯示完整格式
- ps -ef | grep xxx ,把包括 xxx 這個(gè)關(guān)鍵字的進(jìn)程都顯示出來(lái)
- grep -v grep,去除 grep 進(jìn)程(即去除含有 xxx 關(guān)鍵字的這個(gè)grep查找進(jìn)程本身)
- awk ‘{print $2}’,提取結(jié)果的第二列數(shù)據(jù)(因?yàn)榈诙姓沁M(jìn)程的PID)
2.檢查文件
方便起見(jiàn),我們就將文件放在 shell 腳本的同級(jí)目錄下。新建配置文件 check_procs.conf,將上面的配置文件示例全部寫(xiě)入
在腳本中編寫(xiě)判斷文件是否存在的代碼
fileName="check_procs.conf" # 文件名 BASE_PATH=$(cd `dirname $0`; pwd) # 獲取當(dāng)前目錄if [ ! -e "${BASE_PATH}/${fileName}" ] # 判斷當(dāng)前目錄下文件是否存在 thenecho "文件不存在或無(wú)法讀取"exit 0 fi- dirname $0,取得當(dāng)前執(zhí)行的腳本文件的父目錄
- cd ‘dirname $0’, 進(jìn)入這個(gè)目錄(切換當(dāng)前工作目錄)
- pwd,顯示當(dāng)前工作目錄(cd執(zhí)行后的)
3.處理注釋
讀取文件,按每一行進(jìn)行判斷,line為變量,表示每一行的內(nèi)容
判斷當(dāng)前行第一個(gè)字符是否為 #,如果是則當(dāng)前行全部是注釋,忽略即可
cat $fileName | while read line # 讀取文件,按行處理 doif [ "${line:0:1}" == "#" ] # 第一個(gè)字符為 ‘#’then# 此處編寫(xiě)處理語(yǔ)句fi done可以看到,當(dāng)前這個(gè)注釋判斷十分簡(jiǎn)單,僅僅是將第一個(gè)字符為 # 的內(nèi)容全部忽略
對(duì)于 ”注釋在行內(nèi)“ 、”多行注釋“ 等這樣的內(nèi)容是不能判斷的,還有待學(xué)習(xí)優(yōu)化。
4.函數(shù)封裝
Shell 中用戶自定義的函數(shù)不需要像 C 一樣指明類型,函數(shù)返回值可以用 return 來(lái)返回, return后跟一個(gè)數(shù)值,范圍為 0-255。如果不用 return,將以最后一條命令運(yùn)行結(jié)果作為返回值。
-
調(diào)用函數(shù)時(shí)可以向其傳遞參數(shù),在函數(shù)內(nèi)部使用 $n 的形式來(lái)獲取參數(shù)的值。比如 $1表示第一個(gè)參數(shù),$2表示第二個(gè)參數(shù),當(dāng)n>=10時(shí),需要使用 ${n} 來(lái)獲取參數(shù),比如第十個(gè)參數(shù) ${10}。
-
函數(shù)返回值在調(diào)用該函數(shù)后通過(guò) $? 來(lái)獲得。但是$? 僅對(duì)其上一條指令負(fù)責(zé),一旦函數(shù)返回后其返回值沒(méi)有立即保存入?yún)?shù),那么其返回值將不再能通過(guò) $? 獲得,所以函數(shù)返回值必須第一時(shí)間使用或保存。
有一點(diǎn)要注意的是,所有函數(shù)在使用前必須定義。所以說(shuō),應(yīng)該將自定義函數(shù)放在腳本的開(kāi)頭部分,這樣函數(shù)就可以正常使用了。
fileName="check_prog.conf" program="" # program為變量,用來(lái)接收參數(shù)# 讀取文件 getFile(){BASE_PATH=$(cd `dirname $0`; pwd)if [ ! -e "${BASE_PATH}/${fileName}" ]thenecho "文件不存在或無(wú)法讀取"exit 0fi } # 跳過(guò)注釋 crossNote(){program=$1 # 接收傳遞的參數(shù)if [ "${program:0:1}" == "#" ]thenreturn 1 # 當(dāng)前行為注釋,返回1fi } # 判斷進(jìn)程 judgeProgress(){program=$1 # 接收傳遞的參數(shù)pid=`ps -ef | grep $program | grep -v grep |awk '{print $2}'`if [ "${pid}" == "" ]thenecho "${program}: DOWN"elseecho -ne "${program}: "echo ${pid}fi }編寫(xiě)主函數(shù),首先讀取文件,然后每行都直接去掉注釋,再判斷進(jìn)程是否在運(yùn)行。
# 主函數(shù) main(){ getFile fileName # 判斷文件存在 cat $fileName | while read line # 按行讀取文件 docrossNote $line # 每一行判斷注釋if [ $? == 1 ] # 返回值為1,當(dāng)前行為注釋,忽略thencontinuefijudgeProgress $line # 判斷進(jìn)程是否運(yùn)行 done } main5.整體代碼
#! /bin/bash # 用于實(shí)現(xiàn)進(jìn)程監(jiān)控的shell腳本 fileName="check_procs.conf" program=""# 讀取文件 getFile(){BASE_PATH=$(cd `dirname $0`; pwd)if [ ! -e "${BASE_PATH}/${fileName}" ]thenecho "文件不存在或無(wú)法讀取"exit 0fi } # 跳過(guò)注釋 crossNote(){program=$1if [ "${program:0:1}" == "#" ]thenreturn 1fi } # 判斷進(jìn)程 judgeProgress(){program=$1#獲得進(jìn)程PID,為空則進(jìn)程未啟動(dòng)pid=`ps -ef | grep $program | grep -v grep |awk '{print $2}'`if [ "${pid}" == "" ]thenecho "${program}: DOWN"elseecho -ne "${program}: "echo ${pid}fi }# 主函數(shù) main(){ getFile fileName cat $fileName | while read line docrossNote $lineif [ $? == 1 ]thencontinuefijudgeProgress $line done } main運(yùn)行腳本
如果在運(yùn)行腳本時(shí)遇到了錯(cuò)誤,請(qǐng)參考這篇文章進(jìn)行解決 Shell腳本使用常見(jiàn)問(wèn)題說(shuō)明
我們?cè)诋?dāng)前目錄下輸入 ll 命令,確認(rèn)配置文件已經(jīng)存在
然后在終端中輸入運(yùn)行腳本的命令
./check_proc.sh回車即可看到最終的運(yùn)行結(jié)果
參考文章
Linux常用命令
vim編輯器的常用技巧
Shell腳本使用常見(jiàn)問(wèn)題說(shuō)明
Shell 函數(shù)
kill -9 ps -ef|grep cpu|grep -v grep|awk '{print $2}'命令解析
總結(jié)
- 上一篇: Shell脚本使用常见问题说明
- 下一篇: Win10安装Latex