•shell是一種腳本語言 •可使用邏輯判斷、循環等語法 •能夠自定義函數 •shell是系統命令的集合 •shell腳本能夠實現自動化運維,能大大增長咱們的運維效率
shell是什麼
shell是一個命令解釋器,它在操做系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操做系統,並處理各類各樣的操做系統的輸出結果,輸出到屏幕返回給用戶。這種對話方式能夠是交互的方式(從鍵盤輸入命令,能夠當即獲得shell的迴應),或非交互(執行腳本程序)的方式
什麼是shell腳本?
當linux命令或語句不在命令下執行(嚴格說,命令行執行的語句也是shell腳本),而是經過一個程序文件執行時,該程序就被稱爲shell腳本或shell程序,shell程序很相似DOS系統下的批處理程序(擴展名*.bat)。用戶能夠在shell腳本中敲入一系列的命令或命令語句組合。這些命令、變量和流程控制語句等有機的結合起來就造成了一個功能很強大的shell腳本。
shell腳本語言的種類
在UNIX/LINUX中主要有兩大類shell。linux
•Bourne shell包括sh、ksh和bash。 •Bourne shell (sh) •Korn shell (ksh) •Bourne Again shell (bash) •POSIX shll (sh) •C shell包括csh和tcsh。 •C shell (csh) •TEXES/TOPS C shell(tcsh)
shell腳本語言是若類型語言,較爲通用的shell有標準的Bourne shell(sh)和C shell(csh)。其中Bource shell(sh)已經被bash shell取代。
查看系統的shell。shell
[root@localhost ~]# cat /etc/shells /bin/sh /bin/bash #功能更強大 /sbin/nologin /bin/dash /bin/tcsh /bin/csh
•開頭須要加#!/bin/bash,指定是哪一個解釋器
•以#開頭的做爲解釋說明
•腳本的名字以.sh結尾,用於區分這是一個shell腳本
•執行方法有幾種
shell腳本的創建
在linux系統中,shell腳本(bash shll程序)一般是在編輯器(如vi/vim)中編寫,由Unix/Linux命令、bash shell命令、程序結構控制語句和註釋等內容組成
腳本開頭(第一行)
一個規範的shell腳本在腳本第一行會指出由哪一個程序(解釋器)來執行腳本中的內容,這一行內容在linux bash編程中通常爲:
#! /bin/bash
或
#! /bin/sh <==255個字符之內
其中開頭的"#!"字符又稱爲幻數,在執行bash腳本的時候,內核會根據"#!"後的解釋器來肯定該用哪一個程序解釋這個腳本的內容。注意,這一行必須在每一個腳本頂端的第一行,若是不是第一行則爲腳本註釋行
腳本註釋
在shell腳本中,跟在(#)井號後面的內容表示註釋,用來對腳本進行註釋說明,註釋部分不會被當作程序執行,僅僅是給用戶看,系統解釋器是看不到的,更不會執行。註釋可自成一行,也能夠跟在腳本命令後面與命令在同一行
shell腳本的執行
當shell腳本運行時,它會先查找系統環境變量ENV,該變量指定了環境文件(一般是.bashrc、.bash_profile、/etc/bashrc、/etc/profile等),而後從該環境變量文件開始執行腳本,當讀取了ENV的文件後,shell會開始執行shell腳本中的內容。
特殊技巧:設置crond任務時,最好把系統環境變量在定時任務腳本中從新定義,不然,一些系統環境變量將不會被加載
執行說明
第一種方法是當腳本文件自己沒有可執行權限(即文件x位爲-號)時常使用的方法,或者文件開頭沒有指定解釋器。
例如:編程
[root@localhost ~]# cat test.sh echo 'i am shell' [root@localhost ~]# sh test.sh i am shell [root@localhost ~]# bash test.sh i am shell
第二種方法須要先將腳本文件的權限改成可執行(即文件加X位),具體方法:chmod u+x script-name或chmod 755 script-name。而後經過腳本路徑就能夠直接執行腳本。
例如:vim
[root@localhost ~]# ll test.sh -rw-rw-r--. 1 root root 1217 7月 27 13:57 test.sh [root@localhost ~]# ./test.sh #使用第二種方式,"./"在當前目錄下執行test.sh腳本文件,沒法使用tab自動補全 -bash: ./test.sh: Permission denied 給test.sh添加可執行權限。 [root@localhost ~]# chmod u+x test.sh [root@localhost ~]# ./test.sh i am shell
第三种放法一般是使用source或"."點號讀入或加載指定的shell腳本文件(如test.sh),而後,依次執行指定shell腳本文件test.sh中的全部語句
例如:bash
[root@lamp ~]# . test.sh i am shell [root@lamp ~]# source test.sh i am shell
說明:若是但願父shell調用子shell的變量、函數等,用source或"."點號執行腳本less
命令:date
date 能夠用來顯示或設定系統的日期與時間。
命令參數運維
-d<字符串>:顯示字符串所指的日期與時間。字符串先後必須加上雙引號; -s<字符串>:根據字符串來設置日期與時間。字符串先後必須加上雙引號;只有root權限才能設置,其餘只能查看 -u:顯示GMT; --help:在線幫助; --version:顯示版本信息
日期格式字符串列表編輯器
%H 小時(以00-23來表示)。 %I 小時(以01-12來表示)。 %K 小時(以0-23來表示)。 %l 小時(以0-12來表示)。 %M 分鐘(以00-59來表示)。 %P AM或PM。 %r 時間(含時分秒,小時以12小時AM/PM來表示)。 %s 總秒數。起算時間爲1970-01-01 00:00:00 UTC。 %S 秒(以本地的慣用法來表示)。 %T 時間(含時分秒,小時以24小時制來表示)。 %X 時間(以本地的慣用法來表示)。 %Z 市區。 %a 星期的縮寫。 %A 星期的完整名稱。 %b 月份英文名的縮寫。 %B 月份的完整英文名稱。 %c 日期與時間。只輸入date指令也會顯示一樣的結果。 %d 日期(以01-31來表示)。 %D 日期(含年月日)。 %j 該年中的第幾天。 %m 月份(以01-12來表示)。 %U 該年中的週數。 %w 該周的天數,0表明週日,1表明週一,異詞類推。 %x 日期(以本地的慣用法來表示)。 %y 年份(以00-99來表示)。 %Y 年份(以四位數來表示)。 %n 在顯示時,插入新的一行。 %t 在顯示時,插入tab。 MM 月份(必要) DD 日期(必要) hh 小時(必要) mm 分鐘(必要) ss 秒(選擇性)
實例:
•年月日ide
[root@localhost ~]# date +"%Y-%m-%d" 2018-07-29 [root@localhost ~]# date +"%y-%m-%d" 18-07-29
•輸出昨天、前天,明天等的日期:函數
[root@localhost ~]# date -d "+1 day " +"%Y-%m-%d" 2018-07-28 [root@localhost ~]# date -d "+2 day " +"%Y-%m-%d" 2018-07-27 [root@localhost ~]# date -d "-1 day " +"%Y-%m-%d" 2018-07-30
•加減操做:
date -d "+1 day" +%Y%m%d #顯示前一天的日期 date -d "-1 day" +%Y%m%d #顯示後一天的日期 date -d "-1 month" +%Y%m%d #顯示上一月的日期 date -d "+1 month" +%Y%m%d #顯示下一月的日期 date -d "-1 year" +%Y%m%d #顯示前一年的日期 date -d "+1 year" +%Y%m%d #顯示下一年的日期
設定時間:
date -s #設置當前時間,只有root權限才能設置,其餘只能查看 date -s 20120523 #設置成20120523,這樣會把具體時間設置成空00:00:00 date -s 01:01:01 #設置具體時間,不會對日期作更改 date -s "01:01:01 2012-05-23" #這樣能夠設置所有時間 date -s "01:01:01 20120523" #這樣能夠設置所有時間 date -s "2012-05-23 01:01:01" #這樣能夠設置所有時間 date -s "20120523 01:01:01" #這樣能夠設置所有時間
•顯示日曆
[root@localhost ~]# 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
•當腳本中使用某個字符串,屢次頻繁而且字符串長度很長時,就應該使用變量代替
•使用條件語句時,常使用變量 if [ $a -gt 1];then ...;fi
•引用某個命令的結果時,用變量替代 n=wc -l 1.txt
•寫和用戶交互的腳本時,變量也是必不可少的 read -p "lnput a number:" n; echo $n 若是沒有寫這個n, 能夠直接使用$REPLY
•內置變量 $0,$1,$2... $0表示腳本自己,$1 第一個參數,$2第二個... $#: 表示參數個數
•數學運算a=1;b=2;c=$($a+$b)或者$[$a+$b]
Shell腳本中,充滿着各類邏輯判斷,是腳本中必備的
•if邏輯判斷格式
格式1:if 條件 ; then 語句; fi 格式2:if 條件; then 語句; else 語句; fi 格式3:if …; then … ;elif …; then …; else …; fi
•數學邏輯判斷表達式:
-gt (>); 大於 great than -lt(<); 小於 less than -ge(>=); 大於或等於 -le(<=); 小於或等於 -eq(==); 等於 equal -ne(!=) 不等於 not equa - - - - - - - - - - - - - - - - - - - - - - 方括號裏面不能使用數學運算符<,>,=,等,兩邊中間都要有空格 要使用這些符號,只能使用兩個括號(()),不用空格 例如 if [ $a -gt $b ]等同if (($a>$b)) if [ $a -lt 5 ]等同if (($a<5)) if [ $b -eq 10 ]等if (($b==10))
•多個條件組合-a,-o
-a表示而且,所有條件都成立 -o或者或者,知足一個條件成立 [root@localhost ~]# a=5;if [ $a -gt 4 -a $a -lt 6 ];then echo ok;fi ok [root@localhost ~]# a=5;if [ $a -gt 5 -o $a -lt 6 ];then echo ok;fi ok
•可使用 && || 結合多個條件
條件A&&條件B:A而且B 條件A||條件B:A或者B if [ $a -gt 5 ] && [ $a -lt 10 ]; then if [ $b -gt 5 ] || [ $b -lt 3 ]; then
•if邏輯判斷例子
格式1:if 條件 ; then 語句; fi
#!/bin/bash a=5 if [ $a -gt 3 ] then echo "ok" fi
格式2:if 條件; then 語句; else 語句; fi
#!/bin/bash a=5 if [ $a -gt 3 ] then echo "ok" else echo "nook" fi
格式3:if …; then … ;elif …; then …; else …; fi
#!/bin/bash a=5 if [ $a -lt 4 ] then echo "<4" elif [ $a -lt 6 ] #注意elif能夠嵌套屢次的 then echo "<6 && >4" else echo "nook" fi
在shell中一般要和文件或者目錄打交道,那麼對於他們的屬性判斷十分重要
[ -f file ]判斷是不是普通文件,且存在 [ -d file ] 判斷是不是目錄,且存在 [ -e file ] 判斷文件或目錄是否存在 [ -r file ] 判斷文件是否可讀 [ -w file ] 判斷文件是否可寫 [ -x file ] 判斷文件是否可執行
例子:
#!/bin/bash file="/tmp/1.txt" if [ -e $file ] then echo $file exist else touch $file
&& ||特殊用法,省略if
1.txt不存在,&&表示前一條命令執行成功,纔會執行後面的命令 [root@localhost ~]# [ -e 1.txt ]&&touch 1.txt [root@localhost ~]# ll 總用量 4 -rw-------. 1 root root 1418 4月 26 05:41 anaconda-ks.cfg drwxr-xr-x 2 root root 60 6月 18 11:40 src1 1.txt不存在,||表示前一條命令執行不成功,纔會執行後面的命令 [root@localhost ~]# [ -e 1.txt ]||touch 1.txt [root@localhost ~]# ll 總用量 4 -rw-r--r-- 1 root root 0 7月 29 22:13 1.txt -rw-------. 1 root root 1418 4月 26 05:41 anaconda-ks.cfg drwxr-xr-x 2 root root 60 6月 18 11:40 src1
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 「$a」 ] 這個表示當變量a的值爲空時會怎麼樣
#!/bin/bash n='wc -l /tmp/1.txt' if [ $n -lt 100 ] then echo "line num less than 100" fi # 若是/tmp/1.txt文件爲空,或者被刪除的話,腳本就會運行出錯,出現bug 應該加上一個判斷條件 #!/bin/bash n='wc -l /tmp/1.txt' if [ -z "$n" ] # [ -z "$n" ] 等同[ ! -n "$n" ],!表示取反 then echo "error" exit elif [ $n -lt 100 ] then echo "line num less than 100" fi 或者 #!/bin/bash if [ ! -f /tmp/1.txt ] then echo "/tmp/1.txt is not exist" exit fi n='wc -l /tmp/1.txt' if [ $n -lt 100 ] then echo "line num less than 100" fi
if [ -n 「$a」 ] 表示當變量a的值不爲空,也能夠判斷文件,判斷文件時能夠不加雙引號
if [ -n 01.sh ]; then echo "ok"; fi 另外 #!/bin/bash if [ -n "$b" ] then echo $b else echo "b is null" fi
一條命令也能夠做爲判斷條件。判斷user1用戶是否存在
if grep -wq 'user1' /etc/passwd; then echo "user1 is exist"; else useradd user1;fi #grep -w 精準匹配單詞,加-q能夠不顯示過濾信息
case判斷格式
case 變量名 in value1) commond1 ;; value2) commod2 ;; value3) commod3 ;; esac
在case中,能夠在條件中使用「|」,表示或的意思,如:
2|3) commond ;;
例子: 輸入一個同窗的分數,判斷成績是否及格,優秀
[root@localhost sbin]# vim case1.sh #!/bin/bash read -p "Please input a number: " n # read -p 是讀取用戶的輸入數據,定義到變量裏面 if [ -z "$n" ] then echo "error not input" exit 1 #「exit 1」表示非正常運行致使退出程序 #退出以後,echo $?會返回1值,表示程序退出是由於出錯了 fi n1=`echo $n|sed 's/[0-9]//g'` #判斷用戶輸入的字符是否爲純數字 #若是是數字,則將其替換爲空,賦值給$n1 if [ -n "$n1" ] then echo "Please input a number." exit 1 #判斷$n1不爲空時(即$n不是純數字)再次提示用戶輸入數字並退出 fi #若是用戶輸入的是純數字則執行如下命令: if [ $n -lt 60 ] && [ $n -ge 0 ] 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 fi #tag的做用是爲判斷條件設定標籤,方便後面引用 case $tag in 1) echo "不及格" ;; 2) echo "及格" ;; 3) echo "良好" ;; 4) echo "優秀" ;; *) echo "The number range is 0-100." ;; esac
運行結果
[root@localhost shell]# sh case1.sh Please input a number: error not input [root@localhost shell]# sh case1.sh Please input a number: 12a23 Please input a number. [root@localhost shell]# sh case1.sh Please input a number: 45 不及格 [root@localhost shell]# sh case1.sh Please input a number: 65 及格 [root@localhost shell]# sh case1.sh Please input a number: 85 良好 [root@localhost shell]# sh case1.sh Please input a number: 95 優秀 [root@localhost shell]# sh case1.sh Please input a number: 120 The number range is 0-100.
•格式:
for 變量名 in 條件; do ...; done
例子:
•用for循環計算1到100的總和
[root@localhost shell]# cat for.sh #!/bin/bash sum=0 for i in `seq 1 100` do sum=$[$sum+$i] done echo $sum #輸出的結果 [root@localhost shell]# sh for.sh 5050
•文件列表循環
[root@localhost shell]# cat for2.sh #!/bin/bash cd /etc/ for a in `ls /etc/` do if [ -d $a ] then ls -d $a fi done #for循環是以空格、回車符做爲分割符分割。
•語法 while 條件; do ...; done
例子:
用while循環檢測系統1分鐘的負載,若是大於,發郵件通知
#!/bin/bash while : #while 跟冒號表示死循環 do load=`w|head -1 |awk -F 'load average: ' '{print $2}'| cut -d . -f1` if [ $load -gt 10 ] then top|mail -s "load is high:$load" admin@163.com fi sleep 30 done
循環判斷輸入的是否純數字
#!/bin/bash while : do read -p "Please input a number:" n if [ -z "$n" ] then echo "You did not enter the number." continue fi n1=`echo $n|sed 's/[0-9]//g'` if [ ! -z "$n1" ] then echo "You can only enter a pure number." continue fi break done echo $n
break表示跳出循環,斷續執行後面的語句
例子
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then break fi echo $i done echo aaaaaa
運行結果
[root@localhost ~]# sh break.sh 1 1 2 2 3 aaaaaa
能夠看到上例中,只循環到第3次的時候,跳出了循環,直接執行了echo aaaaaa的語句
continue結束本次循環,不執行後面的語句,直到循環結束
[root@localhost etc]# cat continue.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then continue fi echo $i done echo aaaaaa
運行結果
[root@localhost etc]# sh continue.sh 1 1 2 2 3 4 4 5 5 aaaaaa
能夠看到循環到第3次的時候,沒有執行後面的語句,直到循環結束
exit退出腳本
[root@localhost etc]# cat exit.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then exit fi echo $i done echo aaaaaa
運行結果
[root@localhost etc]# sh exit.sh 1 1 2 2 3
能夠看到第三次,直接退出了腳本