set nocompatible set history=100 filetype on filetype plugin on filetype indent on set autoread set mouse=c syntax enable set cursorline hi cursorline guibg=#00ff00 hi CursorColumn guibg=#00ff00 set foldenable set foldmethod=manual set foldcolumn=0 setlocal foldlevel=3 set foldclose=all nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc' : 'zo')<CR> set expandtab set tabstop=4 set shiftwidth=4 set softtabstop=4 set smarttab set ai set si set wrap set sw=4 set wildmenu set ruler set cmdheight=1 set lz set backspace=eol,start,indent set whichwrap+=<,>,h,l set magic set noerrorbells set novisualbell set showmatch set mat=4 set hlsearch set ignorecase set encoding=utf-8 set fileencodings=utf-8 set termencoding=utf-8 set smartindent set cin set showmatch set guioptions-=T set guioptions-=m set vb t_vb= set laststatus=4 set pastetoggle=<F9> set background=dark highlight Search ctermbg=black ctermfg=white guifg=white guibg=black autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") == 'sh' call setline(1, "#!/bin/bash") call setline(2, "##############################################################") call setline(3, "# File Name: ".expand("%")) call setline(4, "# Version: V1.0") call setline(5, "# Author: neo") # 做者 call setline(6, "# Organization: anonymous") # 公司名 call setline(7, "# Created Time : ".strftime("%F %T")) call setline(8, "# Description:") call setline(9, "##############################################################") endif endfunc
# 一、單分支if條件句語法: if 條件表達式 then 指令 fi # 二、雙分支if條件句語法: if 條件表達式 then 指令 else 指令 fi # 三、多分支if條件句語法: if 條件表達式1 then 指令1 elif 條件表達式2 then 指令2 else 指令3 fi # if條件單分支與條件測試編程對比實踐: # 例1:若是不存在 /backup 目錄就建立 #!/bin/bash path="/backup" [ -d $path ] || mkdir /backup -p if [ -d $path ] then : # shell 中 , : 表示什麼都不作 else mkdir $path -p fi [ ! -d $path ] && mkdir $path -p if [ ! -d $path ] then mkdir $path -p fi # 例2:開發shell腳本判斷系統剩餘內存的大小,若是低於 100MB 就提示內存不足,不然提示內存充足 # 分析: 1)提取系統內存 2) if進行判斷 # 獲取內存的命令: free -m [root@m01 ~]# free -m total used free shared buffers cached Mem: 474 214 259 0 78 33 -/+ buffers/cache: 102 371 Swap: 767 0 767 [root@m01 ~]# # linux默認把剩餘的內存都看成 buffers/cache 對待,因此上面的 371 就表示剩餘的內存(單位是 MB) # 取出 剩餘內存371的方法以下: [root@m01 ~]# free -m|awk 'NR==3{print $4}' 371 [root@m01 ~]# free -m|awk 'NR==3{print $NF}' # $NF 表示的最後一個Field(列),即輸出最後一個字段的內容 371 # 例題2的示例: [root@m01 practice]# cat get_memory_size.sh #!/bin/bash ############################################################## # File Name: get_memory_size.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-27 23:38:55 # Description: ############################################################## mem=`free -m|awk 'NR==3{print $NF}'` if [ $mem -lt 100 ] then echo "memory insufficient" else echo "memory is sufficient" fi [root@m01 practice]# bash get_memory_size.sh memory is sufficient # 注意: read 讀入沒辦法用 $#
函數的概念與做用:java
函數的做用就是將程序裏屢次被調用的相同代碼組合起來(函數體),併爲其取個名字(即函數名),其它全部想重複調用這部分代碼的地方都只 須要調用這個名字就能夠了。當須要修改這部分重複代碼時,也只須要改變函數體內的一部分代碼便可實現全部調用的修改,也能夠把函數獨立寫 到文件裏,當須要調用函數時,再加載進來使用。 # shell函數的優點: 1. 把相同的程序段定義成函數,能夠減小整個程序的代碼量,提高開發效率 2. 增長程序的可讀、易讀性,提高管理效率 3. 能夠實現程序功能模塊化,使得程序具有通用性(可移植性) # 對於shell來講,Linux系統裏面的近2000個命令均可以說是shell的函數
# 語法1: function 函數名(){ 指令集 return 返回值 } # 語法2: function 函數名 { # 這種定義方式時, 函數名 和 { 之間必需要有一個空格 指令集 return 返回值 } # 語法3:(推薦) 函數名(){ 指令集 return 返回值 }
shell函數的執行:linux
帶參數的函數的執行:面試
注意: 上圖中的第3條表示,$0 依然是腳本的名字,而不是函數所在腳本的名字shell
[root@m01 func]# cat func_04.sh #!/bin/bash ############################################################## # File Name: func_04.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-28 10:25:16 # Description: ############################################################## function func01(){ local i="local neo" # local 變量名 ---> 定義局部變量,該變量只能在函數內部使用 echo "I am $i" return 120 # 函數的返回值 } echo "local var val:$i" # 局部變量在函數外部不能被調用 func01 [root@m01 func]# sh func_04.sh local var val: I am local neo [root@m01 func]# echo $? # exit [<n>] 狀態碼n能夠不指定,默認是上一條命令的退出狀態碼。 120 [root@m01 func]# # 在函數內的變量最好加上 local ,即把函數內的變量定義成 局部變量,避免變量衝突
# 方法一、 wget 命令: --spider # 模擬爬蟲 -q # 安靜訪問 -o /dev/null # 不輸出 -T # --timeout 超時時間 -t # --tries 重試次數 [root@m01 func]# wget --spider -T 5 -q -o /dev/null -t 2 www.baidu.com [root@m01 func]# echo $? # 經過 echo $? 檢測 wget 的URL是否正常 0 [root@m01 func]# # 方法二、 curl 命令: -I # 看響應頭 -s # 安靜訪問 -o /dev/null # 不輸出 -w %{http_code} # 返回狀態碼;200爲正常 -m01 # 超時時間 [root@m01 func]# curl www.baidu.com -s &>/dev/null [root@m01 func]# echo $? # 也是經過查看 curl 的執行結果來判斷 URL 是否正常 0 [root@m01 func]# curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null www.baidu.com 200 # 也可經過查看 狀態碼 查看 URL 是否正常 # 示例代碼: [root@m01 func]# cat checkurl.sh #!/bin/bash ############################################################## # File Name: checkurl.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-29 09:19:34 # Description: ############################################################## function usage(){ # 輸入有誤時的函數 echo "Usage:$0 url" exit 1 } function checkurl(){ # 檢測網站是否正常的函數 wget -q -o /dev/null -t 2 -T 5 $1 if [ $? -eq 0 ] then echo "$1 is ok" else echo "$1 failed" fi } function main(){ # 至關於 入口函數 if [ $# -ne 1 ] then usage # 若是輸入的參數個數不爲1,則調用 usage 函數 fi checkurl $1 # 調用檢測url的函數 } main $* # $* :把全部的參數都傳給 main 函數 [root@m01 func]# sh checkurl.sh Usage:checkurl.sh url [root@m01 func]# sh checkurl.sh www.baidu.com 2 Usage:checkurl.sh url [root@m01 func]# sh checkurl.sh www.baidu.com www.baidu.com is ok
case結構條件句至關於多分支的 if/elif/else 條件句,可是它比這些條件句看起來更規範工整,常被用於實現系統服務啓動腳本等企業應用場景中。 # case語句的語法: case "變量" in 值1) 指令1... ;; 值2) 指令2... ;; 值3) 指令3... ;; *) 指令4... esac # 示例代碼: [root@m01 func]# cat case01.sh #!/bin/bash cat <<EOF 1. install lamp 2. install lnmp 3. exit EOF read -p "pls input an integer from above:" num # 1. 判斷是否爲數字 expr 2 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi # 判斷執行處理 case $num in 1) echo "install lamp..." ;; 2) echo "install lnmp..." ;; 3) echo "bye" exit ;; *) echo "Uage:$0 {1|2|3}" exit 1 esac [root@m01 func]# sh case01.sh 1. install lamp 2. install lnmp 3. exit pls input an integer from above:1 install lamp... [root@m01 func]# sh case01.sh 1. install lamp 2. install lnmp 3. exit pls input an integer from above:3 bye [root@m01 func]# sh case01.sh 1. install lamp 2. install lnmp 3. exit pls input an integer from above:6 Uage:case01.sh {1|2|3}
示例1:給不一樣內容加不一樣的顏色編程
[root@m01 func]# cat case02.sh #!/bin/bash ############################################################## # File Name: case02.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-06-30 23:38:25 # Description: ############################################################## red="\033[31m" green="\033[32m" yellow="\033[33m" blue="\033[34m" tail="\033[0m" function color(){ case $1 in red) echo -e "${red}$2${tail}" ;; green) echo -e "${green}$2${tail}" ;; yellow) echo -e "${blue}$2${tail}" ;; blue) echo -e "${blue}$2${tail}" ;; *) echo {Usage:$0 colorfunction color char} exit 1 esac } cat <<EOF 1.apple 2.pear 3.banana 4.cherry EOF read -p "pls input a number:" num case $num in 1) color red apple ;; 2) color green pear ;; 3) color yellow banana ;; 4) color blue cherry ;; *) echo "Usage:$0 {1|2|3|4}" exit 1 esac [root@m01 func]# sh case02.sh 1.apple 2.pear 3.banana 4.cherry pls input a number:1 apple [root@m01 func]#
示例2:開發網絡服務rsync服務的啓動腳本實踐vim
利用case語句開發Rsync服務啓動中止腳本,本例採用case語句以及新的思路來實現。數組
# 分析: 1. 啓動命令: rsync --daemon 2. 中止進程: pkill rsync killall rsync kill 進程號 # 推薦這種方式 [root@m01 ~]# rsync --daemon Failed to parse config file: /etc/rsyncd.conf # 這臺主機上沒有 rsync 環境 [root@m01 ~]# touch /etc/rsyncd.conf # 建立一個 rsyncd.conf 的空文件,就能建立一個最簡單的 rsync 環境,此時 rsync 就能啓動 [root@m01 ~]# rsync --daemon [root@m01 ~]# [root@m01 ~]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 15961 root 4u IPv4 89573 0t0 TCP *:rsync (LISTEN) # rsync 已經啓動 rsync 15961 root 5u IPv6 89574 0t0 TCP *:rsync (LISTEN) [root@m01 ~]# pkill rsync [root@m01 ~]# lsof -i:873 [root@m01 ~]# rsync --daemon [root@m01 ~]# killall rsync [root@m01 ~]# lsof -i:873 [root@m01 ~]# rsync --daemon [root@m01 ~]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16068 root 4u IPv4 90215 0t0 TCP *:rsync (LISTEN) rsync 16068 root 5u IPv6 90216 0t0 TCP *:rsync (LISTEN) [root@m01 ~]# kill 16068 [root@m01 ~]# lsof -i:873 [root@m01 ~]#
示例代碼1:基本的 rsync 啓動腳本bash
[root@m01 func]# cat rsyncd.sh #!/bin/bash ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## case "$1" in start) rsync --daemon if [ $? -eq 0 ] then echo "rsync startup ok" else echo "rsync startup failed" fi ;; stop) killall rsync if [ $? -eq 0 ] then echo "rsync stop ok" else echo "rsync stop failed" fi ;; restart) killall rsync && sleep 1 && rsync --daemon # sleep 1 ---> 中止1秒 (注意:重啓中間要停一下) if [ $? -eq 0 ] then echo "rsync restart ok" else echo "rsync restart failed" fi ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac [root@m01 func]# bash rsyncd.sh start rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16228 root 4u IPv4 91096 0t0 TCP *:rsync (LISTEN) rsync 16228 root 5u IPv6 91097 0t0 TCP *:rsync (LISTEN) [root@m01 func]# bash rsyncd.sh stop rsync stop ok [root@m01 func]# lsof -i:873 [root@m01 func]# bash rsyncd.sh start rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16259 root 4u IPv4 91271 0t0 TCP *:rsync (LISTEN) rsync 16259 root 5u IPv6 91272 0t0 TCP *:rsync (LISTEN) [root@m01 func]# bash rsyncd.sh restart rsync restart ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16265 root 4u IPv4 91312 0t0 TCP *:rsync (LISTEN) # 重啓以後 進程號發生了改變 rsync 16265 root 5u IPv6 91313 0t0 TCP *:rsync (LISTEN) [root@m01 func]#
示例代碼2:完善實用的 rsync 啓動腳本網絡
[root@m01 func]# cp rsyncd.sh rsyncd2.sh # 作備份 [root@m01 func]# cat rsyncd2.sh #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop script # 上面兩行的做用是讓腳本開機自啓動 (這兩行必須寫在腳本開頭) ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## function start(){ rsync --daemon retval=$? # 獲取上一條命令的執行結果做爲返回值; 外部須要調用這個 retval ,因此定義成全局變量 if [ $retval -eq 0 ] then echo "rsync startup ok" return $retval # 專業的腳本函數須要給 返回值 else echo "rsync startup failed" return $retval fi } function stop(){ killall rsync retval=$? if [ $retval -eq 0 ] then echo "rsync stop ok" return $retval else echo "rsync stop failed" return $retval fi } case "$1" in start) start retval=$? # 接收 start 的執行結果並賦值給 retval 做爲返回值 ;; stop) stop retval=$? ;; restart) stop && sleep 1 && start retval=$? ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac exit $retval # 把上面的執行結果返回給腳本外面 [root@m01 func]# lsof -i:873 [root@m01 func]# sh rsyncd2.sh start rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16731 root 4u IPv4 93672 0t0 TCP *:rsync (LISTEN) rsync 16731 root 5u IPv6 93673 0t0 TCP *:rsync (LISTEN) [root@m01 func]# sh rsyncd2.sh restart rsync stop ok rsync startup ok [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 16737 root 4u IPv4 93713 0t0 TCP *:rsync (LISTEN) # 重啓以後 pid 發生了變化 rsync 16737 root 5u IPv6 93714 0t0 TCP *:rsync (LISTEN) [root@m01 func]# sh rsyncd2.sh stop rsync stop ok [root@m01 func]# sh rsyncd2.sh restart rsync: no process killed rsync stop failed [root@m01 func]# echo $? 1 [root@m01 func]# [root@m01 func]# cp rsyncd2.sh /etc/init.d/rsyncd [root@m01 func]# chmod +x /etc/init.d/rsyncd # 加上執行權限 [root@m01 func]# chkconfig --list rsyncd # 此時 rsync服務 沒在開機啓動管理裏面 service rsyncd supports chkconfig, but is not referenced in any runlevel (run 'chkconfig --add rsyncd') [root@m01 func]# chkconfig --add rsyncd # 把 rsyncd 服務添加到開機啓動管理裏面 [root@m01 func]# chkconfig --list rsyncd rsyncd 0:off 1:off 2:on 3:on 4:on 5:on 6:off # 此時 rsyncd 在2345級別開機自啓動 [root@m01 func]# # 加載系統函數庫作輸出提示 [root@m01 func]# cp /etc/init.d/rsyncd{,.1} # 作備份 [root@m01 func]# cat /etc/init.d/rsyncd #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop script ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## . /etc/init.d/functions # 調用系統函數庫(用於輸出提示) function start(){ rsync --daemon retval=$? # 獲取上一條命令的執行結果做爲返回值; 外部須要調用這個 retval ,因此定義成全局變量 if [ $retval -eq 0 ] then action "rsync startup ok" /bin/true # 用於輸出提示 return $retval # 專業的腳本函數須要給 返回值 else action "rsync startup failed" /bin/false return $retval fi } function stop(){ killall rsync &>/dev/null # &>/dev/null 不要輸出(只看返回值) retval=$? if [ $retval -eq 0 ] then action "rsync stop ok" /bin/true return $retval else action "rsync stop failed" /bin/false return $retval fi } case "$1" in start) start retval=$? # 接收 start 的執行結果並賦值給 retval 做爲返回值 ;; stop) stop retval=$? ;; restart) stop && sleep 1 && start retval=$? ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac exit $retval # 把上面的執行結果返回給腳本外面 [root@m01 func]# [root@m01 func]# lsof -i:873 [root@m01 func]# /etc/init.d/rsyncd start rsync startup ok [ OK ] [root@m01 func]# /etc/init.d/rsyncd restart rsync stop ok [ OK ] rsync startup ok [ OK ] [root@m01 func]# /etc/init.d/rsyncd stop rsync stop ok [ OK ] [root@m01 func]# /etc/init.d/rsyncd restart rsync stop failed [FAILED] [root@m01 func]#
示例代碼3:和系統腳本相似的 rsync 啓動腳本app
# 分析: 1. 系統腳本啓動的時候一般會定義一個鎖文件 lockfile,當系統啓動時建立一個鎖文件(能夠一般查看有沒有這個鎖文件來判斷服務有沒有成功) 2. 當服務中止成功時,兩把鎖文件刪除 [root@m01 func]# cp /etc/init.d/rsyncd{,.2} # 先備份 [root@m01 subsys]# cat /etc/rsyncd.conf # 在 rsyncd.conf 文件中定義一個獲取 rsync服務 進程號 pid 的文件 pid file = /var/run/rsyncd.pid [root@m01 subsys]# rsync --daemon [root@m01 subsys]# cat /var/run/rsyncd.pid # 在 rsyncd.conf 中添加了 pid file 以後,啓動 rsync 服務以後,pid file 中就會保存 rsync 服務的 pid 18082 [root@m01 func]# cat /etc/init.d/rsyncd #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop script ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-01 23:34:57 # Description: ############################################################## lockfile=/var/lock/subsys/rsync # 先定義一個鎖文件 rsyncd_pid_file_path="/var/run/rsyncd.pid" # 定義 rsync 進程號的路徑 . /etc/init.d/functions function start(){ rsync --daemon &>/dev/null retval=$? if [ $retval -eq 0 ] then action "rsync startup ok" /bin/true touch $lockfile # 啓動成功後,就建立一個鎖文件 return $retval else action "rsync startup failed" /bin/false return $retval fi } function stop(){ if test -s $rsyncd_pid_file_path # -s ---> 判斷文件是否存在且不爲空 then rsyncd_pid=`cat $rsyncd_pid_file_path` if (kill -0 $rsyncd_pid &>/dev/null) # kill -0 進程號 ---> 判斷該進程號對應的服務是否存在;存在則echo $?返回0,不存在返1 then kill $rsyncd_pid retval=$? if [ $retval -eq 0 ] then action "rsync stop ok" /bin/true \rm -f $lockfile # 中止成功後就刪除鎖文件 return $retval else action "rsync stop failed" /bin/false return $retval fi else # 此種狀況是:$rsyncd_pid 對應的 rsyncd 服務不存在 action "rsyncd service is not running" return 2 fi else # 此種狀況是: $rsyncd_pid_file_path 對應的路徑不存在 action "$rsyncd_pid_file_path not exist, or rsyncd not startup" /bin/false return 3 fi } case "$1" in start) start retval=$? # 接收 start 的執行結果並賦值給 retval 做爲返回值 ;; stop) stop retval=$? ;; restart) stop && sleep 1 && start retval=$? ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac exit $retval # 把上面的執行結果返回給腳本外面 [root@m01 subsys]# lsof -i:873 [root@m01 func]# /etc/init.d/rsyncd stop /var/run/rsyncd.pid not exist, or rsyncd not startup [FAILED] [root@m01 func]# /etc/init.d/rsyncd restart /var/run/rsyncd.pid not exist, or rsyncd not startup [FAILED] [root@m01 func]# /etc/init.d/rsyncd start rsync startup ok [ OK ] [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 18740 root 4u IPv4 102100 0t0 TCP *:rsync (LISTEN) rsync 18740 root 5u IPv6 102101 0t0 TCP *:rsync (LISTEN) [root@m01 func]# /etc/init.d/rsyncd restart rsync stop ok [ OK ] rsync startup ok [ OK ] [root@m01 func]# lsof -i:873 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rsync 18764 root 4u IPv4 102183 0t0 TCP *:rsync (LISTEN) rsync 18764 root 5u IPv6 102184 0t0 TCP *:rsync (LISTEN) [root@m01 func]# /etc/init.d/rsyncd stop rsync stop ok [ OK ] [root@m01 func]#
case條件句使用總結:
# while 循環的語法: while 條件表達式 do 指令... done # 示例1:每隔2秒輸出一次系統負載(負載是系統性能的基礎重要指標)狀況 [root@m01 loop]# cat loop01.sh while true do uptime >>/tmp/uptime.log sleep 2 done # 後臺運行的命令: & 、nohup 、screen (運維人員經常使用) 常見命令: kill killall pkill ---> 殺掉進程 ps ---> 查看進程 pstree ---> 顯示進程狀態樹 top ---> 顯示進程 renice ---> 改變優先權 nohup ---> 用戶退出系統以後繼續工做(後臺運行) pgrep ---> 查找匹配條件的進程 strace ---> 跟蹤一個進程的系統調用狀況 ltrace ---> 跟蹤進程調用庫函數的狀況
while循環可能會涉及到的一些命令:
示例2:使用while循環對下面的腳本進行修改,使得當執行腳本時,每次執行完腳本之後不退出腳本了,而是繼續提示用戶輸入。
[root@m01 loop]# cat loop02.sh while true do read -p "pls input two numbers:" a b if [ -z "$b" ] then echo "pls input two numbers:" continue # continue 表示結束本次循環 fi expr 10 + $a + $b &>/dev/null if [ $? -ne 0 ] then echo "pls input two numbers:" continue fi echo "a-b=$(($a-$b))" echo "a+b=$(($a+$b))" echo "a*b=$(($a*$b))" echo "a/b=$(($a/$b))" echo "a**b=$(($a**$b))" echo "a%b=$(($a%$b))" done [root@m01 loop]#
示例3:猜數字遊戲:首先讓系統隨機生成一個數字,給這個數字定一個範圍(1-60),讓用戶輸入猜的數字,對輸入進行判斷,若是不符合要求,就給予高或低的提示,猜對後則給出猜對用的次數,用while語句實現。
# 分析: 1. 隨機數 ---> $RANDOM # $RANDOM 隨機數的範圍: 0~32767 [root@m01 loop]# echo $RANDOM 15258 [root@m01 loop]# echo $(($RANDOM%60)) # 取 0~60 之間的隨機數 10 [root@m01 loop]# cat loop03.sh #!/bin/bash ############################################################## # File Name: loop03.sh # Version: V1.0 # Author: neo # Organization: anonymous # Created Time : 2019-07-02 23:18:45 # Description: ############################################################## val="$((RANDOM%60))" count=0 while true do read -p "pls input one number:" num ((count++)) if [ -z "$num" ] then read -p "pls input one number:" num continue fi expr 10 + $num &>/dev/null if [ $? -ne 0 ] then read -p "pls input one number:" num continue fi if [ $val -gt $num ] then echo "try bigger" elif [ $val -lt $num ] then echo "try smaller" else echo "guess right" echo "count:$count" exit fi done [root@m01 loop]#
示例4: 分析Apache訪問日誌(access_2010-12-8.log),把日誌中每行的訪問字節數對應字段數字相加,計算出總的訪問量。給出實現程序,用while循環實現。
# while 循環讀取文件有3種方式(經常使用下面的前2種方式): # 方式1:在while循環結尾done經過輸入重定向指定讀取的文件。 while read line # 讀取文件內容時,是從文件由上到下讀取 do cmd # 對 line 進行處理 done<FILE # 方式2:使用cat讀取文件內容,而後經過管道進入while循環處理。 cat FILE_PATH|while read line do cmd done # 方式3:採用exec讀取文件後,而後進入while循環處理。 exec <FILE sum=0 while read line do cmd done # 讀取文件內容示例 [root@m01 ~]# seq 10 >neo.log [root@m01 ~]# cat neo.log 1 2 3 4 5 6 7 8 9 10 [root@m01 loop]# vim while-read-from-file.sh while read line do echo "$line" done</root/neo.log [root@m01 loop]# sh while-read-from-file.sh 1 2 3 4 5 6 7 8 9 10 # 示例代碼以下: [root@m01 loop]# cat loop04.sh #!/bin/bash awk '{print $10}' /root/access_2010-12-8.log|grep -v - >/tmp/count_bytes.log num=0 while read line do ((num+=line)) done</tmp/count_bytes.log echo $num [root@m01 loop]#
while循環涉及的一些命令:
for循環語句和 while 循環語句相似,但 for 循環語句主要用於執行次數有限的循環,而不是用於守護進程以及無限循環。for 循環語句常見的語法有兩種 # for循環的語法: 1)普通語法 for 變量名 in 變量取值列表 do 指令... done 2)C語言型for循環語法 for((exp1;exp2;exp3)) do 指令... done # 示例1:經過開發腳本實現僅設置 sshd rsyslog crond network sysstat 服務開機自啓動 [root@m01 loop]# cat for01.sh #!/bin/bash for service in `chkconfig |awk '!/crond|network|rsyslog|sshd|sysstat/{print $1}'` do chkconfig $service off done [root@m01 loop]# # 示例2:計算從1加到100之和 [root@m01 loop]# cat for02.sh #!/bin/bash for ((i=1;i<=100;i++)) # C語言型的 for 循環 do ((sum+=i)) done echo $sum echo =================================== for n in {1..100} do ((total+=n)) done echo $total echo =================================== for n in `seq 100` do ((amount+=n)) done echo $amount echo ================================== while ((j<=100)) do ((vol+=j)) ((j++)) done echo $vol [root@m01 loop]# echo $((100*(100+1)/2)) 5050 [root@m01 loop]# # 示例3:在Linux下批量修改文件名,將文件名中的「_finished」去掉。 # 準備測試數據: mkdir /neo -p cd /neo touch stu_102999_1_finished.jpg stu_102999_2_finished.jpg stu_102999_3_finished.jpg touch stu_102999_4_finished.jpg stu_102999_5_finished.jpg ls -l # 以下: [root@m01 ~]# mkdir /neo -p [root@m01 ~]# cd /neo [root@m01 neo]# touch stu_102999_1_finished.jpg stu_102999_2_finished.jpg stu_102999_3_finished.jpg [root@m01 neo]# touch stu_102999_4_finished.jpg stu_102999_5_finished.jpg [root@m01 neo]# ls -l total 0 -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_1_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_2_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_3_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_4_finished.jpg -rw-r--r-- 1 root root 0 Jul 3 12:06 stu_102999_5_finished.jpg # for循環腳本: [root@m01 loop]# cat loop05.sh #!/bin/bash file_path="/neo/*.jpg" for file in `ls $file_path` do mv $file ${file/_finished/} done # awk 操做 [root@m01 neo]# ls *.jpg|awk -F "_finished" '{print "mv",$0,$1$2}'|sh [root@m01 neo]# ll total 0 -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_1.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_2.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_3.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_4.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_5.jpg [root@m01 neo]# # rename 操做 # rename語法: rename [from] [to] file [root@m01 neo]# rename _finished "" *.jpg # 把文件名中的 "_finished" 改成 空 [root@m01 neo]# ll total 0 -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_1.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_2.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_3.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_4.jpg -rw-r--r-- 1 root root 0 Jul 3 14:19 stu_102999_5.jpg [root@m01 neo]#
條件與循環控制及程序返回值相關知識點:
數組也是一個變量;Shell的數組就是把有限個元素(變量或字符內容)用一個名字命名,而後用編號對它們進行區分的元素集合。 這個名字就稱爲數組名,用於區分不一樣內容的編號就稱爲數組下標。組成數組的各個元素(變量)稱爲數組的元素,有時也稱爲下標變量。 # 數組的本質仍是變量,是特殊的變量形式,如: array=(1 2 3 4 5)
# 方法1:推薦 array=(one two three four) # 方法2: array=([0]=one [1]=two [2]=three [3]=four) # 方法3: [root@m01 ~]# array[0]=one [root@m01 ~]# array[1]=2 [root@m01 ~]# array[2]=3 [root@m01 ~]# echo ${array[@]} one 2 3 [root@m01 ~]# echo ${array[*]} # 獲取全部的數組元素 one 2 3 [root@m01 ~]# 方法4:命令的結果放到數組裏,推薦。 array=(`ls /server/scripts`) # 操做數組元素 # 讀取數組內容 *** [root@m01 ~]# array=(1 2 3) [root@m01 ~]# echo ${array[0]} 1 [root@m01 ~]# echo ${array[*]} 1 2 3 [root@m01 ~]# echo ${array[@]} 1 2 3 [root@m01 ~]# echo ${#array[@]} # 數組的長度 3 [root@m01 ~]# echo ${array[4]} [root@m01 ~]# # 給數組添加內容 [root@m01 ~]# array[3]=neo [root@m01 ~]# echo ${array[*]} 1 2 3 neo [root@m01 ~]# array[3]=four # 會把數組的元素覆蓋 [root@m01 ~]# echo ${array[*]} 1 2 3 four # 會把數組的元素覆蓋 [root@m01 ~]# # 刪除數組內容 [root@m01 ~]# unset array[1] # 刪除數組下標爲1的數組元素 [root@m01 ~]# echo ${array[*]} 1 3 four [root@m01 ~]# echo ${array[2]} 3 [root@m01 ~]# # for循環數組: [root@m01 loop]# cat array_for.sh #!/bin/bash array=(1 2 3 4 5) for n in ${array[*]} do echo $n done echo ======================= for ((i=0;i<${#array[*]};i++)) # C語言型的for 循環數組;數組的下標從0開始 do echo ${array[i]} # i 是下標 done [root@m01 loop]# sh array_for.sh 1 2 3 4 5 ======================= 1 2 3 4 5 [root@m01 loop]#
# (1)定義命令 靜態數組: array=(1 2 3) 動態數組: array=($(ls)) 或 array=(`ls`) 給數組賦值: array[3]=4 (2)打印命令 打印全部元素: ${array[@]} 或 ${array[*]} 打印數組長度: ${#array[@]}或${#array[*]} 打印單個元素: ${array[i]} #<==i是數組下標
企業實踐:利用bash for循環打印下面這句話中字母數不大於6的單詞(某企業面試真題)。
I am oldboy teacher welcome to oldboy training class
[root@m01 loop]# cat loop06.sh #!/bin/bash array=(I am oldboy teacher welcome to oldboy training class) for word in ${array[*]} do if [ ${#word} -le 6 ] then echo ${word} fi done echo =================== for ((i=0;i<${#array[*]};i++)) do if [ ${#array[i]} -le 6 ] then echo ${array[i]} fi done [root@m01 loop]# sh loop06.sh I am oldboy to oldboy class =================== I am oldboy to oldboy class [root@m01 loop]#