shell首先它是一個腳本,並不能做爲正式的編程語言。由於是跑在linux的shell中,因此叫shell腳本。說白了,shell腳本就是一些命令的集合。舉個例子,我想要實現這樣的操做:php
1)進入到/tmp/目錄;linux
2)列出當前目錄中全部的文件名;shell
3)把全部當前的文件拷貝到/root/目錄下;編程
4)刪除當前目錄下的全部文件;vim
簡單的4步在shell窗口中須要你敲4次命令,按4次回車。這樣是否是很麻煩?固然這4步操做很是簡單,若是是更加複雜的命令設置須要幾十次操做呢?那樣的話一次一次敲鍵盤會很麻煩。因此不妨把全部的操做都記錄到一個文檔中,而後去調用文檔中的命令,這樣一步操做就能夠完成。其實這個文檔就是shell腳本,只是這個shell腳本有它特殊的格式。bash
shell腳本能幫助咱們很方便的去管理服務器,由於咱們能夠指定一個任務計劃定時去執行某一個shell腳本實現咱們想要需求。這對於linux系統管理員來講是一件很是值得自豪的事情。服務器
有一個問題須要約定一下,凡是自定義的腳本建議放到/usr/local/sbin/目錄下,這樣作的目的是,一來能夠更好的管理文檔;二來之後接管你的管理員都知道自定義腳本在哪裏,方便維護。編程語言
[root@localhost ~]# vi test.sh
#!/bin/bash
# This is my first shell script. date echo "Hello World!"
shell腳本一般都是以.sh爲後綴名的,這個並非說不帶.sh這個腳本就不能執行,只是你們的一個習慣而已。因此,之後你發現了.sh爲後綴的文件那麼它必定會是一個shell腳本了。test.sh中第一行「#!/bin/bash」它表明的意思是,該文件使用的是bash語法。若是不設置該行,那麼你的shell腳本就不能執行。「#」表示註釋,後面跟一些腳本相關的註釋內容。固然這些註釋並不是必須的,若是你懶得很,能夠省略,可是筆者不建議省略。由於隨着你工做時間的增長,你寫的shell腳本會愈來愈多,若是有一天你回頭查看你寫的某個腳本時,極可能忘記該腳本時用來幹什麼的以及何時寫的。因此寫上註釋是有必要的。函數
[root@localhost ~]# sh test.sh Wed Sep 5 23:33:17 CST 2018 Hello World! [root@localhost ~]#
shell腳本的執行很簡單,直接「sh filename」便可,另外你還能夠這樣執行。調試
[root@localhost ~]# chmod +x test.sh [root@localhost ~]# ./test.sh Wed Sep 5 23:34:55 CST 2018 Hello World! [root@localhost ~]#
默認咱們用vim編輯的文檔是不帶有執行權限的,因此須要加一個執行權限,那樣就能夠直接使用「./filename」執行這個腳本了。另外使用sh命令去執行一個shell腳本的時候是能夠加-x選項來查看這個腳本執行過程的,這樣有利於咱們調試這個腳本哪裏出問題了。
[root@localhost ~]# sh -x test.sh + date Wed Sep 5 23:38:44 CST 2018 + echo 'Hello World!' Hello World! [root@localhost ~]#
該shell腳本中用到了「date」這個命令,它的做用就是來打印當前系統的時間。其實在shell腳本中date使用率很是高。有幾個選項筆者經常在shell腳本中用到:
[root@localhost ~]# date "+%Y %m %d %H:%M:%S" 2018 09 06 00:20:31 [root@localhost ~]#
%Y表示年,%m表示月,%d表示日期,%H表示小時,%M表示分鐘,%S表示秒
[root@localhost ~]# date "+%y %m %d" 18 09 06 [root@localhost ~]#
注意%Y和%y的區別。
[root@localhost ~]# date -d "-1 day" "+%Y %m %d" 2018 09 05 [root@localhost ~]# date -d "+1 day" "+%Y %m %d" 2018 09 07 [root@localhost ~]# date -d "-1 month" "+%Y %m %d" 2018 08 06 [root@localhost ~]# date -d "-1 year" "+%Y %m %d" 2017 09 06 [root@localhost ~]#
-d選項也是常常要用到的,它能夠打印n天前或者n天后的日期,固然也能夠打印n個月/年前或者後的日期。
[root@localhost ~]# vi test2.sh
#!/bin/bash d=`date +%H:%M:%S` echo "the script begin at $d" echo "now we will sleep 2 seconds." sleep 2 d1=`date +%H:%M:%S` echo "the script end at $d1"
在test2.sh中使用到了反引號,你是否還記得它的做用?「d」和「d1」在腳本中做爲變量出現,定義變量的格式爲「變量名=變量值」。當在腳本中引用變量時須要加上「$」符號。下面看看腳本執行的結果吧。
[root@localhost ~]# sh test2.sh the script begin at 00:43:40 now we will sleep 2 seconds. the script end at 00:43:42 [root@localhost ~]#
下面咱們用shell計算兩個數的和。
[root@localhost ~]# vi test3.sh
#!/bin/bash a=1 b=2 sum=$[$a+$b] echo "sum is $sum"
數學計算藥用「[]」括起來而且外面要帶一個「$」。腳本結果爲:
[root@localhost ~]# sh test3.sh sum is 3 [root@localhost ~]#
shell腳本還能夠和用戶交互。
[root@localhost ~]# vi test4.sh
#!/bin/bash echo "Please input a number:" read x echo "Please input another number:" read y sum=$[$x+$y] echo "The sum of two numbers is:$sum"
這就用到了read命令了,它能夠從標準輸入得到變量的值,後跟變量名。「read x」表示x變量的值須要用戶經過鍵盤輸入的到。腳本執行過程以下:
[root@localhost ~]# sh test4.sh Please input a number: 5 Please input another number: 6 The sum of two numbers is:11 [root@localhost ~]#
咱們不妨加上-x選項再來看一下這個執行過程:
[root@localhost ~]# sh -x test4.sh + echo 'Please input a number:' Please input a number: + read x 3 + echo 'Please input another number:' Please input another number: + read y 4 + sum=7 + echo 'The sum of two numbers is:7' The sum of two numbers is:7 [root@localhost ~]#
在test4.sh中還有更加簡潔的方式。
[root@localhost ~]# vi test5.sh
#!/bin/bash read -p "Please input a number: " x read -p "Please input another number: " y sum=$[$x+$y] echo "The sum of two numbers is:$sum"
read -p選項相似echo的做用。執行以下:
[root@localhost ~]# sh test5.sh Please input a number: 3 Please input another number: 5 The sum of two numbers is:8 [root@localhost ~]#
你有沒有用過這樣的命令「/etc/init.d/iptables restart」前面的/etc/init.d/iptables文件其實就是一個shell腳本,爲何後面能夠跟一個「restart」?這裏就涉及到了shell腳本的預設變量。實際上,shell腳本在執行的時候後邊能夠跟變量的,並且還能夠跟多個。
[root@localhost ~]# vi test6.sh
#!/bin/bash sum=$[$1+$2] echo $sum
執行過程以下:
[root@localhost ~]# sh test6.sh 5 8 13 [root@localhost ~]#
在腳本中,你會不會奇怪,哪裏來的$1和$2,這其實就是shell腳本的預設變量,其中$1的值就是在執行的時候輸入的5,而$2的值就是執行的時候輸入的8,固然一個shell腳本的預設變量是沒有限制的,這回你明白了吧。另外還有一個$0,不過他表明的是腳本自己的名字。不妨把腳本修改一下。
[root@localhost ~]# vi test6.sh
#!/bin/bash echo "$0 $1 $2"
執行結果想必你也猜到了吧。
[root@localhost ~]# sh test6.sh 5 8 test6.sh 5 8 [root@localhost ~]#
若是你學過C語言或者其餘語言,相信你不會對if陌生,在shell腳本中咱們一樣可使用if邏輯判斷。在shell中if判斷的基本語法爲:
1)不帶else
if 判斷語句; then
command
fi
[root@localhost ~]# vi if1.sh
#!/bin/bash read -p "Please input your score: " a if((a<60));then echo "you didn't pass the exam." fi
在if1.sh中出現呢了((a<60))這樣的形式,這是shell腳本中特有的格式,用一個小括號或者不用都會報錯,請記住這個格式,便可。執行結果爲:
[root@localhost ~]# sh if1.sh Please input your score: 36 you didn't pass the exam. [root@localhost ~]#
2)帶有else
if 判斷語句;then
command
else
command
fi
[root@localhost ~]# vi if2.sh
#!/bin/bash read -p "Please input your score: " a if((a<60));then echo "you didn't pass the exam." else echo "Good! you passed the exam." fi
執行結果爲:
[root@localhost ~]# sh if2.sh Please input your score: 98 Good! you passed the exam. [root@localhost ~]#
3)帶有elif
if 判斷語句;then
command
elif 判斷語句;then
command
else
command
fi
[root@localhost ~]# vi if3.sh
#!/bin/bash read -p "Please input your score: " a if((a<60));then echo "you didn't pass the exam." elif ((a>60)) && ((a<85));then echo "Good! you passed the exam." else echo "Very good! your score is very high!" fi
這裏的&&表示「而且」的意思,當前你也可使用||表示「或者」,執行結果:
[root@localhost ~]# sh if3.sh Please input your score: 98 Very good! your score is very high! [root@localhost ~]# sh if3.sh Please input your score: 50 you didn't pass the exam. [root@localhost ~]# sh if3.sh Please input your score: 75 Good! you passed the exam. [root@localhost ~]#
以上只是簡單的介紹了if語句的結構。在判斷數字大小除了可使用「(())」的形式外,還可使用「[]」。可是就不能使用>,<,=這樣的符號了,要使用-lt(小於)、-gt(大於)、-ge(大於等於)、-le(小於等於)、-eq(等於)、-ne(不等於)。
[root@localhost ~]# a=10;if [ $a -lt 5 ];then echo ok;fi [root@localhost ~]# a=10;if [ $a -gt 5 ];then echo ok;fi ok [root@localhost ~]# a=10;if [ $a -ge 5 ];then echo ok;fi ok [root@localhost ~]# a=10;if [ $a -le 5 ];then echo ok;fi [root@localhost ~]# a=10;if [ $a -eq 5 ];then echo ok;fi [root@localhost ~]# a=10;if [ $a -ne 5 ];then echo ok;fi ok [root@localhost ~]#
再看看if使用&&和||的狀況。
[root@localhost ~]# a=10;if [ $a -lt 1 ] || [ $a -gt 10 ];then echo ok;fi [root@localhost ~]# a=8;if [ $a -gt 1 ] && [ $a -lt 10 ];then echo ok;fi ok [root@localhost ~]#
shell腳本中if還常常判斷文檔屬性,好比判斷是普通文件仍是目錄,判斷文件是否有讀寫執行權限,經常使用的也就幾個選項:
-e:判斷文件或目錄是否存在;
-d:判斷是否是目錄,並是否存在;
-f:判斷是不是普通文件,並存在;
-r:判斷文檔是否有可讀權限;
-w:判斷文檔是否有可寫權限;
-x:判斷是否可執行;
使用if判斷時,具體格式爲:if [-e filename];then
[root@localhost ~]# if [ -d /home ];then echo ok;fi ok [root@localhost ~]# if [ -f /home ];then echo ok;fi [root@localhost ~]# if [ -f test.txt ];then echo ok;fi ok [root@localhost ~]# if [ -e test.txt ];then echo ok;fi ok [root@localhost ~]# if [ -e test1.txt ];then echo ok;fi [root@localhost ~]# if [ -r test.txt ];then echo ok;fi ok [root@localhost ~]# if [ -w test.txt ];then echo ok;fi ok [root@localhost ~]# if [ -x test.txt ];then echo ok;fi [root@localhost ~]#
在shell腳本中,除了用if來判斷邏輯外,還有一種經常使用的方式,那就是case了。具體格式爲:
case 變量 in
value1)
command
;;
vaule2)
command
;;
value3)
command
;;
*)
command
;;
esac
上面的結構中,不限制value的個數,*則表明除了上面的value外的其餘值。下面筆者寫了一個判斷輸入值時奇數或者偶數的腳本。
[root@localhost ~]# vi case.sh
#!/bin/bash read -p "Please input a number: " n a=$[$n%2] case $a in 1) echo "The number is odd" ;; 0) echo "The number is even" ;; esac
執行結果是:
[root@localhost ~]# sh case.sh Please input a number: 3 The number is odd [root@localhost ~]# sh case.sh Please input a number: 8 The number is even [root@localhost ~]#
shell腳本中也算是一門簡易的編程語言了,固然循環是不能缺乏的。經常使用到的循環有for循環和while循環。
[root@localhost ~]# vi for.sh
#!/bin/bash for i in `seq 1 5`;do echo $i done
腳本中的seq 1 5表示從1到5的一個序列。你能夠直接運行這個命令試一下。腳本執行結果爲:
[root@localhost ~]# sh for.sh 1 2 3 4 5 [root@localhost ~]#
經過這個腳本就能夠看到for循環的基本結構:
for 變量名 in 循環條件;do
command
done
[root@localhost ~]# for i in 1 2 3 4 5;do echo $i;done 1 2 3 4 5 [root@localhost ~]#
循環的條件那一部分也能夠寫成這樣的形式,中間用空格隔開便可。
[root@localhost ~]# for i in `ls`;do echo $i;done 1.txt anaconda-ks.cfg break2.sh break.sh case1.sh case2.sh case.sh code continue2.sh continue.sh for1.sh for2.sh for3.sh for.sh function1.sh function2.sh if1.sh if2.sh if3.sh myfile test1.sh test2.sh test3.sh test4.sh test5.sh test6.sh test.sh test.txt until.sh users wc while2.sh while.sh [root@localhost ~]#
再來看一下這個while循環,基本格式是:
while 條件;do
command
done
[root@localhost ~]# vi while.sh
#!/bin/bash a=10 while [ $a -ge 1 ];do echo "$a" a=$[$a-1] done
腳本執行結果爲:
[root@localhost ~]# sh while.sh 10 9 8 7 6 5 4 3 2 1 [root@localhost ~]#
若是你學過開發,確定知道函數的做用。若是你是剛剛接觸到這個概念的話,也沒有關係,其實很好理解的。函數就是把一段帶啊整理到一個小單元中,並給這個小單元起一個名字,當用到這段代碼時直接調用這個小單元的名字便可。有時候腳本中的某段代碼老是重複使用,若是寫成函數,每次用到時直接用函數名代替便可,這樣就節省了時間還節省了空間。
[root@localhost ~]# vi fun.sh
#!/bin/bash function sum(){ sum=$[$1+$2] echo $sum } sum $1 $2
fun.sh中的sum()爲自定義的函數,在shell腳本中要用這樣的格式去定義函數。
function 函數名(){
command
}
上個腳本的執行結果爲:
[root@localhost ~]# sh fun.sh 5 8 13 [root@localhost ~]#
在shell腳本中,函數必定要在最前面,不能出如今中間或者最後,由於函數是要被調用的,若是還沒出現就被調用,確定是會出錯的。
一、編寫shell腳本,計算1-100的和;
#!/bin/bash sum=0 for i in `seq 1 100`;do sum=$[$sum+$i] done echo $sum
二、編寫shell腳本,要求輸入一下數字,而後計算出從1到這個數字的和。要求,若是輸入的數字小於1,則從新輸入,知道輸入正確的數字爲止;
#!/bin/bash while :;do read -p "Input a number: " a sum=0 if ((a>1));then while [ $a -ge 1 ];do sum=$[$sum+$a] a=$[$a-1] done echo $sum break else continue fi done
#!/bin/bash n=0 while [ $n -lt 1 ];do read -p "Please input a number, it must greater than 1: " n done sum=0 for i in `seq 1 $n`;do sum=$[$sum+$i] done echo $sum
三、編寫shell腳本,把/root/目錄下的全部目錄(只須要一級)拷貝到/tmp/目錄下;
#!/bin/bash dir="/root/" for f in `ls $dir`;do tmp_dir=${dir}${f} if [ -d $tmp_dir ];then cp -r $tmp_dir /tmp/ fi done
四、編寫shell腳本,批量創建用戶user_00,user_01,...,user_100而且全部用戶屬於users組;
#!/bin/bash group=users egrep "^$group" /etc/group >& /dev/null if [ $? -ne 0 ];then groupadd $group fi for i in `seq 0 100`;do if [ $i -lt 10 ];then user="user_0${i}" else user="user_${i}" fi egrep "^$user" /etc/passwd >& /dev/null if [ $? -ne 0 ];then useradd -g $group $user fi done
五、編寫shell腳本,截取文件test.log中的包含關鍵詞‘abc’的行中第一列(假設分隔符爲「:」),而後把截取的數字排序(假設第一列爲數字),而後打印出重複次數超過10次的列;
六、編寫shell腳本,判斷輸入的IP是否正確(IP的規則是:n1.n2.n3.n4,其中1<n1<255,0<n2<255,0<n3<255,0<n4<255)。