Shell編程課堂筆記php
目錄前端
Shell編程課堂筆記.............................................................................................................................................. 1java
shell編程第一天.................................................................................................................................................... 3node
一.爲何要學習Shell編程..................................................................................................................... 3mysql
二.什麼是shell.............................................................................................................................................. 4linux
三.什麼是Shell腳本................................................................................................................................... 4nginx
四.腳本語言的種類..................................................................................................................................... 6web
五.shell腳本的執行..................................................................................................................................... 8正則表達式
六.shell腳本開發級別規範及習慣......................................................................................................... 8sql
Shell編程次日................................................................................................................................................... 9
一. bash shell特性...................................................................................................................................... 9
二. 變量常見類型........................................................................................................................................ 9
三. 變量賦值方式..................................................................................................................................... 11
四. 變量數值運算..................................................................................................................................... 12
shell編程第三天................................................................................................................................................. 14
一.shell條件測試....................................................................................................................................... 14
shell編程第四天........................................................................................................................................ 21
二.shell流程控制....................................................................................................................................... 21
四.實例.安裝nginx.................................................................................................................................... 22
五. 根據不一樣的系統安裝不一樣的yum源.......................................................................................... 23
六. 安裝不一樣版本的PHP....................................................................................................................... 24
七. 流程控制語句case........................................................................................................................... 25
八. 實現簡單的JumpServer................................................................................................................. 27
九. 使用case實現多級菜單................................................................................................................. 29
十. expect進行參數傳遞,執行命令或其餘操做......................................................................... 30
十一. 批量獲取在線主機, 進行祕鑰批量分發............................................................................... 30
Shell編程第五天................................................................................................................................................. 33
一.for循環語句.......................................................................................................................................... 34
二. while循環語句.................................................................................................................................... 35
三. 監控網站,每隔10秒肯定一次網站是否正常...................................................................... 36
四. Shell內置命令..................................................................................................................................... 37
shell編程第六天................................................................................................................................................. 37
一. 回顧........................................................................................................................................................ 37
二. shell腳本之函數................................................................................................................................. 38
三. 函數變量做用域................................................................................................................................. 40
四. wgret命令參數,curl命令參數....................................................................................................... 40
shell編程第七天................................................................................................................................................. 41
一. shell數組應用...................................................................................................................................... 41
shell編程第八天................................................................................................................................................. 45
一.shell正則應用....................................................................................................................................... 45
二. 基礎正則表達式................................................................................................................................. 46
三. 擴展正則表達式................................................................................................................................. 47
四. 正則表達式實戰................................................................................................................................. 47
五. sed文本處理........................................................................................................................................ 48
六. sed匹配替換........................................................................................................................................ 51
七. awk文本處理....................................................................................................................................... 52
八. awk工做原理....................................................................................................................................... 53
九. awk模式動做....................................................................................................................................... 55
十. awk條件表達式.................................................................................................................................. 56
十一. 運算表達式..................................................................................................................................... 56
十二. 邏輯操做符和複合模式.............................................................................................................. 56
十三. Awk條件判斷................................................................................................................................. 57
十四. awk 循環語句................................................................................................................................. 58
十五. awk數組實戰.................................................................................................................................. 58
十六. Awk數組案例................................................................................................................................. 59
shell編程第一天
一.爲何要學習Shell編程
1.Shell腳本語言是實現linux/unix系統管理及自動化運維重要且必備的工具,linux/unix系統的底層及基礎應用軟件的核心大都涉及shell腳本內容.每個合格的linux系統管理員或運維工程師,都須要熟練shell腳本語言的編寫,並可以閱讀系統及各種軟件附帶的shell腳本內容,只有這樣才能提高運維人員的工做效率,適應日益複雜的工做環境,減小沒必要要的重複工做,從而爲我的的職場發展奠基較好的基礎 2.學好shell編程所需的基礎知識 學好shell編程並設想輕鬆地經過shell腳本自動化管理企業生產系統的必備基礎以下: (1)對vim編輯器能熟練使用,熟練SSH終端機」.vimrc」等的配置 (2)要有必定的linux命令基礎,至少掌握80個以上linux經常使用命令並能熟練使用 (3)要熟練掌握linux正則表達式以及三劍客命令(grep ,sed,awk) (4)熟悉常見的linux網絡服務部署,優化,日誌分析及排錯 精簡系統啓動服務的方法 (1)setup (2)ntsysv (3)腳本 #!/bin/bash for srv in `chkconfig --list|grep 「3:on」|awk ‘{print $1}’` do chkconfig $srv off done for srv in crond network sshd rsyslog do chkconfig $srv on done or for Srv in `chkconfig --list | grep "3:on" | awk '{print $1}' | grep -vE "crond|network|sshd|rsyslog"` do chkconfig $Srv off done 3 如何才能學好Shell編程 學好Shell編程的核心:多練→多思考→再練→再思考,堅持如此循環便可! 學習的來源: 一、耳朵 二、眼睛 三、手 四、大腦 五、總結 (1)掌握Shell腳本的基本語法方法 (2)掌握Shell腳本的各類常見語法 (3)造成本身的腳本開發風格 (4)從簡單作起,簡單判斷,簡單循環 (5)多模仿、多離開參考資料練習、多思考 (6)學會分析問題,逐漸造成編程思惟 (7)編程變量名字規範,採用駝峯語法表示 (8)不要拿來主義,特別針對新手 |
二.什麼是shell
Shell是一個命令解釋權,它的做用是介紹執行用戶輸入的命令及程序等,用戶詩人一天命令,shell就解釋執行一條.這種從鍵盤一輸入命令,就能夠當即迴應的對話方式,備稱爲較好的方式 Shell存在於操做系統的最外層,負載直接與用戶對話,把用戶的輸入介紹給操做系統,並基礎各類各樣的操做系統的輸出結果,輸出到屏幕返回給用戶,當咱們輸入系統用戶名和密碼,登陸到linux後的全部操做都由shell解釋並執行 |
三.什麼是Shell腳本
系統目錄的堆積 特定的格式+特定的語法+系統的命令=文件 範例1:清除/var/log下messages日誌文件的簡單命令腳本 把全部命令放在一個文件裏堆積起來就造成腳本,下面就是一個由最簡單的命令堆積而成的shell腳本.要注意的是,得使用root身份來運行 #清除日誌腳本 cd /varlog cat /devnull >messages echo 「logs cleaned up」 提示: /varlog/messages是linux系統日誌文件很重要. 這個腳本實際上是有一些問題的,讀者有沒有看出來?它所在的問題以下: (1)若是不是root用戶,就沒法執行腳本清理日誌,而且會提示系統權限報錯. (2)沒有任何流程控制語句,簡單地說就是隻順序操做,沒有成功判斷和邏輯嚴密性. 範列2:寫一個包含命令,變量和流程控制語句的清除/var/log下messages日誌文件的shell腳本. #/bin/bash #清除日誌腳本 LOG_DIR=/varlog #$uid爲0的用戶,即root用戶 ROOT_UID=0 #腳本須要使用root用戶來運行,所以,對當前用戶進行判斷,不合要求的給出友好提示,並終止程序運行。 if [ "$UID" -ne "$ROOT_UID" ] #若是當前用戶不是root,不容許執行腳本。 then echo "Must be root to run this script." #給出提示後退出。 exit 1 #<==退出腳本。 fi #若是切換到指定目錄不成功,給出提示,並終止程序運行。 cd $LOG_DIR || { echo "Cannot change to necessary directory." exit 1 } #通過上述兩個判斷後,此處的用戶權限和路徑就應該是對的,只有清空成功,纔打印成功提示. cat /dev/null>messages && { echo "Logs cleaned up." exit 0 #退出以前返回0表示成功. 返回1表示失敗。 } echo "Logs cleaned up fail." exit 1 初學者若是想快速掌握shell腳本的編寫方法,最有效的思路就是採用電子遊戲中過關的方式,好比範列2的腳本能夠分紅以下幾關來設計: 第一關,必須是root才能執行腳本,不然給出友好提示並終止腳本運行. 第二關,成功切換目錄(cd /var/log),不然給出友好提示並終止腳本運行. 第三關,清理日誌( cat /dev/null >messages),清理成功給出正確提示. 第四關,通關或失敗,給出相應提高(echo輸出). Shell腳本在linux運維工做中的地位 Shell腳本語言很擅長處理純文本類型的數據,而linux系統中幾乎全部的配置文件,日誌文件(如NFS,Rsyanc,Httpd,Nginx,LVS,MySQL),以及絕大多數的啓動文件讀書純文本類型的文件.天然學好shell腳本語言,就能夠利用它在linux系統中發貨巨大的做用. 1.自動化的完成基礎配置 系統初始化操做,系統更新,內存調整,網絡時區,SSH優化 2.自動化安裝程序 LNMP,LAMP,MySQL,Nginx,Redis 3自動化調整配置文件 nginx.conf . my.cnf 4.自動化部署業務 部署php,java秒級回退 5.自動化按期備份恢復 MySQL全備 + 增量 + binlog + crond + shell腳本 6.自動化信息的採集 Zabbix + shell:硬件,系統,服務,網絡,等等 7.自動化日誌分析 ELK 取值->排序->去重->統計->分析 8.自動化擴容/縮容 Zabbix + shell -擴容:監控服務器cup,如cpu負載持續80%+ 觸發動做(腳本) -腳本: 調用api開通雲主機->初始化環境->加入集羣->對外提供 -縮容: 監控服務器CUP使用率20%->判斷有多高wed節點->判斷是否超過預設->縮減到對應的預設狀態->變動負載配置 |
四.腳本語言的種類
1.shell腳本語言的種類 [root@oldboy ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/dash /bin/tcsh /bin/csh bash特色: 命令補全: tab 命令別名: alias unalias 命令修改 命令歷史:history 問題:history查看命令歷史時,能夠帶上時間戳麼? 答: export HISTTIMEFORMAT="%F %T `whoami` history
Linux系統中的主流shell是bash,bash是由bourne shell(sh)發展而來,單bash還包含了csh和ksh的特點. 2.其餘經常使用的腳本語言種類 (1)PHP語言 PHP是網頁程序語言.也是腳本語言.它是一款更專一於web頁面開發(前端展現)的語言. 例如:wordpress,dedecms,discus等著名開源產品都是用PHP語言開發的 (2)Perl語言 Perl腳本語言,比shell腳本語言強大不少,在2010年之前很流行,它的語法靈活,複雜,在實現不一樣的功能時能夠用多種不一樣的方式,缺點是不易讀,團隊協做困難. (3)Python語言 Python是近幾年很是流行的語言,它不但能夠用於腳本程序開發,也能夠實現web頁面程序開發(例如:openstack,saltsack都是Python語言開發的),遊戲開發.大數據開發.移動端開發 (4)GO語言 Go語言是谷歌推出的一種全新的編程語言,能夠在不損失應用程序性能的狀況降低低代碼的複雜性。 Go 同時具備兩種編譯器,一種是創建在GCC基礎上的Gccgo,另一種是分別針對64位x64和32位x86計算機的一套編譯器(6g和8g)。谷歌目前正在研發其對ARM芯片和Android設備的支持。 3.shell腳本語言與PHP/perl/Python語言的區別和優點 Shell腳本語言的優點在於處理偏操做系統底層的業務. 例如:linux系統內部的不少應用,(有的是應用的一部分)都是使用shell腳本語言開發的,由於有1000多個linux系統命令爲他作支撐.特別是linux正則表達式及三劍客 grep awk sed 等命令..
對於一些常見的系統腳本,使用shell開發會更簡單快速, 例如:讓軟件一鍵自動化安裝,優化,監控報警腳本,軟件啓動腳本,日誌分析腳本,雖然PHP/Python語言也可以作到,可是考慮到掌握難度,開發效率,開發習慣等,他們可能就不如用shell腳本語言流行及有優點.對於一些常規的業務應用,使用shell更符合linux運維簡單,易用,高效的三大基本原則
PHP語言的優點在於小型網站系統和開發;Python語言的優點在於開發較複雜的運維工具軟件,,web界面的管理工具和web業務的開發.(例如:CMDB自動化運維平臺,跳板機,批量管理軟件saltstack.雲計算openstack軟件)等.咱們開發一個應用根據業務需求結合不一樣語言優點及自身擅長的語言來選擇,揚長避短,從而達到高效開發及同樣自身維護等目的. 面向過程: shell 建立一臺電腦 面向對象:Python組裝一臺電腦 4.經常使用操做系統默認的是shell 經過如下兩種方法能夠查看CentOS linux系統默認的shell 方法1: [root@oldboy ~]# echo $SHELL /bin/bash 方法2: [root@oldboy ~]# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash 提示:結尾的/bin/bash就是用戶登陸後的Shell解釋器。 5.shell腳本的規範 (1)腳本放在統一目錄 mkdir -p /server/seripts (2)推薦使用vim編輯器編輯腳本 (3)以.sh爲擴展名 (4)規範的shell腳本第一行會支持由那個程序(解釋器)來執行腳本中的內容 #!/bin/bash 或 #!/bin/sh (5)開頭的’#!’稱爲幻數,在執行shell腳本的時候,內核會根據」#!」後的解釋器來肯定用那個程序解釋腳本中的內容. 注意:這一行必須在每一個腳本頂端的第一行,若是不是第一行則爲腳本註釋行 (6)腳本註釋 在shell腳本中,跟在#後面的內容表示註釋.註釋部署不會被執行.僅給人看.註釋能夠自成一行,也能夠跟在命令後面,與命令同行.要養成寫註釋的習慣,方便本身與他人 最好不用中文註釋,由於在不一樣字符集的系統中會出現亂碼 (7)CMD CMD是command的縮寫.即命令提示符(CMD),是在OS / 2 , Windows CE與Windows NT平臺爲基礎的操做系統(包括Windows 2000和XP中, Vista中,和Server 2003 )下的「MS-DOS 方式」。中文版Windows XP 中的命令提示符進一步提升了與DOS 下操做命令的兼容性,用戶能夠在命令提示符直接輸入中文調用文件。 在9x系統下輸入command就能夠打開命令行.而在NT系統上能夠輸入cmd來打開,在windows2000後被cmd替代,利用CMD命令查詢系統的信息或者是判斷網絡的好壞 |
五.shell腳本的執行
Shell腳本是從上至下,從左至右依次執行每一行的命令及語句,即執行完了一個命令後再執行下一個命令,若是在shell腳本中遇到子腳本(即:腳本嵌套)時,就會先執行子腳本的內容,完成後再返回父腳本繼續執行父腳本內的後續命令及語句. 一般狀況下,當shell腳本執行時,會向系統內核請求啓動一個新的進程,以便在該進程中執行腳本命令以及子shell腳本. Shell腳本的執行一般能夠採用如下幾種方式: (1):bash script-name或sh (2):path/script-name或./script-name (必需要有執行權限) (3):source script-name或.將腳本里的代碼調入到當前環境運行 (4):cat script-name |bash (5):bash < script-name |
六.shell腳本開發級別規範及習慣
Shell腳本開發規範習慣很是重要,雖然這些規範部署必需要遵照的,但有了好的規範和習慣,能夠大大提高開發效率,並下降後期對於腳本的維護成本.當多人協做開發時,你們有一個互相遵照的規範就顯得更重要.哪怕是一我的開發,最好也採起一套固定的規範,這樣腳本更易讀,易於後期維護,最主要的是要讓本身養成一個一出手就是專業和規範習慣. 注意: (1)登陸shell /etc/profile是登陸shell啓動後運行的第一個啓動腳本 它只爲登陸shell運行;非登入shelll不會引起這個腳本 登入shell加載啓動腳本的順序爲: /etc/profile → /etc/profile.d → .bash_profile → .bashrc → /etc/bashrc 每一個調用的腳本會依次撤銷前一個調用腳本中的改變 在退出登入shell時,咱們還能夠執行某些任務,如建立自動備份,清除臨時文件 把這些任務放在.bash_logout文件中 (2)非登陸shell 非登入shell加載啓動腳本順序: .bash → /etc/bashrc → /etc/profile.d |
Shell編程次日
一. bash shell特性
1.命令補全和文件路徑補全,若是寫錯沒法補全. table 2.命令歷史記錄功能 history 3.命令別名功能 alias unalias 4.經常使用快捷鍵 Ctrl+u,k,a,e,l,c,z,d,w,r,y, 5.先後臺做業控制 bg, fg, jobs, screen 6.輸入輸出重定向 > ,>> ,2> ,2>> ,&> ,cat < 7.管道 | 8.命令排序 ; 沒有邏輯關係,不管分號前面的命令執行是否成功都執行後者 && 前面執行成功,則執行後者 || 前面執行不成功,則執行後者 rpm -a mysql &>/devnull && echo 「已安裝」 || echo 「未安裝」 9.shell通配符 * 匹配任意多個字符 ? 匹配任意一個字符 [ ]匹配括號中任意一個字符 a-z, 0-9, A-Z ( )在子shell中執行(cd /boot;ls) (umask 077; touch file1000) { }集合 touch file{1..100} \ 轉義符 10.echo輸出顏色,printf 格式化輸出文件 echo -e 「\033[30m 黑色字 \033[0m」 echo -e "\033[31m 紅色字 \033[0m" echo -e 「\033[32m 綠色字 \033[0m」 echo -e "\033[33m 黃色字 \033[0m" echo -e "\033[34m 藍色字 \033[0m" echo -e "\033[35m 紫色字 \033[0m" echo -e "\033[36m 天藍字 \033[0m" echo -e "\033[37m 白色字 \033[0m" |
二. 變量常見類型
變量說明:用一個固定的字符串去表示不固定的內容 變量 常量 Shell變量以下幾類分爲 (1)自定義變量 (2)系統環境變量 (3)位置參數變量 (4)預先定義變量 1.自定義變量 變量名=變量值, 步容許數字命名, 不能使用-命名 默認只在當前環境生效 使用export能夠在當前用戶的全部環境中生效 將export定義變量寫入/etc/bashrc,對全部用戶永久生效 將export定義變量寫入 .bashrc,支隊該用戶永久生效 (1)引用變量 $變量名 或 ${變量名} (2)查看變量 echo $變量名 set 顯示全部變量,包括自定義變量和環境變量 (3)取消變量 unset 變量名 做用範圍:僅在當前shell中有效 2.系統環境變量 (1)定義環境變量`export export 變量,將自定義變量轉換成環境變量` (2)引用環境變量`$變量名 或 ${變量名}` (3)查看環境變量`echo $變量名 env |grep Name` (4)取消環境變量`unset 變量名` (5)變量做用範圍`在當前shell和子shell有效 3.位置參數變量 腳本參數傳參: $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} 4.預先定義變量 $0腳本文件名 $* 全部的參數 「$*」顯示會不一樣 $@全部的參數 $# 參數的個數 $$ 當前進程的PID $! 上一個後天進程的PID $? 上一個命令的返回值 0 表示成功 例子: #1.判斷用戶是否爲root if [ $UID -eq 0 ];then echo 「continue」 else echo 「please change user」 root exit fi #2.判斷軟件包是否安裝 rpm -q $1 &>/dev/null if [ $? -eq 0 ];then echo 「package $1 installed」 else echo 「package $1 not installed」 fi ping $1 -c2 -f &> /dev/null if [ $? -eq 0 ];then echo "$1 up" else echo "$1 down" fi |
三. 變量賦值方式
1.顯示賦值(變量名=變量值) 例: ip1=192.168.56.11 school="Oldboyedu" today1=`date +%F` today2=$(date +%F) //例:取根分區使用百分比 [root@oldgirl 02 12:16:28]# df -h|grep /$ | awk '{print $5}' 2% [root@oldgirl 02 12:17:27]# df -h| awk 'NR==2{print $5}' 2% [root@oldgirl 02 12:19:02]# echo `df -h| awk 'NR==2{print $5}'` 2% [root@oldgirl 02 12:19:21]# echo $(df -h| awk 'NR==2{print $5}') 2% 2.read從鍵盤讀入變量值 read -p 「提示信息:」 變量名 read -t 5 -p "提示信息: " 變量名 [root@oldgirl 02 12:32:33]# read -p "input username,password: " User Pass input username,password: aaa 123 [root@oldgirl 02 12:33:12]# echo $User aaa [root@oldgirl 02 12:33:18]# echo $Pass 123 3.注意事項: 定義或引用變量時注意事項: " "弱引用,' '強引用 [root@shell ~]# school=Iphone [root@shell ~]# echo "${school} is good" Iphone is good [root@shell ~]# echo '${school} is good' ${school} is good 4.``命令替換等價於 $()反引號中的shell命令會被先執行 [root@shell ~]# touch `date +%F`_file1.txt [root@shell ~]# touch $(date +%F)_file2.txt [root@shell ~]# Root_Partition_Usage=$(df -Ph |grep '/$' |awk '{print $5}') [root@shell ~]# Root_Partition_Usage=`df -Ph |grep '/$' |awk '{print $5}'`
|
四. 變量數值運算
1.從前日後輸出變量內容 [root@shell ~]# url=www.sina.com.cn //獲取變量值的長度 [root@shell ~]# echo ${#url}
//從前日後,最短匹配 [root@shell ~]# echo ${url#*.}
//從前日後,最長匹配(貪婪匹配) [root@shell ~]# echo ${url##*.} 2.從後往前刪除變量內容 [root@shell ~]# url=www.sina.com.cn //從後往前,最短匹配 [root@shell ~]# echo ${url%.*} //從後往前,最長匹配 貪婪匹配 [root@shell ~]# echo ${url%%.*} 3.索引及切片 //從0列開始,切出5列,第0-4列 [root@shell ~]# echo ${url:0:5} //從5列開始,切出5列,第5-9列 [root@shell ~]# echo ${url:5:5} //去除前5列 [root@shell ~]# echo ${url:5} 4.變量內容替換 [root@shell ~]# url=www.sina.com.cn //將第一個匹配的sina替換爲baidu [root@shell ~]# echo ${url/sina/baidu} //將第一個匹配的n替換爲N [root@shell ~]# echo ${url/n/N} //貪婪匹配 [root@shell ~]# echo ${url//n/N} 5.變量替代 ${變量名-新的變量值} 變量沒有被賦值:會使用「新的變量值「 替代 變量有被賦值(包括空值):不會被替代 //例1 [root@Shell ~]# url=www.sina.com [root@Shell ~]# echo $url www.sina.com [root@Shell ~]# echo ${url-www.baidu.com} www.sina.com [root@Shell ~]# unset url [root@Shell ~]# echo ${url-www.baidu.com} //例2 [root@Shell ~]# url2= [root@Shell ~]# echo ${url2-www.baidu.com} ${變量名:-新的變量值} 變量沒有被賦值(包括空值): 都會使用「新的變量值「 替代 變量有被賦值: 不會被替代 //例1 [root@Shell ~]# unset url [root@Shell ~]# echo $url
[root@Shell ~]# url=www.sina.com [root@Shell ~]# echo $url www.sina.com [root@Shell ~]# echo ${url:-www.baidu.com} www.sina.com [root@Shell ~]# unset url [root@Shell ~]# echo ${url:-www.baidu.com} www.baidu.com
//例2 [root@Shell ~]# url2= [root@Shell ~]# echo $url2
[root@Shell ~]# echo ${url2:-www.baidu.com} 6.變量自增 [root@shell ~]# unset i [root@shell ~]# unset j [root@shell ~]# i=1 [root@shell ~]# j=1 [root@shell ~]# let x=i++ 先賦值,再運算 [root@shell ~]# let y=++j 先運算,再賦值
//對變量值不會產生任何影響 [root@shell ~]# echo $i 2 [root@shell ~]# echo $j 2
//對錶達式的值的影響 [root@shell ~]# echo $x 1 [root@shell ~]# echo $y 2
對變量的值的影響: [root@shell ~]# i=1 [root@shell ~]# let i++ [root@shell ~]# echo $i 2 |
shell編程第三天
一.shell條件測試
條件測試: 判斷某需求是否知足,須要由測試機制來實現: 如何編寫測試表達式實現所需的測試: (1)執行命令,並利用命令狀態返回值來判斷; (2)測試表達式 Test expression [ expression ] [[ expression ]] 注意:expression兩端必須有空白字符,不然爲語法錯誤 腳本的狀態返回值: 默認是腳本中執行的最後一條命令的狀態返回值; 自定義狀態退出狀態碼; 注意shell檢查遇到exit時,即會終止,所以,整個腳本執行幾位結束; 1.文件測試 存在性測試: -a file -e file 文件的存在性測試,存在則爲真,不然則爲假; 存在性及類型測試 -b file: 塊 -c file: 字符設備 -d file: 目錄 -f file: 普通文件 -h file或-L file:符號鏈接 -p file:命令管道 -s file:套接字 文件權限測試: -r. -w. -x : -u file:是否存在而且擁有suid權限 -g file:是否存在而且擁有sgid權限 -k file:是否存在而且擁有sticky權限 文件是否有內容: -s file:是否有內容,有爲真,沒有爲假; 時間戳測試: -N fiel: 文件自從上一次讀操做後,是否被修改過; 從屬關係測試; -O fiel:當前用戶是否爲文件屬主; -G fiel:當前用戶是否屬於文件的屬組; 雙目測試: file1 -ef file2: file1與file2是否爲指向同一個文件系統上的相同inode的硬鏈接; file1 -nt file2: file1是否新宇file2; file1 -ot file2: fiel1是否舊於file2; 2.常見使用方式 [ ! -d /bbb ] && mkdir /test [ -d /bbb ] || mkdir /test 3.腳本使用方式 #!/bin/bash #定義備份目錄站點 back_dir=/var/mysql_back
#test -d $back_dir || mkdir -p $back_dir if [ ! -d $back_dir ];then mkdir -p $dack_dir fi echo 「開始備份.....」 4.數值比較 數值比較 [ 整數1操做符 整數 2 ] -gt 大於 -lt 小於 -eq 等於 -ne 不等於 -ge 大於等於 -le 小於等於 例: 1.條件測試, 腳本使用案例, 建立用戶 #!/bin/bash read -p 「please input a username:」 user id $user &>/devnull;then if [ $? -eq 0 ];then echo 「user $user already exists」 else useradd $user if [ $? -eq 0 ];then echo 「$user is created」 fi fi 2.查看磁盤當前使用狀態,若是使用率超過百分之80%則報警發郵件 #查看磁盤使用率 df -h |grep 「/$」|awk ‘{print $5}’|awk -F ‘%’ ‘{print $1}’ #腳本 #!/bin/sbah Root_Partition_Use=$(df -h|grep "/$"|awk '{print $5}'|awk -F '%' '{print $1}')
if [ $Root_Partition_Use -ge 30 ];then echo "root partition use:${Root_Partition_Use}%" > /tmp/disk_use.txt fi 3.查看內存/當前使用狀態,若是使用率超過80%則報警發郵件 [root@shell]# cat mem_use.sh Mem_Total=$(free -m|grep "^M"|awk '{print $2}') Mem_Use=$(free -m|grep "^M"|awk '{print $3}') Mem_Per=$((($Mem_Use*100)/$Mem_Total))
if [ $Mem_Per -ge 30 ];then echo -e "\033[31m Memory usage ${Mem_B}% is too high \033[0m" else echo -e "\033[32m Memory usage ${Mem_B}% is normal \033[0m" fi 5.字符串比較 字符串測試:字符比較 ==:是否等於; >,<,!= =~:左側字符串是否可以被右側的PATTERN所匹配; -z "STRING":判斷指定的字符串是否爲空;空爲真,不空爲假; -n "STRING":判斷指定的字符串是否不空;不空爲真,空爲假;
注意: (1)字符串要加引用; (2)要使用[[ ]]; (1)字符串比對 [root@shell]# [ "$USER " = "root" ];echo $? 0 [root@shell]# [ "$USER " == "root" ];echo $? 0 [root@shell]# BBB="" [root@shell]# echo ${#BBB} 0 [root@shell]# [ -z "$BBB" ] 字符長度爲 0 [root@shell]# echo $? 0 [root@shell]# [ -n "$BBB" ] 字符長度不爲 0 [root@shell]# echo $? 1 //小結:變量爲空 或未定義: 長度都爲0 (2).字符串比對 [root@shell]# [ "$USER" = "root" ];echo $? 0 [root@shell]# [ "$USER" = "shell" ];echo $? 1 [root@shell]# [ "$USER" != "alice" ];echo $? 0 (3).多整數比對條件 [root@shell]# [ 1 -lt 2 -a 5 -gt 10 ];echo $? 1 [root@shell]# [ 1 -lt 2 -o 5 -gt 10 ];echo $? 0 [root@shell]# [[ 1 -lt 2 && 5 -gt 10 ]];echo $? 1 [root@shell]# [[ 1 -lt 2 || 5 -gt 10 ]];echo $? 0 6.正則比對 [root@shell]# [ "$USER" = "root" ];echo $? 0 [root@shell]# [ "$USER" =~ ^r ];echo $? bash: [: =~: binary operator expected 2 [root@shell]# [[ "$USER" =~ ^r ]];echo $? //使用正則 0 //判斷變量是否是數字 [root@shell]# num=123 [root@shell]# [[ "$num10" =~ ^[0-9]+$ ]];echo $? 0 [root@shell]# [[ "$num20" =~ ^[0-9]+$ ]];echo $? 1 7.判斷用戶輸入的是不是數字 [root@shell]# cat test02.sh #!/bin/bash
read -p "請輸入一個數值: " num if [[ ! "$num" =~ ^[0-9]+$ ]];then echo " 你輸入的不是數字,程序退出!!!" exit fi echo "Number Is $num" 8. 批量建立用戶腳本, 僅我的使用 #!/usr/bin/bash read -p "Please input number: " num read -p "Please input prefix: " prefix
for i in `seq $num` do user=$prefix$i useradd $user echo "123" |passwd --stdin $user &>/dev/null if [ $? -eq 0 ];then echo "$user is created." fi done 9. 批量建立用戶腳本, 改進版 #!/usr/bin/bash read -p "Please input number: " num if [[ ! "$num" =~ ^[0-9]+$ ]];then echo "error number!" && exit 1 fi
read -p "Please input user prefix: " prefix if [ -z "$prefix" ];then echo "error prefix" exit fi
for i in `seq $num` do user=$prefix$i useradd $user echo "123" |passwd --stdin $user &>/dev/null if [ $? -eq 0 ];then echo "$user is created." fi done 企業案例1.輸入或經過命令行傳入一個字符或數字,若是傳入數字等於1,打印1;若是等於2,打印2;其餘值,提示輸入不對,退出 #echo -n "please input one key:" #read value read -p "please input one key:" value [ ${#value} -ne 1 ] && { echo "please input one key" exit } expr $value + 1 &> /dev/null [ $? -ne 0 ] && { echo "please input number" exit } [ $value -eq 1 ] && { echo $value exit 0 } [ $value -eq 2 ] && { echo $value exit 0 } [[ ! $value =~ [1-2] ]] && { echo "input error" exit 0 } 企業案例2.分別使用傳參和read讀入方式比較兩個整數大小,禁止使用if語句. [ $# -ne 2 ] && { echo "please input two int." exit } int1=$1 int2=$2 expr $int1 + $int2 &> /dev/null [ $? -ne 0 ] && { echo "please input int" exit } [ $int1 -gt $int2 ] && { echo "$int1 > $int2" exit } [ $int1 -lt $int2 ] && { echo "$int1 < $int2" exit } [ $int1 -eq $int2 ] && { echo "$int1 = $int2" exit } 企業案例3.打印選擇菜單,按照選擇一鍵安裝不一樣的web服務。 1.install lamp 2.install lnmp 3.exit cat << End 1.install lamp 2.install lnmp 3.exit End read -p "please input number you want:" num expr $num + 1 &> /dev/null [ $? -ne 0 ] && { echo "you input must be {1|2|3}." exit } [ $num -eq 1 ] && { echo "install lamp..." # source lamp_install.sh sleep 3 exit $? } [ $num -eq 2 ] && { echo "install lnmp..." # source lnmp_install.sh sleep 3 exit $? } [ $num -eq 3 ] && { echo "bye" exit $? } [[ ! $num =~ [1-3] ]] && { echo "input error" exit $? } |
shell編程第四天
一.回顧
1.條件判斷 test -d filename [ 2 -lt 3 ] [[ 2 -lt 3 ]] ((2<3)) 2.文件比較 文件類型 -f -d 文件權限 2.數值比較 -le (小於等於) -ge (大於等於) -eq (等於) -lt (小於) -gt (大於) -ne (不等於) 3.字符串比較 == (等於) =~ (約等於) != (不等於) 4.邏輯判斷 && (前一個命令執行成功,再執行後一個命令) 字符 -a || (前一個美麗執行失敗,再執行後一個命令) 字符 -o |
二.shell流程控制
1.流程控制語句if 單分支結構 if [ 若是你有房 ];then 我就嫁給你 fi 雙分支結構 if [ 若是你有房 ];then 我就嫁給你 else 再見 fi 多分支結構 if [ 若是你有房 ];then 我就嫁給你 elif [ 你有車 ];then 我就嫁給你 elif [ 你有錢 ];then 我也嫁給你 else 再見 fi
猜數字遊戲,0-99之間數字 若是大了,就輸出一個信息.從新再猜 若是小了,就輸出一個信息,從新再猜 若是猜對了,恭喜,輸出猜的次數 腳本內容 #!/bin/bash echo "下面咱們玩一個猜數字遊戲.取值範圍在0-99之間" ran_num=$(expr $RANDOM % 100) while true do read -p "請輸入一個數字(0-99):" num
[[ ! "$num" =~ ^[0-9]+$ ]] && { continue } if [ $num -gt $ran_num ];then echo "大了,請繼續:" elif [ $num -lt $ran_num ];then echo "小了,請繼續:" else echo "恭喜,你猜對了! $count" exit fi done |
四.實例.安裝nginx
#!/bin/bash #install nginx #1.判斷網絡 ping -c1 www.baidu.com $>/dev/null if [ $? -ne 0 ];then echo 「請檢查你的網絡」 exit 1 fi #2.yum倉庫 yum_repo=$(yum repolist|grep nginx|wc -l) if [ $yum_repo -eq 0 ];then cat >/etc/yum.repos.d/nginx.repo <<-EOF [nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/7/x86_64/ gpgcheck=0 enabled=1 EOF yum makecache elif [ $yum_repo -eq 1 ];then yum install nginx -y &>/dev/null install_nginx=$(rpm -q nginx|wc -l) if [ $install_nginx -eq 1 ];then echo 「 nginx已經安裝」 fi nginx_status=$(systemctl status nginx|grep Active |awk ‘{print $1 $3}’) systemctl start nginx &>/dev/null if [ $? -eq 0 ];then echo 「nginx 已經啓動完畢」 echo 」nginx當前狀態是:$nginx_status」 else echo 「nginx啓動失敗 $nginx_status」 killall httpd &>/dev/null killall nginx &>/dev/null systemctl start nginx if [ $? -eq 0 ];then echo -e 「nginx從新啓動成功」 nginx_status=$(systemctl status nginx |grep Active |awk ‘{print $1 $3}’) echo -e 「\033[32m $nginx_status \033[0m」 fi fi else echo 「未知問題,請手動檢查一下」 fi |
五. 根據不一樣的系統安裝不一樣的yum源
#!/bin/bash os_name=$(cat /etc/redhat-release) os_version=$(cat /etc/redhat-release |awk ‘{print $4}’| awk -F ‘.’ ‘{print $1}’) if [ $os_version = 「(Final)」 ];then os_version=$(cat /etc/redhat-release |awk ‘{print $3}’ |awk -F ‘.’ ‘{print $1}’) fi if [ $os_vesion -eq 7 ];then mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/* .repo /etc/yum.repos.d/backup cat >/etc/yum.repos.d/base.repo<<-EOF [base] name=local base yum source baseurl=ftp://192.168.56.1/base/7/x86_64 enadle=1 gpgcheck=0 EOF Echo 「$os_name 系統已經配置好鬱悶倉庫」 elif [ $os_version -eq 6 ];then mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup wget -o /etc/yum.repos.d/Centos-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo &>/dev/null echo "$os_name 系統已經配置好yum倉庫" elif [ $os_version -eq 5 ];then mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-5.repo &>/dev/null echo "$os_name 系統已經配置好yum倉庫" else echo "沒法檢測當前系統版本,請檢查/etc/redhat-release" fi
|
六. 安裝不一樣版本的PHP
#!/bin/bash #install php install_php56() { echo "install php5.6......" } install_php70() { echo "install php7.0......" } install_php71() { echo "install php7.1......" } while : do echo "################################" echo -e "\t1 php-5.6" echo -e "\t2 php-7.0" echo -e "\t3 php-7.1" echo -e "\tq exit" echo "################################"
read -p "version[1-3]: " version if [ "$version" = "1" ];then install_php56 elif [ "$version" = "2" ];then install_php70 elif [ "$version" = "3" ];then install_php71 elif [ "$version" = "q" ];then exit else echo "error" fi done |
七. 流程控制語句case
case語句
case 變量 in 模式 1) 命令序列 1;; 模式 2) 命令序列 2;; 模式 3) 命令序列 3 ;; *) 無匹配後命令序列 Esac 1.批量刪除用戶
#!/bin/bash read -p "Please enter the username prefix to be deleted: " delname read -p "Please enter the number of users you need to delete:" delnum
echo "You want to delete the following users: Username prefix: $delname User number: $delnum "
for i in $(seq $delnum) do username=$delname$i read -p "are you sure you want to delete ${username}?[y|Y|Yes|n|N|NO] " reday case $reday in y|Y|YES) id $username &>/dev/null if [ $? -eq 0 ];then userdel $username &>/dev/null echo "$username deleted." else echo "$username not exist." fi ;; n|N|no|NO|No) continue ;; *) echo "you can only enter [y|Y|Yes|n|N|NO]" esac done 2.系統管理工具箱
Command action h 顯示命令幫助 f 顯示磁盤分區 d 顯示磁盤掛載 m 查看內存使用 u 查看系統負載 q 退出程序
#!/bin/bash menu(){ cat <<-EOF =================== h 顯示命令幫助 f 顯示磁盤分區 d 顯示磁盤掛載 m 查看內存使用 u 查看系統負載 q 退出程序 ===================== EOF } menu while true do read -p "Command [h|f|d|m|u|q]: " sys case "$sys" in h) clear menu ;; f) clear lsblk ;; d) clear df -h ;; m) clear free -m ;; u) clear uptime ;; q) break ;; *) echo "you can olny enter [h|f|d|m|u|q]." continue esac done |
八. 實現簡單的JumpServer
#!/usr/bin/bash
#jumpServer
Mysql_master=192.168.70.160 Mysql_slave1=192.168.70.161 Mysql_slave2=192.168.70.162 Nginx_Up=192.168.70.150 Nginx_WEB1=192.168.70.151 Nginx_WEB2=192.168.56.11
menuinfo(){ cat <<-EOF ------------------------------- | 1) mysql-master | | 2) mysql-slave1 | | 3) mysql-slave2 | | 4) Nginx-Upstream | | 5) Nginx-WebNode1 | | 6) Nginx-WebNode2 | | h) help | --------------------------------- EOF } #調用函數打印菜單 menuinfo #控制不讓輸入ctrl+c,z trap "" HUP INT TSTP while true do read -p "請輸入要鏈接的主機編號: " num case $num in 1|mysql-master) ssh root@$Mysql_master ;; 2|Mysql_slave1) ssh root@$Mysql_slave1 ;; 3|Mysql_slave2) ssh root@$Mysql_slave2 ;; h|help) clear meminfo ;; #退出腳本後門, 不要讓其餘人知道 exec) break ;; esac done //不管使用登錄式shell或非登錄式shell都會執行該腳本, 前提root用戶不容許登錄 [root@Shell day03]# cat /home/oldboy/.bashrc sh /home/oldboy/jumpserver.sh
4.使用case編寫服務啓動與中止腳本
#!/usr/bin/bash # manager Nginx start stop restart reload source /etc/init.d/functions
act=$1 te(){ if [ $? -eq 0 ];then action "Nginx Is $act" /bin/true else action "Nginx Is $act" /bin/false fi } start(){ /usr/sbin/nginx &>/dev/null te
} stop(){ /usr/sbin/nginx -s stop &>/dev/null te }
reload(){ /usr/sbin/nginx -s reload te }
status(){ Ngx_status=$(ps aux|grep "[n]ginx"|egrep -v "vi|sh"|grep master|awk '{print $2}') Nginx_Status_Port=$(netstat -lntp|grep nginx|awk '{print $4}') echo "Nginx_status_Pid: $Ngx_status" echo "Nginx_status_Port: $Nginx_Status_Port" } case $1 in start) start ;; stop) stop ;; restart) stop sleep 1 start ;; reload) reload ;; status) status ;; *) echo "Usage: $0 {start|stop|status|restart|reload|}" esac |
九. 使用case實現多級菜單
## 3.交互腳本expect 1.expect實現簡單的交互登錄
#!/usr/bin/expect spawn ssh root@192.168.70.161
expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "centos\r" }; } interact
2.expect定義變量實現交互方式
#!/usr/bin/expect set ip 192.168.70.161 set user root set password centos set timeout 5
spawn ssh $user@$ip
expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "$password\r" }; } #交互方式 interact |
十. expect進行參數傳遞,執行命令或其餘操做
#!/usr/bin/expect #位置傳參 set ip [lindex $argv 0] set user root set password centos set timeout 5
spawn ssh $user@$ip
expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "$password\r" }; }
#當出現#號符執行以下命令 expect "#" send "useradd bgx\r" send "pwd\r" send "exit\r" expect eof |
十一. 批量獲取在線主機, 進行祕鑰批量分發
cat for_ip.sh #!/usr/bin/bash
#1 拿到IP地址 >ip.txt for i in {160..162} do ip=192.168.70.$i { ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip" >> ip.txt fi }& done #2.生成對應的密鑰 if [ ! -f ~/.ssh/id_rsa ];then ssh-keygen -P "" -f ~/.ssh/id_rsa fi
#3.批量分發密鑰 while read line do /usr/bin/expect <<-EOF set pass 1 set timeout 2 spawn ssh-copy-id $line -f expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "1\r"} } expect eof EOF done<ip.txt [root@oldboy 09]# cat rsyncd.sh #!/bin/bash ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com ############################################################## RETVAL=0 start(){ rsync --daemon RETVAL=$? if [ $RETVAL -eq 0 ] then echo "rsync is ok" else echo "rsync is fail" fi } stop(){ killall rsync RETVAL=$? if [ $RETVAL -eq 0 ] then echo "rsync is stopped" else echo "rsync is stop fail" fi } case "$1" in start) start ;; stop) stop ;; restart) stop sleep 2 start ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac 專業一點的 [root@oldboy 09]# cat rsyncd2.sh #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop scripts ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com ############################################################## start(){ rsync --daemon retval=$? if [ $retval -eq 0 ] then echo "rsync startup ok" return $retval else echo "rsync startup fail" return $retval fi } stop(){ killall rsync retval=$? if [ $retval -eq 0 ] then echo "rsync stop ok" return $retval else echo "rsync stop fail" return $retval fi } case "$1" in start) start retval=$? ;; stop) stop retval=$? ;; restart) stop sleep 1 start retval=$? ;; *) echo "usage:$0 {start|stop|restart}" exit 1 esac exit $retval |
Shell編程第五天
一.for循環語句
1.for 循環基礎語法 for 變量名 in [ 取值列表 ] do 循環體 done 2.for案例,批量探測主機存活狀態 #cat for_ip.sh #循環主機 for i in {1..254} do #併發執行 { ip=10.0.0.$i ping -c1 -W1 $ip &>/dev/null If [ $? -eq 0 ];then Echo 「$ip」 |tee -a ip.txt fi }& done #等待前臺進程結束,在日後執行 wait echo "Get IP Is Finsh!!" 3.for循環批量建立用戶 #!/usr/bin/bash
read -p "請輸入用戶名前綴|密碼|數量: " rep pass num
if [[ ! $num =~ ^[0-9]+$ ]];then echo "Error 請從新輸入數字" fi
cat <<-EOF 你輸入的用戶名前綴是: $rep 你輸入的統一密碼是: $pass 你輸入要建立的數量: $num EOF read -p "你肯定要建立嗎? [y|n]" aredy case $aredy in y|Y|yes|YES) for i in $(seq $num) do username=$rep$i id $usernme &>/dev/null if [ $? -ne 0 ];then useradd $username && \ echo "$pass"|passwd --stdin $username &>/dev/null echo "$username Is OK!" fi done ;; n|N|No|NO) exit 1 ;; *) read -p "你肯定要建立嗎? [y|n]" aredy esac 4.for循環經過文件批量建立用戶 #!/bin/bash
for i in $(cat user.list) do id $i &>/dev/null if [ $? -ne 0 ];then useradd $i && \ echo "123" |passwd --stdin $i &>/dev/null echo "$i created." else echo "$i alreadt exists!!!" fi done
5.批量修改密碼
#!/usr/bin/bash for i in {160..162} do ip=192.168.70.$i ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then ssh $ip "echo 1|passwd --stdin root" &>/dev/null echo "$ip: Is Passwod Successfuly" fi done |
二. while循環語句
while循環基礎語法 //當條件測試成立(條件測試爲真),執行循環體 while 條件測試 do 循環體 done 1.使用while建立用戶 #!/usr/bin/bash while read user do id $user &>/dev/null if [ $? -eq 0 ];then echo "useradd $user is already exists" else useradd $user &>/dev/null echo "useradd $user is Created." fi done<user.list #文件中存在用戶和密碼 #!/usr/bin/bash while read user do u=$(echo $user|awk '{print $1}') p=$(echo $user|awk '{print $2}')
id $u &>/dev/null if [ $? -eq 0 ];then echo "useradd $u is already exists" else useradd $u &&\ echo "$p"|passwd --stdin $u &>/dev/null echo "useradd $u is Created Passwd Is Ok." fi
done<user2.tt |
三. 監控網站,每隔10秒肯定一次網站是否正常
#!/bin/bash if [ $# -ne 1 ];then echo $"usage $0 url." exit1 } fi while true do if [ $(curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" $1 | egrep -w "200|301|302" | wc -l) -ne 1 ];then echo "$1 is error." else echo "$1 is ok." fi sleep 10 done |
四. Shell內置命令
exit 退出整個程序 break 結束當前循環,或跳出本層循環 continue 忽略本次循環剩餘的代碼,直接進行下一次循環 |
shell編程第六天
一. 回顧
day01: 1.shell腳本結構 #!/bin/bash cmd 2.shell腳本執行 bash/sh:不須要腳本具備執行權限,打開一個子進程使用bash來解釋腳本里面的語句. ./:(路徑)必需要有執行權限,打開一個字進程,使用bash來解釋腳本里面的語句. source/. :不須要執行權限.直接將腳本里面的語句調入當前環境執行. 3.學習shell腳本的基礎: 基礎命令 如何更優秀: 習慣 標準 day02: 1.變量類型 自定義變量 1.變量名必須用字母或_開頭 2.變量名=變量值,export , /etc/bashrc ,~/bashrc 環境變量 1.變量名全大寫 2.變量名=變量值,export ,/etc/bashrc , ~/bashrc 位置變量 $n 預約義變量 $# 腳本里一共有幾個位置變量 $* 腳本里全部變量值 加」」會把全部變量值視爲一個總體 $@ 腳本里全部變量值 加」」會把全部變量值單個顯示 $? 腳本里最後一個命令執行後狀態碼 0表示成功 非0表示不成功 $0 運行這個腳本的文件名 $! $$ $_ day03: 1.條件測試語句 test [ ] [[ ]] :字符串比較 (( )) day04: 1.判斷語句 if 語句: 單分支 雙分支 多分支 case語句: day05: 1.循環語句 for while |
二. shell腳本之函數
函數:function,把一段獨立功能的代碼看成一個總體,併爲之取一個名字,命名的代碼段,此即爲函數. 注意:定義函數的代碼段不會自動執行,在調用時執行;所謂調用函數,在代碼中給定函數名便可;函數名出如今任何位置,在代碼執行時,都會被自動替換爲函數代碼; 過程式編碼:代碼重用 模塊化編程 結構化編程 語法一: function f-name { ... 函數體... } 語法二:(推薦) f_name() { .....函數體.... } 例1:給定一個用戶名.取得用戶的id號和默認shell 分析:
例2:服務腳本框架 分析:
返回值 建立鎖文件
刪除鎖文件
函數的生命週期: 每次被調用時建立函數,返回時終止; 其狀態返回結果爲函數體中運行的最後一個命令的狀態; 自定義狀態返回值,須要使用」return」 return [0-255] 0:成功 1-255:失敗 函數的執行結果返回值: (1) 使用echo或printf命令進行輸出; (2) 函數體中調用的命令執行結果; 函數的退出狀態碼: (1) 默認取決於函數中執行的最後一條命令的退出狀態碼; (2) 自定義:return 例1:添加10個用戶,用戶名做爲參數傳給函數 #!/bin/bash #retval 0 :usrt created #retval 5 :user exist adduser() { if id $1 &>/dev/null;then return 5 else useradd $1 return $? fi } for i in `seq 10` do username=$1$i adduser $username RETVAL=$? if [ $RETVAL -eq 5 ];then echo 「$username exist.」 elif [ $RETVAL -eq 0 ];then echo 「$username created.」 else echo 「no reason,please check it yoursrlf.」 fi done 函數可接受參數: 傳遞參數給函數:在函數體中,可使用$1,$2,....引用傳遞給函數的參數,還能夠在函數中使用$*或$@引用全部參數,$#引用傳遞的參數的個數: 在調用函數時,在函數名後面以空白符分隔給定參數列表便可,例如:testfunc arg1 arg2 arg3.... |
三. 函數變量做用域
1.局部變量: 做用域是函數的生命週期:在函數結束時被自動銷燬; 定義局部變量的方法:local VARIABLE=VALUE 2.本地變量: 做用域是運行腳本的shell進程的生命週期;所以,其做用範圍爲當前shell腳本程序文件 示例: #!/bin/bash name=tom setname(){ local name=jerry ceho 「Function:$name」 } setname echo 「shell:$name」 |
四. wgret命令參數,curl命令參數
shell編程第七天
一. shell數組應用
1.數組分類 普通數組:只能用整數 做爲數組索引 關聯數組:可使用字符串 做爲數組索引 2.普通數組 (1)數組賦值方式 針對每一個索引進行賦值 [root@oldboy ~]# array1[0]=pear [root@oldboy ~]# array1[1]=apple [root@oldboy ~]# array1[2]=orange [root@oldboy ~]# array1[3]=peach 一次賦多個值,數組名=(多個變量值) [root@oldboy ~]# array2=(tom jack alice) [root@oldboy ~]# array3=(tom jack alice "bash shell") [root@oldboy ~]# array4=(1 2 3 "linux shell" [20]=puppet) 將給文件中的每個行,做爲一個元數賦值給數組 array3 [root@oldboy ~]# array5=(`cat /etc/passwd`) (2)查看數組賦值結果 #定義普通數組 [root@oldboy ~]# declare -a array (3)訪問數組元數 統計數組元數的個數 [root@oldboy ~]# echo ${#array1[@]} 4 訪問數組中的第一個元數 [root@oldboy ~]# echo ${array1[0]} pear 從數組索引1開始 [root@oldboy ~]# echo ${array1[@]:1} apple orange peach 從數組索引1開始,訪問兩個元數 [root@oldboy ~]# echo ${array_fruit[@]:1:2} apple orange 訪問數組中全部數據,至關於echo ${array1[*]} [root@oldboy ~]# echo ${array_fruit[@]} pear apple orange peach (4)獲取數組索引 獲取數組元數的索引 [root@oldboy ~]# echo ${!array1[@]} 0 1 2 3 使用值來遍歷數組 #!/bin/bash array_fruit=( apple orange pear) for i in ${array_fruit[*]} do echo $i done 使用索引來遍歷數組 #!/bin/bash array_fruit=(apple orange prar) for i in ${!array-fruit[*]} do echo ${array_fruit[$i]} done 實例1.利用bash for循環打印下面這句話中字母數不大於6的單詞 welcome to oldboyedu my name is oldboy #!/bin/bash declare -a array_word array_word=(welcome to oldboyedu my name is oldboy) for i in ${array-word[@]} do if [ ${#i} -le 6 ];then echo $i fi done 實例2.批量檢查多個網站地址是否正常 要求: (1) 使用shell數組方法實現,檢測策略儘可能模擬用戶訪問 (2) 每10秒鐘作一次全部的檢查,沒法訪問的輸出報警 (3) 待檢測的地址以下. http://blog.oldboyedu.com http://blog.etiantian.org http://oldboy.blog.51cto.com 分析: 1. 定義一個數組 2. 經過for打印數組列表 3. 經過wget/curl發給我url,經過訪問返回值判斷 4. 使用while true循環,sleep 10 #!/bin/bash declare -a array_url array_url=( http://blog.oldboyedu.com http://blog.etiantian.org http://oldboy.blog.51cto.com ) while true do for n in ${array_url[*]} do wget -q -T 3 --tries=1 --spider $n if [ $? -eq 0 ];then echo 「$n is ok」 else echo 「$n is fail」 fi done sleep 2 done 3.關聯數組 (1)定義關聯數組,什麼是關聯數組 [root@oldboy ~]# declare -A tt_array_1 [root@oldboy ~]# declare -A tt_array_2 (2)給關聯數組進行賦值 數組名[索引號]=變量值 [root@oldboy ~]# tt_array1[index1]=pear [root@oldboy ~]# tt_array1[index2]=apple [root@oldboy ~]# tt_array1[index3]=orange [root@oldboy ~]# tt_array1[index4]=peach 給關聯數組一次賦多個值 [root@oldboy ~]#tt_array2=([index1]=tom [index2]=jack [index3]=alice ) (3)查看關聯數組 [root@oldboy ~]#declare -A (4)訪問數據元數 訪問數組中的第二個元數 [root@oldboy ~]# echo ${tt_array2[index2]} jack 訪問數組中全部元數,等同於 echo${array1[*]} [root@oldboy ~]# echo ${tt_array2[@]} tom jack alice 訪問數組中全部元數索引 [root@oldboy ~]# echo ${!tt_array2[@]} index1 index2 index3 4.遍歷數組 經過數字元數的索引進行遍歷(推薦) 注意:將統計的對象做爲數組的索引,僅針對關聯數組 實例1.統計/etc/passwd的shell數量 cat /etc/passwd | awk -F ‘.’ ‘{print $NF}’ |sort|uniq -c [root@oldboy ~]# cat array_passwd_count.sh #!/bin/bash declare -A array_passwd (1)對數組進行賦值 while read line do type=$(echo $line |awk -F ‘.’ ‘{print $NF}’) let array_passwd[$type]++ done </etc/passwd (2)對數組進行遍歷 for i in ${!array_passwd[@]} do echo 「shell:$i,eount: ${array_passwd[$i]}」 done 實例2.統計Nginx日誌IP訪問次數 cat /etc/httpd/logs/access_log | awk '{print $1}'| sort|uniq -c [root@oldboy ~]# cat array_nginx_count.sh #!/bin/bash # nginx log top 10 IP conut declare -A array_nginx #1.給關聯數組的索引進行賦值 while read line do type=$(echo $line|awk '{print $1}') let array_nginx[$type]++ done </var/log/nginx/access.log
for i in ${!array_nginx[@]} do echo "IP是:$i 出現多少次${array_nginx[$i]}" done 實例3.統計TCP的狀態信息 [root@oldboy ~]# cat array_tcp_state.sh #!/bin/bash declare -A array_tcp type=$(ss -an |grep :80|awk '{print $1}') #1.對數組進行的索引賦值 for i in $type do let array_tcp[$i]++ done #2.遍歷數組 for j in ${!array_tcp[@]} do echo "當前的狀態是:$j,當前狀態出現了多少次:${array_tcp[$j]}" done
當前的狀態是:ESTAB,當前狀態出現了多少次:325 當前的狀態是:CLOSE-WAIT,當前狀態出現了多少次:35 當前的狀態是:TIME-WAIT,當前狀態出現了多少次:14017 當前的狀態是:SYN-RECV,當前狀態出現了多少次:21 當前的狀態是:FIN-WAIT-1,當前狀態出現了多少次:37 當前的狀態是:LISTEN,當前狀態出現了多少次:1 |
shell編程第八天
一.shell正則應用
正則表達式介紹: 正則表達式`regular expression`, RE是一種字符模式,用於在查找過程當中匹配指定的字符。 在大多數程序裏,正則表達式都被置於兩個正斜槓之間;例如`/l[oO]ve/`就是由正斜槓界定的正則表達式,它將匹配被查找的行中任何位置出現的相同模式。在正則表達式中,元字符是最重要的概念。 正則表達式的做用
正則表達式注意事項
|
二. 基礎正則表達式
元字符意義BRE,正則表達式時間就是一些特殊字符,賦予了它特定的含義 字符匹配: . :匹配任單個字符; [ ]:匹配指定範圍內的任意當個字符; [^]:匹配指定範圍外的任意單個字符; [a-z]:匹配全部小寫自字母 [A-Z]:匹配全部大寫字母 [0-9]:匹配全部數字 [a-z0-9]:匹配字母和數字 [abcd]:匹配括號裏有的字母 匹配次數:用子啊要指定其出現的次數的字符的後面,用於如今其前面字符出現的次數; *:匹配其前面的字符任意次:0,1,屢次: 例如:grep 「x*y」 abxy,aby,xxxxy,yad .*:匹配任意長度的任意字符; \?:匹配其前面的字符0次或1次,也就是說其前面的字符是無關緊要的; \+:匹配其前面的字符1次或屢次,也就是說其前面的字符至少出現1次; \{m\}:匹配其前面的字符m次; \{m,n\}:匹配其前面的字符至少m次,至多n次; \{0,n\}:至多n次; \{m,\}:至少m次; 位置錨定: ^:行首錨定;用於模式的最左側; $:行尾錨定;用於模式的最右側; ^PATTERN$:用PATTERN來匹配整行; ^$:空白行; ^[[:space:]]*$:空行或包含空白字符的行; 單詞:非特殊字符組成的連續字符串都稱爲單詞; \<或\b:詞首錨定,用於單詞的左側; \>或\b:詞尾錨定,用於單詞的右側; \<PATHERN\>:匹配完整單詞; |
三. 擴展正則表達式
擴展正則表達式:ERE,egrep,grep -E 擴展正則表達式的元字符: 字符匹配: .:匹配任意單個字符; []:匹配指定範圍內的任意單個字符; [^]:匹配指定範圍外的任意單個字符; 次數匹配: *:匹配其前面的字符任意次:0,1,屢次; .*:匹配任意長度的任意字符; ?:匹配其前面的字符0次或1次,也就是說其前面的字符是無關緊要的; +:匹配其前面的字符1次或屢次,也就是說其前面的字符至少出現1次 {m}:匹配其前面的字符m次; {m,n}:匹配其前面的字符至少m次,至多n次; {0,n}:至多n次; {m,}:至少m次; 位置錨定: ^:行首錨定;用於模式的最左側; $:行尾錨定;用於模式的最右側; ^PATTERN$:用PATTERN來匹配整行; ^$:空白行; ^[[:space:]]*$:空行或包含空白字符的行; \<PATTERN或\b:詞首錨定,用於單詞的左側; PATTERN\>或\b:詞尾錨定,用於單詞的右側; \<PATHERN\>:匹配完整單詞; |
四. 正則表達式實戰
I am oldboy teacher! I teach linux. test
I like badminton ball ,billiard ball and chinese chess! my blog is http://oldboy.blog.51cto.com our site is http://www.oldboy.com my qq num is 191868516. not 191886888516. //過濾以m開頭的行 [root@Shell ~]# grep "^m" test.txt my blog is http://oldboy.blog.51cto.com my qq num is 191868516. [root@Shell ~]# grep "m$" test.txt my blog is http://oldboy.blog.51cto.com our site is http://www.oldboyedu.com //排除空行, 並打印行號 [root@student ~]# grep -vn "^$" oldboy.txt //匹配任意一個字符,不包括空行 [root@student ~]# grep "." oldboy.txt //.匹配全部 [root@student ~]# grep ".*" oldboy.txt //匹配單個任意字符 [root@node1 ~]# grep "oldboy.i" oldboy.txt //以點結尾的 [root@student ~]# grep "\.$" oldboy.txt //精確匹配到 [root@student ~]# grep -o "8*" oldboy.txt //匹配有abc的行 [root@student ~]# grep "[abc]" oldboy.txt //匹配數字所在的行"[^0-9]" [root@student ~]# grep "[0-9]" oldboy.txt //匹配全部小寫字母[^a-z] [root@student ~]# grep "[a-z]" oldboy.txt //重複0三次 [root@student ~]# grep "8\{3\}" oldboy.txt //重複3個000不用轉義符 [root@student ~]# grep -E "8{3}" oldboy.txt //重複數字8, 3-5次 [root@student ~]# grep -E "8{3,5}" test.txt //至少1次或1次以上 [root@student ~]# grep -E "8{1,}" oldboy.txt |
五. sed文本處理
sed是一個流編輯器, 非交互式的編輯器,它一次處理一行內容. 處理時,把當前處理的行存儲在臨時緩衝區中,稱爲「模式空間」(pattern space) 接着用 sed 命令處理緩衝區中的內容,處理完成後, 把緩衝區的內容送往屏幕。 接着處理下一行,這樣不斷重複,直到文件末尾。 文件內容並無改變,除非你 使用重定向存儲輸出。 Sed 要用來自動編輯一個或多個文件;簡化對文件的反覆操做;編寫轉換程序等。 1.sed命令格式 sed [options] 'command' file(s) sed正則使用 與 grep同樣,sed 在文件中查找模式時也可使用正則表達式(RE)和各類元字符。 正則表達式是括在斜槓間的模式,用於查找和替換,如下是sed支持的元字符。 使用基本元字符集 , $, ., *, [], < >, (), {} 使用擴展元字符集 ?, +, { }, |, ( ) 使用擴展元字符的方式 + sed -r 2.sed命令示例 sed對指定行進行操做,包括打印、刪除、修改、追加等。 sed選項參數 -e 容許多項編輯 -n 取消默認的輸出 -i 直接修改對應文件 -r 支持擴展元字符 sed命令參數 a 在當前行後添加一行或多行 c 在當前行進行替換修改 d 在當前行進行刪除操做 i 在當前行以前插入文本 p 打印匹配的行或指定行 n 讀入下一輸入行,從下一條命令進行處理 ! 對所選行之外的全部行應用命令 h 把模式空間裏的內容重定向到暫存緩衝區 H 把模式空間裏的內容追加到暫存緩衝區 g 取出暫存緩衝區的內容,將其複製到模式空間,覆蓋該處原有內容 G 取出暫存緩衝區的內容,將其複製到模式空間,追加在原有內容後面 多重編輯選項e 例: //先刪除行,而後管道給後面的sed進行替換 [root@Shell ~]# sed '1,9d' passwd |sed 's#root#alex#g' //使用-e進行屢次編輯修改操做 [root@Shell ~]# sed -e '1,9d' -e 's#root#alex#g' passwd
打印命令p
//打印匹配halt的行 [root@Shell ~]# sed -n '/halt/p' passwd halt:x:7:0:halt:/sbin:/sbin/halt //打印第二行的內容 [root@Shell ~]# sed -n '2p' passwd bin:x:1:1:bin:/bin:/sbin/nologin //打印最後一行 [root@Shell ~]# sed -n '$p' passwd
追加命令a //給30行添加配置 \t tab鍵(須要轉義) \n 換行符 [root@Shell ~]# sed -i '30a listen 80;' passwd 修改命令c //指定某行進行內容替換 [root@Shell ~]# sed -i '7c SELINUX=Disabled' /etc/selinux/config //正則匹配對應內容, 而後進行替換 sed -i '/^SELINUX=/cSELINUX=Disabled' /etc/selinux/config //非交互式修改指定的配置文件 [root@Shell ~]# sed -ri '/UseDNS/cUseDNS no' /etc/ssh/sshd_config [root@Shell ~]# sed -ri '/GSSAPIAuthentication/c#GSSAPIAuthentication no' /etc/ssh/sshd_config [root@Shell ~]# sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config 刪除命令d //指定刪除第三行, 但不會改變文件內容 [root@Shell ~]# sed '3d' passwd [root@Shell ~]# sed '3{d}' passwd //從第三行刪除到最後一行 [root@Shell ~]# sed '3,$d' passwd //刪除最後一行 [root@Shell ~]# sed '$d' passwd //刪除全部的行 [root@Shell ~]# sed '1,$d' passwd //匹配正則進行該行刪除 [root@Shell ~]# sed '/mail/d' passwd 插入命令i //在文件的某一行上面添加內容 [root@Shell ~]# sed -i '30i listen 80;' passwd
寫文件命令w //將匹配到的行寫入到新文件中 [root@Shell ~]# sed -n '/root/w newfile' passwd
//將passwd文件的第二行寫入到newfile中 [root@Shell ~]# sed -n '2w newfile' passwd 獲取下一行命令n //匹配root的行, 刪除root行的下一列 [root@Shell ~]# sed '/root/{n;d}' passwd
//替換匹配root行的下一列 [root@Shell ~]# sed '/root/{n; s/bin/test/}' passwd
暫存和取用命令h H g G
//將第一行的寫入到暫存區, 替換最後一行的內容 [root@Shell ~]# sed '1h;$g' /etc/hosts //將第一行的寫入到暫存區, 替換最後一行的內容 [root@Shell ~]# sed '1h;$g' /etc/hosts
//將第一行的寫入到暫存區, 在最後一行調用暫存區的內容 [root@Shell ~]# sed '1h;$G' /etc/hosts
//將第一行的內容刪除但保留至暫存區, 在最後一行調用暫存區內容追加至於尾部 [root@Shell ~]# sed -r '1{h;d};$G' /etc/hosts //將第一行的寫入到暫存區, 在最後一行調用暫存區的內容 [root@Shell ~]# sed '1h;$G' /etc/hosts
//將第一行的內容刪除但保留至暫存區, 在最後一行調用暫存區內容追加至於尾部 [root@Shell ~]# sed -r '1{h;d};$G' /etc/hosts
//將第一行的內容寫入至暫存區, 從第二行開始進行重定向替換 [root@Shell ~]# sed -r '1h;2,$g' /etc/hosts
//將第一行重定向至暫存區, 2-3行追加至暫存區, 最後追加調用暫存區的內容 [root@Shell ~]# sed -r '1h; 2,3H; $G' /etc/hosts
反向選擇命令!
//除了第三行,其餘所有刪除 [root@Shell ~]# sed -r '3!d' /etc/hosts |
六. sed匹配替換
s 替換命令標誌 g 行內全局替換 i 忽略替換大小寫 替換命令s //替換每行出現的第一個root [root@Shell ~]# sed 's/root/alice/' passwd //替換以root開頭的行 [root@Shell ~]# sed 's/^root/alice/' passwd //查找匹配到的行, 在匹配的行後面添加內容 [root@Shell ~]# sed -r 's/[0-9][0-9]$/& .5/' passwd
//匹配包含有root的行進行替換 [root@Shell ~]# sed -r 's/root/alice/g' passwd //匹配包含有root的行進行替換,忽略大小寫 # sed -r 's/root/alice/gi' /etc/passwd
//後向引用 [root@Shell ~]# sed -r 's#(Roo)#\1-alice#g' /etc/passwd [root@Shell ~]# ifconfig eth0|sed -n '2p'|sed -r 's#(^.*et) (.*) (net.*$)#\2#g'
//示例 [root@bgx ~]# vim a.txt /etc/abc/456 etc //刪除文本中的內容,需加轉義 [root@Shell ~]# sed -r '\/etc\/abc\/456/d' a.txt //若是碰到/符號, 建議使用#符替換 [root@Shell ~]# sed -r 's#/etc/abc/456#/dev/null#g' a.txt [root@Shell ~]# sed -r 's@/etc/abc/456@/dev/null@' a.txt 刪除文件 //刪除配置文件中#號開頭的註釋行, 若是碰到tab或空格是沒法刪除 [root@Shell ~]# sed '/^#/d' file //刪除配置文件中含有tab鍵的註釋行 [root@Shell ~]# sed -r '/^[ \t]*#/d' file //刪除無內容空行 [root@Shell ~]# sed -r '/^[ \t]*$/d' file
//刪除註釋行及空行 [root@Shell ~]# sed -r '/^[ \t]*#/d; /^[ \t]*$/d' /etc/vsftpd/vsftpd.conf [root@Shell ~]# sed -r '/^[ \t]*#|^[ \t]*$/d' /etc/vsftpd/vsftpd.conf [root@Shell ~]# sed -r '/^[ \t]*($|#)/d' /etc/vsftpd/vsftpd.conf 給文件行添加註釋 //將第二行到第六行加上註釋信息 [root@Shell ~]# sed '2,6s/^/#/' passwd
//將第二行到第六行最前面添加#註釋符 [root@Shell ~]# sed -r '2,6s/.*/#&/' passwd
//添加#註釋符 [root@Shell ~]# sed -r '3,$ s/^#*/#/' passwd # sed -r '30,50s/^[ \t]*#*/#/' /etc/nginx.conf # sed -r '2,8s/^[ \t#]*/#/' /etc/nginx.conf |
七. awk文本處理
awk是一種編程語言,用於在`linux/unix`下對文本和數據進行處理。 awk數據能夠來自標準輸入、一個或多個文件,或其它命令的輸出。 awk一般是配合腳本進行使用, 是一個強大的文本處理工具。
awk 的處理文本和數據的方式以下:
1.進行逐行掃描文件, 從第一行到最後一行 2.尋找匹配的特定模式的行,在行上進行操做 3.若是沒有指定處理動做,則把匹配的行顯示到標準輸出 4.若是沒有指定模式,則全部被操做的行都被處理 awk 的兩種形式語法格式
awk [options] 'commands' filenames awk [options] -f awk-script-file filenames
options -F 定義輸入字段分隔符,默認的分隔符是空格或tab鍵 command BEGIN{} {} END{} 行處理前 行處理 行處理後 [root@Shell ~]# awk 'BEGIN{print 1/2} {print "ok"} END {print "Game Over"}' /etc/hosts 0.5 ok ok ok Game Over awk命令格式 //awk 'pattern' filename 匹配文件 [root@Shell ~]# awk '/root/' /etc/passwd
//awk '{action}' filename 對文件行進行動做處理 [root@Shell ~]# awk -F: '{print $1}' /etc/passwd cut -d: -f1
//awk 'pattern {action}' filename 匹配+處理動做 [root@Shell ~]# awk -F ':' '/root/ {print $1,$3}' /etc/passwd [root@Shell ~]# awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd
//command |awk 'pattern {action}' //判斷大於多少則輸出什麼內容 [root@Shell ~]# df |awk '/\/$/ {if ($3>50000) print $4}' |
八. awk工做原理
# awk -F: '{print $1,$3}' /etc/passwd 1.awk使用一行做爲輸入,並將這一行賦給內部變量$0每一行也可稱爲一個記錄,以換行符結束 2.awk進行字段分解,每一個字段存儲在已編號的變量中,從$1開始 3.awk默認狀況下的分隔符是空格, 是由內部變量FS來肯定字段分隔符。初始FS爲空格 4.awk打印字段,將以設置的方法使用print函數打印 5.awk在打印的字段間加上空格,由於$1,$3 之間有一個逗號。逗號它映射爲另外一個內部變量,稱爲輸出字段分隔符OFS默認爲空格 6.awk輸出以後,將從文件中獲取另外一行,並將其存儲在$0中,覆蓋原來的內容,而後將新的字符串分隔成字段並進行處理。該過程將持續到全部行處理完畢
### 4.2Awk內部變量 `$0`保存當前記錄的內容 [root@Shell ~]# awk '{print $0}' /etc/passwd
`NR`控制輸入的總行數 //打印整個文本的行號 [root@Shell ~]# awk '{print NR,$0}' /etc/passwd //打印文件的前三行 [root@Shell ~]# awk 'NR<=3' /etc/passwd
`FNR`記錄輸入文件的編號 [root@Shell ~]# awk '{print FNR,$0}' /etc/passwd /etc/hosts NF保存行的最後一列內容 [root@Shell ~]# awk -F ":" '{print $1,$NF}' /etc/passwd
`FS`指定字段分割符,默認空格 //以冒號做爲字段分隔符 [root@Shell ~]# awk -F: '/root/{print $1, $3}' /etc/passwd [root@Shell ~]# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd //以空格冒號tab做爲字段分割 [root@Shell ~]# awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd
`OFS`輸出字段分隔符 //,映射爲OFS,初始狀況下OFS變量是空格 [root@Shell ~]# awk -F: '/root/{print $1,$2,$3,$4}' /etc/passwd [root@Shell ~]# awk 'BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2,$3}' /etc/passwd
`RS`輸入記錄分隔符,默認爲換行符 [root@Shell ~]# awk -F: 'BEGIN{RS=" "} {print $0}' /etc/hosts
`ORS`將文件每一行合併爲一行,以空格爲分割 [root@Shell ~]# awk -F: 'BEGIN{ORS=" "} {print $0}' /etc/hosts
//一般狀況下讓輸出分隔符爲換行符, 而後依次打印響應的字段 [root@Shell ~]# awk -F ":" 'BEGIN{OFS="\n"}{print $1,$2,$3,$4,$5,$6,$7}' passwd //將RS記錄值標記爲冒號分割, 打印後至關於將每行的內容進行切割 [root@Shell ~]# awk 'BEGIN{RS=":"}{print $0}' passwd
`print`格式化輸出函數 [root@Shell ~]# date|awk '{print $2,"5月份""\n",$NF,"今年"}' [root@Shell ~]# awk -F: '{print "用戶是:" $1 "\t 用戶uid:" $3 "\t 用戶gid:" $4}' /etc/passwd
printf 函數 [root@Shell ~]# awk -F: '{printf "%-15s %-10s %-15s\n", $1, $2, $3}' /etc/passwd %s 字符類型 %d 數值類型 佔 15 字符 - 表示左對齊,默認是右對齊 printf 默認不會在行尾自動換行,加\n |
九. awk模式動做
awk語句都由模式和動做組成。 模式部分決定動做語句什麼時候觸發及觸發事件。 若是省略模式部分,動做將時刻保持執行狀態。模式能夠是條件語句或複合語句或正則表達式。 1.awk正則表達式 //匹配記錄(整行) [root@Shell ~]# awk '/^root/' /etc/passwd [root@Shell ~]# awk '$0 ~ /^root/' /etc/passwd
//匹配字段:匹配操做符(~ !~) [root@Shell ~]# awk '!/^root/' /etc/passwd [root@Shell ~]# awk '$0 ~ !/^root/' /etc/passwd 2.比較表達式 比較表達式採用對文本進行比較,只有當條件爲真,才執行指定的動做。 比較表達式使用關係運算符,用於比較數字與字符串。 關係運算符 |運算符 |含義 |示例 |:---|:----|:---- |< |小於 |x<y |<= | 小於或等於 | x<=y |= |等於 |x==y |!= |不等於 |x!=y |>= |大於等於 | x>=y |> | 大於 |x>y //uid爲0的列出來 [root@Shell ~]# awk -F ":" '$3==0' /etc/passwd //uid小於10的所有列出來 [root@Shell ~]# awk -F: '$3 < 10' /etc/passwd //用戶登錄的shell等於/bin/bash [root@Shell ~]# awk -F: '$7 == "/bin/bash" ' /etc/passwd //第一列爲alice的列出來 [root@Shell ~]# awk -F: '$1 == "alice" ' /etc/passwd //爲alice的用戶列出來 [root@Shell ~]# awk -F: '$1 ~ /alice/ ' /etc/passwd [root@Shell ~]# awk -F: '$1 !~ /alice/ ' /etc/passwd //磁盤使用率大於多少則,則打印可用的值 [root@Shell ~]# df |awk '/\/$/'|awk '$3>1000000 {print $4}'
|
十. awk條件表達式
[root@Shell ~]# awk -F: '$3>300 {print $0}' /etc/passwd [root@Shell ~]# awk -F: '{if($3>300) print $0}' /etc/passwd [root@Shell ~]# awk -F: '{if($3>5555){print $3} else {print $1}}' /etc/passwd |
十一. 運算表達式
[root@Shell ~]# awk -F: '$3 * 10 > 500000' /etc/passwd [root@Shell ~]# awk -F: 'BEGIN{OFS="--"} { if($3*10>50000) {print $1,$3} } END {print "打印ok"}' /etc/passwd [root@Shell ~]# awk '/southem/{print $5 + 10}' datafile [root@Shell ~]# awk '/southem/{print $5 + 10.56}' datafile [root@Shell ~]# awk '/southem/{print $8 - 10}' datafile [root@Shell ~]# awk '/southem/{print $8 / 2 }' datafile [root@Shell ~]# awk '/southem/{print $8 * 2 }' datafile [root@Shell ~]# awk '/southem/{print $8 % 2 }' datafile |
十二. 邏輯操做符和複合模式
&& 邏輯與 || 邏輯或 ! 邏輯非
//匹配用戶名爲root而且打印uid小於15的行 [root@Shell ~]# awk -F: '$1~/root/ && $3<=15' /etc/passwd //匹配用戶名爲root或uid大於5000 [root@Shell ~]# awk -F: '$1~/root/ || $3>=5000' /etc/passwd awk示例1 # awk '/west/' datafile # awk '/^north/' datafile # awk '$3 ~ /^north/' datafile # awk '/^(no|so)/' datafile # awk '{print $3,$2}' datafile # awk '{print $3 $2}' datafile # awk '{print $0}' datafile # awk '{print "Number of fields: "NF}' datafile # awk '/northeast/{print $3,$2}' datafile # awk '/^[ns]/{print $1}' datafile # awk '$5 ~ /\. [7-9]+/' datafile # awk '$2 !~ /E/{print $1,$2}' datafile # awk '$3 ~ /^Joel/{print $3 "is a nice boy."}' datafile # awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile # awk '$4 ~ /Chin$/{print "The price is $" $8 "."}' datafile # awk '/Tj/{print $0}' datafile # awk -F: '{print "Number of fields: "NF}' /etc/passwd # awk -F"[ :]" '{print NF}' /etc/passwd awk示例2 [root@Shell ~]# cat b.txt bgx oldboy:is a:good boy!
[root@Shell ~]# awk '{print NF}' b.txt 4 [root@Shell ~]# awk -F ':' '{print NF}' b.txt 3 [root@Shell ~]# awk -F"[ :]" '{print NF}' b.txt 6
|
十三. Awk條件判斷
`if`語句格式:
{ if(表達式){語句;語句;... }}
//打印當前管理員用戶名稱 [root@Shell ~]# awk -F: '{ if($3==0){print $1 "is adminisitrator"} }' /etc/passwd //統計系統用戶數量 [root@Shell ~]# awk -F: '{ if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd //統計普通用戶數量 [root@Shell ~]# awk -F: '{ if($3>1000){i++}} END {print i}' /etc/passwd
`if...else` 語句格式: {if(表達式){語句;語句;... }else{語句;語句;...}} # awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd # awk -F: '{if($3==0) {count++} else{i++} }' /etc/passwd # awk -F: '{if($3==0){count++} else{i++}} END{print " 管理員個數: "count ; print " 系統用戶數: "i}' /etc/passwd
`if...else if...else` 語句格式: {if(表達式 1){語句;語句;... }else if(表達式 2){語句;語句;. .. }else{語句;語句;... }}
[root@Shell ~]# awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print i;print j;print k}' /etc/passwd [root@Shell ~]# awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print "管理員個數"i; print "系統用戶個數" j; print "系統用戶個 數" }' /etc/passwd 管理員個數1 系統用戶個數29 系統用戶個數69 |
十四. awk 循環語句
while循環 [root@Shell ~]# awk 'BEGIN{ i=1; while(i<=10){print i; i++} }' [root@Shell ~]# awk -F: '{i=1; while(i<=NF){print $i; i++}}' /etc/passwd [root@Shell ~]# awk -F: '{i=1; while(i<=10) {print $0; i++}}' /etc/passwd [root@Shell ~]#cat b.txt 111 222 333 444 555 666 777 888 999 [root@Shell ~]# awk '{i=1; while(i<=NF){print $i; i++}}' b.txt
for循環 //C 風格 for [root@Shell ~]# awk 'BEGIN{for(i=1;i<=5;i++){print i} }' //將每行打印 10 次 [root@Shell ~]# awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd [root@Shell ~]# awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd [root@Shell ~]# awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' passwd |
十五. awk數組實戰
[root@Shell ~]# awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd [root@Shell ~]# awk -F: '{username[i++]=$1} END{print username[1]}' /etc/passwd [root@Shell ~]# awk -F: '{username[i++]=$1} END{print username[0]}' /etc/passwd >注意:將須要統計的某個字段做爲數組的索引,最後對索引進行遍歷 1.按索引遍歷 [root@Shell ~]# awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd [root@Shell ~]# awk -F: '{username[++x]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd 2.統計`/etc/passwd` 中各類類型 shell 的數量 # awk -F: '{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }' /etc/passwd 3.網站訪問狀態統計<當前時實狀態ss> [root@Shell ~]# ss -an|awk '/:80/{tcp[$2]++} END {for(i in tcp){print i,tcp[i]}}' 4.統計當前訪問的每一個IP的數量<當前時實狀態 netstat,ss> [root@Shell ~]# ss -an|awk -F ':' '/:80/{ips[$(NF-1)]++} END {for(i in ips){print i,ips[i]}}' |
十六. Awk數組案例
Nginx日誌分析,日誌格式以下: log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
52.55.21.59 - - [25/Jan/2018:14:55:36 +0800] "GET /feed/ HTTP/1.1" 404 162 "https://www.google.com/" "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52" "-"
1.統計2018年01月25日,當天的PV量 [root@Shell ~]# grep "25/Jan/2018" log.bjstack.log |wc -l [root@Shell ~]# awk "/25\/Jan\/2018/" log.bjstack.log |wc -l [root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips) {sum+=ips[i]} {print sum}}' log.bjstack.log //統計15-19點的pv量 [root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00 {print $0}"' log.bjstack.log |wc -l
2.統計2018年01月25日,一天內訪問最多的10個IP [root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){ print ips[i],i}}' log.bjstack.log |sort -rn|head //統計15-19點訪問次數最多的10個IP [root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00"' log.bjstack.log |awk '{ips[$1]++} END {for(i in ips){print ips[i],i}}'|sort -rn|head
3.統計2018年01月25日,訪問大於100次的IP [root@Shell ~]# awk '/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){if(ips[i]>10){print i,ips[i]}}}' log.bjstack.log
4.統計2018年01月25日,訪問最多的10個頁面($request top 10) [root@Shell ~]# awk '/25\/Jan\/2018/ {request[$7]++} END {for(i in request){print request[i],i}}' log.bjstack.log |sort -rn|head
5.統計2018年01月25日,每一個URL訪問內容總大小($body_bytes_sent) [root@Shell ~]# awk '/25\/Jan\/2018/ {request[$7]++;size[$7]+=$10} END {for(i in request){print request[i],i,size[i]}}' log.bjstack.log |sort -rn|head
6.統計2018年01月25日,每一個IP訪問狀態碼數量($status) [root@Shell ~]# awk '{ip_code[$1 " " $9]++} END {for(i in ip_code){print ip_code[i],i}}' log.bjstack.log|sort -rn|head
7.統計2018年01月25日,訪問狀態碼爲404及出現的次數($status) [root@Shell ~]# grep "404" log.bjstack.log |wc -l [root@Shell ~]# awk '{if($9=="404") code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
8.統計2018年01月25日,8:30-9:00訪問狀態碼是404 [root@Shell ~]# awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00" && $9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log [root@Shell ~]# awk '$9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log
9.統計2018年01月25日,各類狀態碼數量 [root@Shell ~]# awk '{code[$9]++} END {for(i in code){print i,code[i]}}' log.bjstack.log [root@Shell ~]# awk '{if($9>=100 && $9<200) {i++} else if ($9>=200 && $9<300) {j++} else if ($9>=300 && $9<400) {k++} else if ($9>=400 && $9<500) {n++} else if($9>=500) {p++}} END{print i,j,k,n,p,i+j+k+n+p}' log.bjstack.log
[root@Shell ~]# awk '{if($9>=100 && $9<200) {i++} else if ($9>=200 && $9<300) {j++} else if ($9>=300 && $9<400) {k++} else if ($9>=400 && $9<500) {n++} else if($9>=500) {p++}} END{print i?i:0,j?j:0,k?k:0,n?n:0,p?p:0,i+j+k+n+p}' log.bjstack.log |