shell腳本
確切一點說,Shell就是一個命令行解釋器,它的做用就是遵循必定的語法將輸入的命令加以解釋並傳給系統。它爲用戶提供了一個向Linux發送請求以便運行程序的接口系統級程序,用戶能夠用Shell來啓動、掛起、中止甚至是編寫一些程序。 Shell自己是一個用C語言編寫的程序,它是用戶使用Linux的橋樑。Shell既是一種命令語言,又是一種程序設計語言,做爲命令語言,它互動式地解釋和執行用戶輸入的命令;做爲程序設計語言,它定義了各類變量和參數,並提供了許多在高階語言中才具備的控制結構,包括循環和分支。它雖然不是 Linux系統內核的一部分,但它調用了系統內核的大部分功能來執行程序、建立文檔並以並行的方式協調各個程序的運行。html
shell腳本的優點在於處理操做系統底層的業務 (linux系統內部的應用都是shell腳本完成)由於有大量的linux系統命令爲它作支撐。2000多個命令都是shell腳本編程的有力支撐,特別是grep、awk、sed等。例如:一鍵軟件安裝、優化、監控報警腳本,常規的業務應用,shell開發更簡單快速,符合運維的簡單、易用、高效原則。java
shell腳本
打開文本編輯器(可使用vi/vim命令來建立文件),新建一個文件test.sh,擴展名爲shlinux
輸入一些代碼,第一行通常是這樣:redis
[root@zhaocheng ~]# cat test.sh #!/bin/bash echo "Hello World" [root@zhaocheng ~]# bash test.sh Hello World
"#!" 是一個約定的標記,它告訴系統這個腳本須要什麼解釋器來執行,即便用哪種Shell。
echo命令用於向窗口輸出文本shell
查看系統中的解釋器編程
[root@localhost ~]# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/tcsh /bin/csh
輸入echo $SHELL默認系統顯示/bin/bashbootstrap
[root@localhost ~]# echo $SHELL /bin/bash
輸入bash -version顯示shell版本vim
[root@localhost ~]# bash -version GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
腳本書寫規範
建議統一存放目錄,方便運維的管理查找去執行[root@localhost ~]# mkdir /shell/scripts -pv
腳本以.sh爲擴展名
開頭指定腳本解釋器。
開頭加版本版權等信息,可配置~/.vimrc文件自動添加。
腳本不要用中文註釋,儘可能用英文註釋。api
代碼書寫優秀習慣
成對的內容一次性寫出來,防止遺漏,如[ ]、' '、" "等
[ ]兩端要有空格,先輸入[ ],退格,輸入2個空格,再退格寫。
流程控制語句一次書寫完,再添加內容。(if 條件 ; then 內容;fi)ddd
經過縮進讓代碼易讀。
腳本中的引號都是英文狀態下的引號,其餘字符也是英文狀態。數組
shell腳本的執行
[root@localhost scripts]# chmod +x test.sh [root@localhost scripts]# ls test.sh [root@localhost scripts]# ./test.sh Hello World [root@localhost scripts]# source test.sh Hello World [root@localhost scripts]# bash test.sh Hello World [root@localhost scripts]# sh test.sh Hello World
**shell的變量
變量能夠分爲兩類:環境變量(全局變量)和普通變量(局部變量)
環境變量也可稱爲全局變量,能夠在建立他們的Shell及其派生出來的任意子進程shell中使用,環境變量又可分爲自定義環境變量和Bash內置的環境變量
普通變量也可稱爲局部變量,只能在建立他們的Shell函數或Shell腳本中使用。普通變量通常是由開發者用戶開發腳本程序時建立的。
環境變量
能夠經過env,或者export獲取到系統中的環境變量**
[root@localhost scripts]# env XDG_SESSION_ID=141785 HOSTNAME=zhaocheng SHELL=/bin/bash TERM=xterm HISTSIZE=3000
輸出系統中的變量
[root@localhost scripts]# echo $HOME /root [root@localhost scripts]# echo $USER root [root@localhost scripts]# echo $HISTSIZE 3000 [root@localhost scripts]# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/date/soft/logstash-7.5.0/bin:/root/bin
普通變量
通常在本地設置並執行的,可是在一個腳本中去執行就是無效的
[root@localhost scripts]# xiaoming=26 [root@localhost scripts]# echo $xiaoming 26 [root@localhost scripts]# cat test.sh #!/bin/bash echo $xiaoming [root@localhost scripts]# bash test.sh
這樣去執行是沒法獲取到普通的變量的,由於這是本地的變量值,若是將它加入到系統變量中固然這就獲取到了
而剛纔經過export命令查看到$PATH就是系統變量的,固然這樣的,咱們執行就能在咱們腳本中直接去調用這個變量
[root@localhost scripts]# cat test.sh #!/bin/bash echo $PATH [root@localhost scripts]# bash test.sh /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/date/soft/logstash-7.5.0/bin:/root/bin
如今咱們將咱們平時定義的變量加入到shell中,通常開發一些腳本的時候方便管理也都會直接將變量在咱們全局變量中去調用,提高腳本效率與清晰,變量爲大寫,這種也是不建議去使用的,退出時,變量就失效,建議寫到腳本中
查看咱們的系統加入的變量可使用export去查看
[root@localhost scripts]# export XIAOMING=26 [root@localhost scripts]# cat test.sh #!/bin/bash echo $XIAOMING [root@localhost scripts]# bash test.sh 26
簡單示例
定義變量將變量導入到系統變量中
[root@localhost scripts]# export TENGXUN=mahuateng [root@localhost scripts]# export ALI=mayun [root@localhost scripts]# export BAIDU=liyanhong [root@localhost scripts]# cat test.sh #!/bin/bash echo $TENGXUN echo $BAIDU echo $ALI
執行效果是直接調用咱們的系統變量,而不須要腳本中再去寫上面的語法,不過均可以使用,根據本身的習慣
[root@localhost scripts]# bash test.sh mahuateng liyanhong mayun
另外就是這裏若是沒有寫進系統變量也能去調用到,可使用source,這樣也能獲取到
[root@localhost scripts]# LIHONGLEI=lei [root@localhost scripts]# cat test.sh #!/bin/bash echo $LIHONGLEI [root@localhost scripts]# source test.sh lei
也能夠將這個加入到/etc/profile中也能夠執行
[root@localhost scripts]# cat test.sh #!/bin/bash echo $PING [root@localhost scripts]# tail -1 /etc/profile PING=guo
這個須要source /etc/profile一下才能獲取到
[root@localhost scripts]# source /etc/profile [root@localhost scripts]# source test.sh guo
通常當linux系統啓動的時候,系統將啓動一個用戶shell,這個shell直接就可使用shell命令或者聲明變量,好比,定義聲明變量,但這個在腳本中輸出爲空,在局部變量須要添加$才能引用
[root@localhost scripts]# name=lili [root@localhost scripts]# echo name name [root@localhost scripts]# echo $name lili
**爲何要用export命令?
其實主要是咱們定義一個變量時能夠在子shell中被調用,而不須要重複去定義,可是當shell執行結束就會自動退出,該環境變量沒法繼續使用
變量在引號的使用
通常是特殊字符的時候須要使用'',若是是引用系統變量的話,必須使用""**
[root@tengxunyun ~]# name1=pingguo [root@tengxunyun ~]# name2='li' [root@tengxunyun ~]# name3="juzi" [root@tengxunyun ~]# name4='^^^^' [root@tengxunyun ~]# name5='&&& &&& $SHELL' [root@tengxunyun ~]# name6="kkk #### $SHELL" [root@tengxunyun ~]# echo $name1 pingguo [root@tengxunyun ~]# echo $name2 li [root@tengxunyun ~]# echo $name3 juzi [root@tengxunyun ~]# echo $name4 ^^^^ [root@tengxunyun ~]# echo $name5 &&& &&& $SHELL [root@tengxunyun ~]# echo $name6 kkk #### /bin/bash
變量使用反引號賦值
若是是變量的話,必定要加$否則它覺得是普通文件,帶_劃線的變量須要將前面變量{}起來
[root@tengxunyun ~]# time=`date` [root@tengxunyun ~]# echo time time [root@tengxunyun ~]# echo $time Thu Feb 20 13:34:26 CST 2020 [root@tengxunyun ~]# file=`ll` [root@tengxunyun ~]# echo $file total 4 -rw-r--r-- 1 root root 26 Feb 20 12:07 test.sh [root@tengxunyun ~]# echo ${time}_day Thu Feb 20 13:34:26 CST 2020_day [root@tengxunyun ~]# echo $time-day Thu Feb 20 13:34:26 CST 2020-day
**編寫腳本的時候咱們須要將註釋加到腳本的開頭,這樣的話,能夠增長咱們的腳本的規範
使用vimrc文件**
[root@zhaocheng ~]# cat .vimrc 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: clsn") call setline(6, "# Organization: http://blog.znix.top") call setline(7, "# Created Time : ".strftime("%F %T")) call setline(8, "# Description:") call setline(9, "##############################################################") call setline(10, "") endif endfunc
位置變量
$0獲取當前的shell腳本的文件名,$1也就是獲取的第二個參數,$2是獲取的第二個參數,${11}當參數超過9以上就須要使用{}引發來
[root@zhaocheng ~]# cat test.sh #!/bin/bash echo $0 echo "第一個參數:"$1 echo "第二個參數:"$2 echo "第11個參數:"${11} [root@zhaocheng ~]# bash test.sh 1 3 3 5 6 78 8 89 9 654 77 test.sh 第一個參數:1 第二個參數:3 第11個參數:77
$#至關於列出總共多少個參數
[root@zhaocheng ~]# cat test.sh #!/bin/bash echo $0 echo "第一個參數:"$1 echo "第二個參數:"$2 echo "第11個參數:"${11} echo "列出有多少個參數:"$# [root@zhaocheng ~]# bash test.sh 66 99 00 9990 test.sh 第一個參數:66 第二個參數:99 第11個參數: 列出有多少個參數:4
*$至關於列出全部的參數**
[root@zhaocheng ~]# cat test.sh #!/bin/bash echo $0 echo "第一個參數:"$1 echo "第二個參數:"$2 echo "第11個參數:"${11} echo "列出有多少個參數:"$# echo "列出全部輸出的參數:"$* [root@zhaocheng ~]# bash test.sh 99 00 88 77 66 55 44 33 test.sh 第一個參數:99 第二個參數:00 第11個參數: 列出有多少個參數:8 列出全部輸出的參數:99 00 88 77 66 55 44 33
*$和¥@對比**
[root@zhaocheng ~]# set -- "It's" a nice day today [root@zhaocheng ~]# echo $1 It's [root@zhaocheng ~]# echo $2 a [root@zhaocheng ~]# echo $3 nice [root@zhaocheng ~]# echo $4 day [root@zhaocheng ~]# echo $5 today [root@zhaocheng ~]# for i in $1;do echo $i;done It's [root@zhaocheng ~]# for i in $2;do echo $i;done a [root@zhaocheng ~]# for i in $*;do echo $i;done It's a nice day today [root@zhaocheng ~]# for i in $#;do echo $i;done 5 [root@zhaocheng ~]# for i in $@;do echo $i;done It's a nice day today [root@zhaocheng ~]# for i in "$@";do echo $i;done It's a nice day today
進程狀態變量
shell進程特殊狀態變量
**定義變量方式
一、直接賦值
二、傳遞參數
三、交互式設置變量,使用read命令
read在命令行的使用**
[root@zhaocheng ~]# read 999 [root@zhaocheng ~]# echo $REPLY 999 [root@zhaocheng ~]# read kele [root@zhaocheng ~]# read kele niunai [root@zhaocheng ~]# echo $kele niunai [root@zhaocheng ~]# echo $REPLY 999
在腳本中的使用
[root@zhaocheng ~]# cat echo.sh #!/bin/bash read -p "請輸入:" i echo $i [root@zhaocheng ~]# bash echo.sh 請輸入:chengzhi chengzhi
賦值的使用,CHA定義變量ls
,這個是咱們的shell命令就須要使用反引號引用起來,通常比較長的目錄能夠直接寫成變量的形式,在shell腳本中直接引用,這樣看起來比較簡潔,這裏是找出這個文件下以.yaml結尾的文件並統計大小和倒着排序
[root@zhaocheng ~]# cat fuzhi.sh #!/bin/bash CHA=`ls` DIR=/opt/k8s/ansible echo $CHA find $DIR -name "*.yaml" |xargs du -sh |sort -nr [root@zhaocheng ~]# bash fuzhi.sh canshu.sh echo.sh fuzhi.sh tianqi.sh yum.sh 8.0K /opt/k8s/ansible/ansible-k8s/ansible-install-k8s/roles/addons/files/kubernetes-dashboard.yaml 8.0K /opt/k8s/ansible/ansible-k8s/ansible-install-k8s/roles/addons/files/kube-flannel.yaml 8.0K /opt/k8s/ansible/ansible-k8s/ansible-install-k8s/roles/addons/files/ingress-controller.yaml 8.0K /opt/k8s/ansible/ansible-k8s/ansible-install-k8s/roles/addons/files/coredns.yaml 4.0K /opt/k8s/ansible/ansible-k8s/ansible-install-k8s/roles/master/files/kubelet-bootstrap-rbac.yaml 4.0K /opt/k8s/ansible/ansible-k8s/ansible-install-k8s/roles/master/files/apiserver-to-kubelet-rbac.yaml
交互式設置變量read
經常使用參數
-p:給出提示符。默認不支持"\n"換行
-s:靜默模式。輸入的內容不會回顯在屏幕上
-t:給出超時時間,在達到超時時間時,read退出並返回錯誤
-n:限制讀取N個字符就自動結束讀取,若是沒有讀滿N個字符就按下回車或遇到換行符,則也會結束讀取
-N:嚴格要求讀滿N個字符才自動結束讀取,即便中途按下了回車或遇到了換行符也不結束。其中換行符或回車算一個字符
-a:將分裂後的字段依次存儲到指定的數組中,存儲的起始位置從數組的index=0開始
-p:給出提示符
read的基本用法
[root@zhaocheng ~]# cat read.sh #!/bin/bash read -p "請輸入你的名字:" lakey read -s -p "請輸入你的性別:" girl read -s -p "請輸入你有沒有對象:" ggg echo echo -e "\033[35m 你的名字是:$lakey \033[0m" echo -e "\033[35m 你的性別是:$girl \033[0m" echo -e "\033[35m 不,你不可能有對象:$ggg \033[0m"
shell中expr的用法
判斷輸入是否爲整數,非整數返回值爲2
計算變量的長度
[root@zhaocheng ~]# expr 1+1
1+1
[root@zhaocheng ~]# expr 1 + 1
2
[root@zhaocheng ~]# expr 1 1
expr: syntax error
[root@zhaocheng ~]# expr 1 * 1
1
[root@zhaocheng ~]# expr 1 \ 3
3
非整數返回值爲2示例
[root@zhaocheng ~]# expr -1 + 1
0
[root@zhaocheng ~]# echo $?
1
[root@zhaocheng ~]# echo a + 1
a + 1
[root@zhaocheng ~]# expr a + 1
expr: non-integer argument
[root@zhaocheng ~]# echo $?
2
$[ ]運算符
[root@zhaocheng ~]# echo $[1+2]
3
[root@zhaocheng ~]# echo $[122]
122
[root@zhaocheng ~]# echo $[1-2]
-1
[root@zhaocheng ~]# echo $[1*2]
2
[root@zhaocheng ~]# echo $[1/2]
0
shell中的文件判斷
經常使用文件測試操做符
判斷這個文件有沒有存在,存在的話輸出0也就爲真,爲1也就爲假
[root@zhaocheng ~]# [ -f /etc/hosts ] [root@zhaocheng ~]# echo $? 0 [root@zhaocheng ~]# [ -f /etc/hosts2 ] [root@zhaocheng ~]# echo $? 1
判斷文件是否存在,返回方式
可使用顏色進行輸出
判斷目錄是否存在
在腳本中使用判斷語法目錄
[root@zhaocheng ~]# cat panduan.sh #!/bin/bash DIR=/opt/k8s1 COLOR="\033[33m 目錄存在 \033[0m " [ -d $DIR ] && echo -e $COLOR || echo "目錄不存在" [root@zhaocheng ~]# bash panduan.sh 目錄不存在
字符串判斷
字符串操做符
-z 判斷字符串長度
-n 判讀字符串長度
[root@zhaocheng ~]# cat panduanzifu.sh #!/bin/bash ZIFU=33 [ -z $ZIFU ] && echo "輸出爲空" || echo "輸出有內容" [root@zhaocheng ~]# bash panduanzifu.sh 輸出有內容 [root@zhaocheng ~]# cat panduanzifu.sh #!/bin/bash ZIFU= [ -z $ZIFU ] && echo "輸出爲空" || echo "輸出有內容" [root@zhaocheng ~]# bash panduanzifu.sh 輸出爲空
[root@zhaocheng ~]# cat panduanzifu.sh #!/bin/bash ZIFU= [ -n $ZIFU ] && echo "輸出爲空" || echo "輸出有內容" [root@zhaocheng ~]# bash panduanzifu.sh
輸出爲空
整數判斷
整數二元比較操做符
判斷兩數是否相等,0爲真判斷成立,1爲假
[root@zhaocheng ~]# [ 1 -eq 0 ] [root@zhaocheng ~]# echo $? 1 [root@zhaocheng ~]# [ 1 -eq 1 ] [root@zhaocheng ~]# echo $? 0 [root@zhaocheng ~]# [ 9 -gt 6 ] && echo "正確" || echo "錯誤"
正確
邏輯符號
經常使用邏輯符號
邏輯操做符與整數判斷配合
45不等於40 90等於90,判讀是對的就成立 [root@zhaocheng ~]# [ 45 -ne 40 -a 90 -eq 90 ] && echo 對 || echo 不對 對 下面這個只要有一個不對,這個就不成立 [root@zhaocheng ~]# [ 45 -ne 40 -a 90 -eq 98 ] && echo 對 || echo 不對 不對
-o 至少有一個是成立的就返回爲真
[root@zhaocheng ~]# [ 45 -ne 40 -o 90 -eq 98 ] && echo 對 || echo 不對 對
!12,特殊用法,直接打開第12條命令
if條件語句
單分支語句
[root@zhaocheng ~]# cat dan.sh #!/bin/bash DIR=/etc/hosts if [ -f $DIR ] then echo "文件存在" fi [root@zhaocheng ~]# bash dan.sh 文件存在
多分支語句
[root@zhaocheng ~]# cat duo.sh #!/bin/bash DIR=/etc/keepalived.conf if [ -f $DIR ] then echo "存在" else echo "不存在" fi [root@zhaocheng ~]# bash duo.sh 存在
[root@zhaocheng ~]# cat bijiao.sh #!/bin/bash A=19 B=8 if [ $A -gt $B ] then echo "$A > $B" else echo "$A < $B" fi [root@zhaocheng ~]# bash bijiao.sh 19 > 8 [root@zhaocheng ~]# cat bijiao.sh #!/bin/bash A=19 B=89 if [ $A -gt $B ] then echo "$A > $B" else echo "$A < $B" fi [root@zhaocheng ~]# bash bijiao.sh 19 < 89