shell腳本的格式shell
示例腳本編程
[root@ying01 shell]# vim 01.sh #!/bin/bash //頭文件 echo "123" //輸出123 ls //打開當前目錄 touch 1.txt //建立1.txt文檔 ls //再次打開當前目錄
執行腳本vim
[root@ying01 shell]# sh 01.sh 123 01.sh 01.sh 1.txt [root@ying01 shell]# ls 01.sh 1.txt
執行腳本的其餘方法:bash
/bin/sh實際是bash的軟鏈接;實際上是真正執行的是bashless
[root@ying01 shell]# ls -l /bin/bash -rwxr-xr-x. 1 root root 960472 8月 3 2017 /bin/bash [root@ying01 shell]# ls -l /bin/sh lrwxrwxrwx. 1 root root 4 5月 9 02:21 /bin/sh -> bash [root@ying01 shell]# bash 01.sh 123 01.sh 01.sh 1.txt
還有一種方式,給腳本文件增長可執行權限,也能夠執行;運維
[root@ying01 shell]# ls -l 01.sh //未有執行權 -rw-r--r-- 1 root root 41 7月 30 00:37 01.sh [root@ying01 shell]# ls 01.sh 1.txt [root@ying01 shell]# /root/shell/01.sh //權限不夠 -bash: /root/shell/01.sh: 權限不夠 [root@ying01 shell]# chmod a+x 01.sh [root@ying01 shell]# ls -l 01.sh //具備可執行權 -rwxr-xr-x 1 root root 41 7月 30 00:37 01.sh [root@ying01 shell]# /root/shell/01.sh //絕對路徑 123 01.sh 1.txt 01.sh 1.txt [root@ying01 shell]# ./01.sh //當前目錄下 123 01.sh 1.txt 01.sh 1.txt
查看腳本執行過程:** bash -x 腳本**函數
[root@ying01 shell]# sh -x 01.sh + echo 123 123 + ls 01.sh 1.txt + touch 1.txt + ls 01.sh 1.txt
查看腳本是否語法錯誤: bash -n 腳本code
[root@ying01 shell]# vim 01.sh #!/bin/bash echo "123 //把雙引號去掉 ls touch 1.txt ls [root@ying01 shell]# sh -n 01.sh //執行 檢查語法,發現雙引號沒有成對出現 01.sh:行2: 尋找匹配的 `"' 是遇到了未預期的文件結束符 01.sh:行6: 語法錯誤: 未預期的文件結尾
經常使用格式開發
- date +%Y-%m-%d, date +%y-%m-%d 年月日
- date +%H:%M:%S = date +%T 時間
- date +%s 時間戳
- date -d @1504620492
- date -d "+1day" 一天後
- date -d "-1 day" 一天前
- date -d "-1 month" 一月前
- date -d "-1 min" 一分鐘前
- date +%w, date +%W 星期
root@ying01 shell]# date //當前的日期 2018年 07月 29日 星期一 09:14:12 CST令 [root@ying01 shell]# cal //日曆 七月 2018 日 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 [root@ying01 shell]# date +%Y //大寫Y 年份 2018 [root@ying01 shell]# date +%y //小寫y 年份 18 [root@ying01 shell]# date +%m //小寫m 月份 07 [root@ying01 shell]# date +%Y%m%d //年月日 20180729 [root@ying01 shell]# date 2018年 07月 30日 星期一 09:16:35 CST [root@ying01 shell]# date +%F //大寫F 日期格式 2018-07-30 [root@ying01 shell]# date +%H //大寫H 小時 09 [root@ying01 shell]# date +%M //大寫M 分鐘 17 [root@ying01 shell]# date +%S //大寫S 秒 14 [root@ying01 shell]# date +%s //小寫s 時間戳 1532913453 [root@ying01 shell]# date +%T //大寫T 常規時間 09:17:53 [root@ying01 shell]# date "+%Y-%m-%d %H:%M:%S %w" //所有時間列出 年月日 時分秒 星期 2018-07-29 09:18:17 7 [root@ying01 shell]#
date -d選項用法文檔
[root@ying01 shell]# date -d "-1 day" //前一天的日期時間 2018年 07月 28日 星期六 09:19:12 CST [root@ying01 shell]# date -d "-1 day" +%F //帶格式的 前一天的日期時間 2018-07-29 [root@ying01 shell]# date -d "-1 month" +%F // 帶格式的 上一個月 2018-06-29 [root@ying01 shell]# date -d "-1 year" +%F //帶格式的 上一個月 2017-07-29 [root@ying01 shell]# date -d "-1 hour" +%T //上一小時的時間 08:19:54 [root@ying01 shell]# date +%s -d "2017-07-29 09:17:53" //查看其對應的時間戳 1501291073
- 當腳本中使用某個字符串較頻繁而且字符串長度很長時就應該使用變量代替(好比a=jdjjdjdddx)
- 使用條件語句時,常使用變量 if [ $a -gt 1 ]; then ... ; fi
- 引用某個命令的結果時,用變量替代 n=wc -l 1.txt
- 寫和用戶交互的腳本時,變量也是必不可少的 read -p "Input a number: " n; echo $n 若是沒寫這個n,能夠直接使用$REPLY
- 內置變量 $0, $1, $2… $0表示腳本自己,$1 第一個參數,$2 第二個 .... $#表示參數個數
- 數學運算a=1;b=2; c=$(($a+$b))或者$[$a+$b]
if命令的格式:
- 格式1:if 條件 ; then 語句; fi
- 格式2:if 條件; then 語句; else 語句; fi
- 格式3:if …; then … ;elif …; then …; else …; fi
邏輯判斷表達式:if [ $a -gt $b ]; if [ $a -lt 5 ]; if [ $b -eq 10 ]等 -gt (>); -lt(<); -ge(>=); -le(<=);-eq(==); -ne(!=) 注意處處都是空格
邏輯判斷符號:
符號 釋義 對應單詞 -gt 大於 greater than -lt 小於 ess than -ge 大於或等於 greater than or equal -le 小於或等於 less than or equal -eq 等於 equality -ne 不等於 inequality 可使用 && || 結合多個條件
- if [ $a -gt 5 ] && [ $a -lt 10 ]; then
- if [ $b -gt 5 ] || [ $b -lt 3 ]; then
[root@ying01 shell]# vim if01.sh #!/bin/bash a=2 if [ $a -lt 3 ] //變量a小於3的時候,輸出OK then echo ok fi [root@ying01 shell]# sh -x if01.sh + a=2 + '[' 2 -lt 3 ']' + echo ok ok
[root@ying01 shell]# vim if02.sh #!/bin/bash a=2 if [ $a -lt 3 ] then echo ok else echo nook fi [root@ying01 shell]# sh -x if02.sh + a=2 + '[' 2 -lt 3 ']' + echo ok ok
[root@ying01 shell]# vim if03.sh #!/bin/bash read -p "請輸入考試分數:" a if [ $a -lt 60 ] then echo "太差勁了!重考,未經過考試!" elif [ $a -gt 60 ] && [ $a -lt 85 ] then echo "還行吧!經過考試,成績良好!" else echo "恭喜你!經過考試,成績優秀! " fi [root@ying01 shell]# sh if03.sh 請輸入考試分數:48 太差勁了!重考,未經過考試! [root@ying01 shell]# sh if03.sh 請輸入考試分數:65 還行吧!經過考試,成績良好! [root@ying01 shell]# sh if03.sh 請輸入考試分數:99 恭喜你!經過考試,成績優秀!
判斷是不是普通文件,且存在: [ -f file ]
[root@ying01 shell]# vim file1.sh #! /bin/bash f="/root/ceshi" if [ -f $f ] then echo $f exist else touch $f fi [root@ying01 shell]# sh -x file1.sh + f=/root/ceshi + '[' -f /root/ceshi ']' + touch /root/ceshi [root@ying01 shell]# sh -x file1.sh + f=/root/ceshi + '[' -f /root/ceshi ']' + echo /root/ceshi exist /root/ceshi exist
判斷是不是目錄,且存在: [ -d file ]
[root@ying01 shell]# vim file2.sh #! /bin/bash f="/root/ceshi" if [ -d $f ] then echo $f exist else mkdir $f ls -ld $f fi [root@ying01 shell]# sh -x file2.sh + f=/root/ceshi + '[' -d /root/ceshi ']' + mkdir /root/ceshi + ls -ld /root/ceshi drwxr-xr-x 2 root root 6 7月 29 11:19 /root/ceshi
而且 &&
f="/root/ceshi" [ -f $f ] && rm -f $f //前一條命令執行成功纔會繼續執行以後的命令 等同於下面的表達方式 if [ -f $f ] then rm -rf $f fi
或者 ||
f="/root/ceshi" [ -f $f ] || touch $f //前面命令不成功時,執行後面的命令 等同於下面的表達方式 if [ ! -f $f ] // 「!」表示了若是這條命令不成功,就往下執行 then touch $f fi
- if [ -z "$a" ] 邏輯條件是:變量a的值爲空
- if [ -n "$a" ] 邏輯條件是:變量a的值不爲空
- if grep -q '123' 1.txt; then 邏輯條件是:1.txt中含有'123'的行
- if [ ! -e file ]; then 邏輯條件是:文件不存在
圓括號與方括號的區別:
- if (($a<1)); then … 等同於 if [ $a -lt 1 ]; then…
- [ ] 中不能使用<,>,==,!=,>=,<=這樣的符號
常見的一些用法注意:
- if -z或者if -n 都不能做用在文件上,只能做用在變量上。
- if [ -z "$a" ] 這個表示當變量a的值爲空時會怎麼樣
- !-z=-n
- !-n=-z
[root@ying01 shell]# vim file3.sh #! /bin/bash n=`wc -l /etc/passwd |awk '{print $1}'` //輸出/etc/passwd的行數 if [ -z "$n" ] //條件:是否爲空 then echo error exit elif [ $n -gt 20 ] //條件:n是否大於20 then echo OK fi [root@ying01 shell]# sh -x file3.sh ++ wc -l /etc/passwd ++ awk '{print $1}' + n=46 + '[' -z 46 ']' + '[' 46 -gt 20 ']' + echo OK OK
if [ -n "$a" ] 表示當變量a的值不爲空,或者說這個文件內容不爲空
-n 判斷變量的時候,須要用""雙引號引發來,如果文件的時候,則不須要用雙引號引發來
[root@ying01 shell]# if [ -n file3.sh ]; then echo ok; fi ok [root@ying01 shell]# if [ -n "$b" ]; then echo $b; else echo "b is null"; fi b is null
case 變量名 in value1) command ;; value2) command ;; *) commond ;; esac
若是case中的某個value是同樣的,咱們能夠這樣寫:
在case程序中,能夠在條件中使用 |,表示或的意思, 好比 2|3) command ;;
腳本案例:
#!/bin/bash read -p "Please input a number: " n //讓用戶輸入一個數字 if [ -z "$n" ] //判斷用戶有沒有輸入 then echo "Please input a number." exit 1 fi n1=`echo $n|sed 's/[0-9]//g'` //檢查用戶輸入的是否是所有是數字,不是數字就置空 if [ -n "$n1" ] then echo "Please just input a number, without any other words." exit 1 fi if [ $n -lt 60 ] && [ $n -ge 0 ] //通過如上的篩選,咱們來判斷輸入數字屬於哪一個範圍,而且把值交給tag then tag=1 elif [ $n -ge 60 ] && [ $n -lt 80 ] then tag=2 elif [ $n -ge 80 ] && [ $n -lt 90 ] then tag=3 elif [ $n -ge 90 ] && [ $n -le 100 ] then tag=4 else tag=0 //大於100的狀況 fi case $tag in //根據如上獲得的值,進行判斷 1) echo "you didn't pass the exam!" ;; 2) echo "good!" ;; 3) echo "very good!" ;; 4) echo "perfect!!!" ;; *) echo "Pls input a number range 0-100." ;; esac
重複執行一系列命令在 編程中很常見。一般你須要重複一組命令直到達到某個特定條件,好比處理某個目錄下的全部文件、系統上的全部用戶或者是某個文本文件中的全部行。
常見的兩種循環,在腳本中廣泛被用到。
- for循環
- while循環
for循環演示:
累加求和
[root@ying01 shell]# vim sum01.sh #!/bin/bash sum=0 for i in `seq 1 3` do sum=$[ $sum+$i ] echo $i done echo SUM=$sum [root@ying01 shell]# sh -x sum01.sh + sum=0 ++ seq 1 3 + for i in '`seq 1 3`' + sum=1 + echo 1 1 + for i in '`seq 1 3`' + sum=3 + echo 2 2 + for i in '`seq 1 3`' + sum=6 + echo 3 3 + echo SUM=6 SUM=6
遍歷一個目錄的目錄或者文件
[root@ying01 shell]# vim for02.sh #!/bin/bash cd /root/100 //進入到目錄 for a in `ls /root/100` //遍歷此目錄 do [ -d $a ] && ls $a # 判斷是不是目錄,並列出其下文件和子目錄 if [ -d $a ] then echo $a ls $a fi done [root@ying01 shell]# ls /root/100 10 3 [root@ying01 shell]# sh -x for02.sh + cd /root/100 ++ ls /root/100 + for a in '`ls /root/100`' + '[' -d 10 ']' + ls 10 \# 4.txt + '[' -d 10 ']' + echo 10 10 + ls 10 \# 4.txt + for a in '`ls /root/100`' + '[' -d 3 ']' + ls 3 2.txt + '[' -d 3 ']' + echo 3 3 + ls 3 2.txt [root@ying01 shell]# sh for02.sh \# 4.txt 10 \# 4.txt 2.txt 3 2.txt
特殊for循環示例:list循環時,會以空格或回車符做爲分隔符了
語法 while 條件; do … ; done
每隔1分鐘檢查一下系統負載,當系統的負載大於10的時候,發一封郵件(監控腳本) 最小單元是任務計劃 cron
[root@ying01 shell]# vim while01.sh #!/bin/bash while : # 冒號 : 表示死循環的意思,或者1,或者 true都是死循環 do load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1` if [ $load -gt 10 ] then /usr/local/sbin/mail.py txwd188@126.com "load high" "$load" fi sleep 30 #休眠30秒,由於檢查系統負載,不須要一直去檢查,過一會再看 done [root@ying01 shell]# sh -x while01.sh + : ++ w ++ cut -d. -f1 ++ awk -F 'load average: ' '{print $2}' ++ head -1 + load=0 + '[' 0 -gt 10 ']' + sleep 30
代碼名詞釋義
- w :查看系統負載 ;
- uptime 能夠直接顯示 w 系統負載的第一行,就能夠省去 head -1
- head -1 //取第一行
- awk -F 'load average: ' '{print $2}' // 以'load average: '分隔,輸出第二段
- cut -d . -f1 // 以 . 分隔 取第一段
在循環過程過,須要用戶輸入一個數字;輸入的不是數字,是數字,輸入爲空;迴應相應的結果
[root@ying01 shell]# vim while02.sh #!/bin/bash while : do read -p "Please input a number: " n if [ -z "$n" ] then echo "you need input sth." continue #continue 從新回到循環 fi n1=`echo $n|sed 's/[0-9]//g'` if [ -n "$n1" ] then echo "you just only input numbers." continue fi break #break 退出循環 done echo $n [root@ying01 shell]# sh while02.sh Please input a number: k you just only input numbers. Please input a number: ! you just only input numbers. Please input a number: 5 5
break 經常使用於循環語句中,跳出整個循環語句,直接結束全部循環。
[root@ying01 shell]# vim break01.sh #!/bin/bash for i in `seq 1 5` do echo A=$i if [ $i -eq 3 ] #比較數字,用-eq ;如果比較的是字符串,那須要用 == then break fi echo B=$i done echo C=$i [root@ying01 shell]# sh break01.sh A=1 B=1 A=2 B=2 A=3 C=3
忽略continue之下的代碼,直接進行下一次循環
[root@ying01 shell]# vim contiue01.sh #!/bin/bash for i in `seq 1 5` do echo A=$i if [ $i -eq 3 ] then continue fi echo B=$i done echo C=$i [root@ying01 shell]# sh contiue01.sh //注意沒有B=3行 A=1 B=1 A=2 B=2 A=3 A=4 B=4 A=5 B=5 C=5
exit能夠定義退出的數值,能夠用於肯定腳本運行到什麼地方的時候,結束
[root@ying01 shell]# vim exit01.sh #!/bin/bash for i in `seq 1 5` do echo A=$i if [ $i -eq 3 ] then exit fi echo B=$i done echo C=$i [root@ying01 shell]# sh exit01.sh //直接從A=3退出; A=1 B=1 A=2 B=2 A=3