您好,登錄后才能下訂單哦!
Shell腳本語言是實現Linux/UNIX系統管理及自動化運維所必備的重要工具,Linux/UNIX系統的底層及基礎應用軟件的核心大部分涉及Shell腳本的內容。每一個合格的Linux系統管理員或運維工程師,都需要熟練的編寫Shell腳本語言,并能夠閱讀系統及各類軟件附帶的Shell腳本內容。只有這樣才能提升運維人員的工作效率,適應日益復雜的工作環境,減少不必要的重復工作,從而為個人的職場發展奠定較好的基礎
能夠熟練使用vim編輯器,熟悉SSH終端
有一定的Linux命令基礎,至少需要掌握80個以上Linux常用命令,并能夠熟練使用它
要熟練掌握Linux正則表達式及三劍客命令(grep,sed,awk)
學好Shel編程的核心:多練-->多思考-->再練-->再思考,堅持如此循環即可!
新手大忌:不可拿來主義,可以模仿,但是要自己嚼爛了吃下去,否則會鬧肚子
格言:你覺得會了并不一定會了,你認為對的并不一定對的
大家要勤動手,自行完成學習筆記和代碼的書寫。通過每一個小目標培養自己的興趣以及成就感
Shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話
把用戶的輸入解釋給操作系統,并處理各種各樣的操作系統的輸出結果,輸出屏幕返回給用戶
這種對話方式可以是:
1)交互的方式:從鍵盤輸入命令,通過/bin/bash的解釋器,可以立即得到shell的回應
2)非交互的方式:腳本
下圖×××部分就是命令解釋器shell
Shell的英文意思是貝殼的意思,命令解釋器Shell像一個貝殼一樣包住系統核心
Shell執行命令分為兩種方式:
內置命令:
如講過的cd,pwd,exit和echo等命令
當用戶登錄系統后,shell以及內置命令就被系統載入內存,并且一直運行
一般命令:如ls,磁盤上的程序文件-->調入-->執行命令
當linux命令或語句不在命令行下執行(嚴格說,命令行也是shell)
而是通過一個程序文件執行時,該程序就被稱為Shell腳本或Shell程序
用戶可以在Shell腳本中敲入一系列的命令及語句組合;這些命令變量和流程控制語句等有機的結合起來就形成一個功能強大的Shell腳本
首先先帶領大家寫一個清空/var/log/messages日志的腳本
我們需要先想明白幾個問題:
1)日志文件在哪?
/var/log/messages
2)用什么命令可以清空文件?
> 重定向
3)寫一個簡單的shell腳本
#! /bin/bash
cd /var/log/
>messages
4)怎樣執行腳本?# sh /server/scripts/log.sh
有沒有考慮到:
有沒有腳本放在統一的目錄
/server/scripts目錄下
權限:用哪個用戶執行文件
需要對用戶做判斷
清空錯文件怎么辦,該如何辦?
錯誤提示:有沒有成功知不知道?
腳本的通用性
小結:
Shell就是命令解釋器。==>翻譯官
Shell腳本==>命令放在腳本里
推薦使用vim編輯器編輯腳本,可以事先做個別名
# echo "alias vi=vim">>/etc/profile # source /etc/profile
規范的Shell腳本第一行會指出由哪個程序(解釋器)來執行腳本中的內容
在linux bash編程中一般為:
#!/bin/bash或#!/bin/sh
其中開頭的“#!”又稱為幻數,在執行Shell腳本的時候
內核會根據“#!”后的解釋器來確定哪個程序解釋腳本中的內容
注意:這一行必須在每個腳本頂端的第一行,如果不是第一行則為腳本注釋行
# ll /bin/shlrwxrwxrwx. 1 root root 4 Dec 23 20:25 /bin/sh -> bash # sh是bash的軟鏈接,推薦標準寫法#!/bin/bash
可以看一下系統自帶的腳本的寫法
head -1 /etc/init.d/*
在Shell腳本中,跟在#后面的內容表示注釋。注釋部分不會被執行,僅給人看
注釋可以自成一行,也可以跟在命令后面,與命令同行。要養成寫注釋的習慣,方便自己與他人
最好不用中文注釋,因為在不同字符集的系統會出現亂碼
1)bash scripts-name或sh script-name(推薦使用)
這種方法是當腳本本身沒有可執行權限時常使用的方法
2)path /script-name 或./scripts-name(全路徑或當前路徑執行腳本)
這種方法首先需要給腳本文件可執行權限
3)source scripts-name或. scripts-name #注意“.”點號,且點號后有空格
source 或.在執行這個腳本的同時,可以將腳本中的函數和變量加載到當前shell
1)開頭指定腳本解釋器
2)開頭加版本版權等信息,可配置~/.vimrc文件自動添加
3)腳本不要用中文注釋,盡量用英文注釋
4)腳本以.sh為擴展名
5)放在統一的目錄
6)代碼書寫優秀習慣
a,成對的內容一次性寫出來,防止遺漏,如[],'',""等
b,[]兩端要有空格,先輸入[]退格,輸入2個空格,再退格寫
c,流程控制語句一次書寫完,再添加內容
if 條件 then 內容 fi
d,通過縮進讓代碼易讀
e,腳本中的引號都是英文狀態下的引號,其他字符也是英文狀態
好的習慣可以讓我們避免很多不必要的麻煩,提高工作效率
變量就是用一個固定的字符串(也可能是字符數字等的組合),替代更多更復雜的內容
這個內容里可能還會包含變量和路徑,字符串等其他內容。變量的定義是存在內存中
x=1 y=2
變量分為兩類:
1)環境變量(也可稱為全局變量)
可以在創建他們的Shell及派生出來的子shell中使用
環境變量又可以分為自定義環境變量和bash內置的環境變量
2)局部變量(普通變量):
只能在創建他們的shell函數或shell腳本中使用,還記得前面的$user?我們創建的一般都是普通變量
環境變量用于定義Shell的運行環境,保證Shell命令的正確執行,Shell通過環境變量來確定登錄用戶名,命令路徑,終端類型,登錄目錄等,所有的環境變量都是全局變量,可用于所有子進程中
包括編輯器,shell腳本和各類應用。但crond計劃任務除外,還需要重新定義環境變量
環境變量可以在命令行中設置,但用戶退出時這些變量值也會丟失,因此最好在用戶家目錄下的
.bash_profile文件中或全局配置/etc/bashrc,/etc/profile文件或者/etc/profile.d/目錄中定義
將環境變量放入profile文件中,每次用戶登錄時這些變量值都將被初始化
通常,所有環境變量均為大寫。環境變量應用于用戶進程前,都應該用export命令導出
例如:export chensiqi=1
有一些環境變量,如HOME,PATH,SHELL,UID,USER等,在用戶登錄前就已被/bin/login
程序設置好了。通常環境變量定義并保存在用戶家目錄下的.bash_profile或/etc/profile文件中
定義局部變量
局部變量在用戶當前的shell生存期的腳本中使用。例如,局部變量test取值為test18
這個值只在用戶當前shell生存期中有意義。如果在shell中啟動另一個進程或退出,局部變量test值將無效
普通字符串變量定義
變量名=value 變量名=‘value’ 變量名=“value”
shell中變量名及變量內容的要求
一般是字母,數字,下劃線組成,且以字母開頭
變量的內容,可以使用單引號或雙引號印起來,或不加引號
雖然變量可以以下劃線開頭,但類似這種變量都是比較特殊的,都是系統自己用的。我們盡量少用
小結:
1)CMD=ls
的ls兩側的符號是鍵盤tab鍵上面的,不是單引號
2)在變量名前加$,可以取得此變量的值,使用echo或printf命令可以顯示變量的值
$A和$(A)寫法不同,效果一樣,推薦后面的寫法
3)${WEEK}DAY若變量和其他字符組成新的變量就必須給變量加上大括號{}.
4)養成將所有字符串變量用雙引號括起來使用的習慣,減少編程遇到的怪異錯誤。“$A”和“${A}”
變量名只能由字母,數字,下劃線組成,且以字母開頭
規范的變量名寫法定義:見名知意
a,testAge=1 <==每個單詞首字母大寫
b,test_age=1 <==每個單詞之間用“-”
c,testAgeSex=1 <==駝峰語法:首個單詞字母小寫,其余單詞首字母大寫
=號的知識,a=1中的等號是賦值的意思,比較是不是相等為“==”
打印變量,變量名前接$符號,變量名后接字符的時候,要用大括號括起來
注意:
變量內容引用方法,一般為雙引號,簡單連續字符可以不加引號,希望原樣輸出,使用單引號
變量內容是命令,要用反引號``或者$()把變量括起來使用
$0 獲取當前執行的shell腳本的文件名,如果執行腳本帶路徑那么就包括腳本路徑 $n 獲取當前執行的shell腳本的第n個參數值,n=1..9,當n為0時 表示腳本的文件名,如果n大于9用大括號括起來{10},參數以空格隔開 $# 獲取當前執行的shell腳本后面接的參數的總個數
$0 獲取當前執行的shell腳本的文件名,包括路徑
$? 獲取執行上一個指令的返回值(0為成功,非零為失敗)
# echo $? 0 # cd /rrr -bash: cd: /rrr: No such file or directory # echo $? 1 $? 返回值參考 0 表示運行成功 2 權限拒絕 1~125 表示運行失敗,腳本命令,系統命令錯誤或參數傳遞錯誤 126 找到該命令,但無法執行 127 未找到要運行的命令 128 命令被系統強制結束
生產環境:
1)用于判斷命令,腳本或函數等程序是否執行成功
2)若在腳本中調用執行“exit數字”,則會返回這個數字給“$?”變量
3)如果在函數中使用“return 數字”,則會以函數返回值的形式傳給“$?”
算數運算符號
# ((a=1+2**3-4%3))使用方法:
# echo $a 8 # b=$((1+2**3-4%3)) # echo $b 8 # echo $((1+2**3-4%3)) 8 小結: 1)“(())”在命令行執行時不需要$符號,但是輸出需要$符號 2)“(())”里所有字符之間有無或多個空格沒有任何影響
# echo $[2+3] 5 # echo $[2*3] 6
# cat test.sh #!/bin/env bash a=6 b=2 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))"
# cat test.sh #!/bin/env bash a=$1 #不需要把后面的$a,$b都改 b=$2 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))"
什么是條件測試呢?
簡單理解,判斷某些條件是否成立,成立執行一種命令,不成立執行另外一種命令
格式:[ <測試表達式> ] 大家要掌握著一種,注意測試表達式兩邊要留空格
好習慣:先敲一對[],然后退格輸入2個空格[],最后再回退一個空格開始輸入[ -f file ]
# [ -f /etc/hosts ] && echo 1 || echo 1 # [ -f /etc/hosts1 ] && echo 1 || echo 0 0 # [ ! -f /etc/hosts1 ] && echo 1 || echo 0 1 # 在做測試判斷時,不一定用上面的方法,用下面的寫一半方法更簡潔 # [ -f /etc/hosts ] && echo 1 1 # [ -f /etc/hosts1 ] || echo 0 0 # 系統腳本 # vi /etc/init.d/nfs .... [ -x /usr/sbin/rpc.nfsd ] || exit 5 [ -x /usr/sbin/rpc.mountd ] || exit 5 [ -x /usr/sbin/exportfs ] || exit 5
比較兩個字符串是否相同,字符串長度是否為零,字符串是否為NULL。Bash區分零長度字符串和空字符串
|常用字符串測試操作符|說明|
|--|--|
|-z "字符串"|若串長度為0則真,-z理解為zero|
|-n “字符串”|若串長度不為0則真,-n理解為no zero|
|“串1”=“串2”|若串1等于串2則真,可以使用“==”代替“=”|
|“串1”!="串2"|若串1不等于串2則真,但不能使用“!==”代替“!=”|
特別注意,以上表格中的字符串測試操作符號務必要用“”引起來
[ -z "$string"]字符串比較,比較符號兩端最好有空格,參考系統腳本
[ "$password" = "john" ] 提示: [,"password",=,"join",]之間必須存在空格
8.6 邏輯操作符在[]中可以用>和<,但需要用\轉義,雖然不報錯,但結果不對。但還是不要混用!
小結:
1)多個[]之間的邏輯操作符是&&或||
2)&&前面成功執行后面
3)||前面不成功執行后面
if [ 條件 ] then 指令 fi 或 if [ 條件 ];then 指令 fi 提示:分號相當于命令換行,上面兩種語法等同
if [ 條件 ] then 指令 else 指令 fi
if [ 條件1 ];then
指令1
elif [ 條件2 ];then
指令2
elif [ 條件3 ];then
指令3
elif [ 條件4 ];then
指令4
else
指令n
fi
case "字符串變量" in 值1) 指令1 ;; 值2) 指令2 ;; *) 指令 esac 注意:case語句相當于一個if的多分支結構語句 case 語句小結: 1)case語句就相當于多分支的if語句。case語句的優勢是更規范,易讀 2)case語句適合變量的值少,且為固定的數字或字符串集合 3)系統服務啟動腳本傳參的判斷多用case語句
while 條件 do 指令 done
for 變量名 in 變量取值列表 do 指令... done
休息命令:sleep 1 休息一秒,usleep 1000000休息1秒單位微妙
# cat test.sh #!/bin/bash while true do uptime >> /var/log/uptime.log sleep 2 done # while true 表示條件永遠為真,因此會一直運行,像死循環一樣 # cat /var/log/uptime.log 23:01:57 up 8:33, 2 users, load average: 0.04, 0.03, 0.05 23:01:59 up 8:33, 2 users, load average: 0.04, 0.03, 0.05 23:02:01 up 8:33, 2 users, load average: 0.04, 0.03, 0.05
# cat test.sh #!/bin/bash i=1 sum=0 while [ $i -lt 100 ] do ((sum=sum+i)) ((i++)) done echo $sum
# cat test.sh #!/bin/bash i=10 while [ $i -gt 0 ] do echo $i sleep 1 ((i--)) done
1)sh while01.sh & #放在后臺執行
2)screen 分離 ctrl+a+d 查看screen -ls進入screen -r num
3)nohup while01.sh &
# cat test.sh #!/bin/bash for i in 5 4 3 2 1 #用空格隔開 do echo $i done # sh test.sh 5 4 3 2 1 # for i in {5..1};do echo $i;done 5 4 3 2 1 # echo 10.1.1.{1..10} 10.1.1.1 10.1.1.2 10.1.1.3 10.1.1.4 10.1.1.5 10.1.1.6 10.1.1.7 10.1.1.8 10.1.1.9 10.1.1.10 # for i in `seq 5 -1 1`;do echo $i;done 5 4 3 2 1 #循環執行命令n次 # for i in `seq 100`;do curl -I baidu.com;done
# cat test.sh #!/bin/bash LANG=en for i in `chkconfig --list|grep "3:on"|awk '{print $1}'` do chkconfig $i off done for name in sshd rsyslog crond network sysstat do chkconfig $name on done
#!/bin/bash Path=/test [ -d "$Path" ] || mkdir -p $Path for i in `seq 10` do touch $Path/test_$i.html done
# cat test.sh #!/bin/bash $Path=/test [ -d "$Path" ] || mkdir -p $Path for file in `ls $Path` do mv $file `echo $file|sed -r 's#test(.*).html#linux\1.HTML#g'` done
# cat test.sh
#!/bin/bash
User=test
Path=/tmp
for user in ${User}{01..10}
do
useradd $user >/dev/null 2>&1
if [ ! $? -eq 0 ];then
echo "$user created faile!"
echo "scripts begin to rollback!"
for i in ${User}{01..10}
do
userdel -r $i >/dev/null 2>&1
[ $? -eq 0 ] || exit 1
done
echo >$Path/user_passwd
exit 1
else
passWD=`echo $RANDOM|md5sum|cut -c1-8`
[ -d $Path ] || mkdir $Path
echo $passWD | passwd --stdin $user
echo "$user:$passWD">>$Path/user_passwd
fi
done
# cat /server/scripts/test.sh #!/bin/bash Path=`pwd` echo $Path for filename in `ls` do [ -d ${Path}/${filename} ] && echo $filename done
# cat /server/scripts/test.sh #!/bin/bash for ((i=1;i<10;i++)) do for ((j=1;j<=i;j++)) do echo -n "$i * $j = $((i*j))" echo -n " " done echo " " done # sh /server/scripts/test.sh
break continue exit用于循環結構中控制虛幻(for,while,if)的走向
#!/bin/bash for ((i=0;i<=5;i++)) do [ $i -eq 3 ] && break &n
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。