Shell指令碼(1)
將自己之前的shell指令碼筆記搬到segmentfault,順帶複習一下shell基礎。2019-1-26
shell指令碼介紹
Shell介紹
Shell是一個命令直譯器,作用是解釋執行使用者輸入的命令程式等,使用者每輸入一條命令,Shell就執行解釋一條。這種從鍵盤輸入命令就可以得到迴應的方式叫做互動的方式。
Shell存在於作業系統的最外層,負責與使用者直接對話,把使用者的輸入解釋給作業系統,並處理各種作業系統的輸出結果,然後輸出到螢幕給使用者。
Shell指令碼
當命令或程式語句不在命令列下執行,而是通過一個程式檔案來執行,這個檔案就叫做Shell指令碼。
Shell指令碼很適合用於處理純文字型別的資料,而Linux系統中幾乎所有的配置檔案,日誌檔案(NFS,Rsync,Httpd,Nginx,LVS 等),以及絕大多數的啟動檔案都是純文字型別的檔案。因此,學好shell語言,就可以利用它在linux系統中發揮巨大的作業。
檢視CentOS系統預設的Shell
[root@moli_linux1 ~]# echo $SHELL /bin/bash [root@moli_linux1 ~]# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash
Shell指令碼的建立和執行
Shell指令碼的建立
一個規範的Shell指令碼在第一行會指出由那個程式(直譯器)來執行指令碼的內容,這一行內容在Linux bash程式設計中一般為:
#!/bin/bash
或者
#!/bin/sh
注意:這一行必須位於每個指令碼頂端的第一行,如果不是第一行則為指令碼註釋行。且shell指令碼檔案的字尾名通常以.sh
結尾。
Shell指令碼的執行
1.bash script-name
(指令碼的路徑名字)或者sh script-name
:這是當指令碼檔案沒有可執行許可權時常用的放法
2.path/script-name
或者./script-name
:指在當前路徑下執行指令碼(指令碼需要有可執行許可權)。即需要將指令碼檔案的許可權先修改為可執行,chmod +xscript-name
。然後通過指令碼的絕對路徑和相對路徑就可以直接執行指令碼。
shell指令碼中的變數
什麼是變數
變數是暫時儲存資料的地方及資料標記,所儲存的資料存在於記憶體空間中,通過正確地呼叫記憶體空間中變數的名字就可以取出與變數對應的資料。CentOS中變數的定義直接由一個賦值符號=
就可以建立一個變數,而echo
命令類似於其他語言的print
命令,列印這個變數的值。
[root@moli_linux1 ~] name="laowan" #定義一個變數 [root@moli_linux1 ~] echo $name#列印這個變數的值 laowan [root@moli_linux1 ~] age=14 [root@moli_linux1 ~] echo $age 14
shell變數的特性
預設情況下,在bash shell 中是不會區分變數型別的。
變數型別
變數分為:環境變數(全域性變數)和普通變數(區域性變數)
環境變數可以在建立它們的shell以及其派生出來的任意子程序shell中使用。環境變數又分為自定義環境變數和bash內建的環境變數。
普通變數只能在建立它們的shell函式或shell指令碼中使用。
提示:有三個命令可以檢視系統中變數的值:set、env、declare。
- set命令輸出所有的變數;
- env只顯示全域性變數;
- declare命令輸出所有的變數,函式,整數和已經匯出的變數。
- set -o命令顯示bash shell的所有引數配置資訊。
環境變數的定義
上面定義一個變數是在一個shell中直接使用賦值符號對這個變數進行建立,但是當開啟一個新的子shell,列印這個變數卻不能打印出來。這是因為我們建立的變數是一個普通變數,若想在其他子shell中使用這個變數,需要將這個變數設定為全域性變數。而定義一個全域性變數的方法如下:
export 變數名=value 或者 declare -x 變數名=value
第二個方法是將變數名新增到環境變數檔案/etc/profile
編輯環境配置檔案 vim /etc/profile 在檔案最後面新增 export name="laowan" 儲存,退出。重新載入檔案 source /etc/profile 列印變數的值 echo $name laowan
而CentOS中,全域性環境變數的配置檔案有三個,分別是:
- /etc.profile
- /etc/bashrc
- /etc/profile.d #這是一個目錄
當用戶登入Linux系統時,首先會先載入/etc/profile全域性環境變數檔案,這是Linux系統預設的Shell主配置檔案,其次會執行/etc/profile.d下的指令碼檔案,要做重啟Linux系統後初始化或者顯示某些內容,只需要把指令碼檔案放在/etc/progile.d下即可,最後才會執行bashrc檔案。
設定登入提示符
Linux中可以設定登入之後,或者遠端連線伺服器開啟的shell中顯示登入提示符。設定登入提示內容的檔案是/etc/motd,編輯這個檔案就可以設定每次登入提示的內容。例如:
[root@moli_linux1 ~]# cat /etc/motd welcome to my Linux Server! 開啟一個新的shell Connecting to 192.168.30.3:22... Connection established. To escape to local shell, press 'Ctrl+Alt+]'. WARNING! The remote SSH server rejected X11 forwarding request. Last login: Sat Jan 26 19:35:54 2019 from 192.168.30.1 welcome to my Linux Server!
可以看到登入提示符。
定義變數不加單引號和雙引號,加單引號,加雙引號的區別
[root@moli_linux1 ~] a=10 [root@moli_linux1 ~] b=10-$a [root@moli_linux1 ~] c='100-$a' [root@moli_linux1 ~] d="100-$a" [root@moli_linux1 ~] echo $a 10 [root@moli_linux1 ~] echo $b 10-10 [root@moli_linux1 ~] echo $c 100-$a [root@moli_linux1 ~] echo $d 100-10
第一種定義b變數的方式,當內容為簡單連續的數字,字串,路徑名時,可以這樣用,不加引號時,值裡有變數的會被解析後輸出。
第二種定義c的變數有加單引號,這樣輸出變數時單引號裡面內容是什麼就是什麼,即使有變數和命令也是直接輸出。
第三種定義d變數的方式加了雙引號,這種輸出變數內容時引號裡的變數以及命令會經過解析後再輸出內容,這種方式比較適合字串中附帶有變數以及命令且想將其解析後再輸出的變數定義。
取消變數
取消變數使用unset命令,注意要取消的變數之前不用新增$
符號。
[root@moli_linux1 ~] a=100 [root@moli_linux1 ~] echo $a 100 [root@moli_linux1 ~] unset a [root@moli_linux1 ~] echo $a #可以看到這個變數的為空 [root@moli_linux1 ~]#
將一個命令的結果賦值給一個新的變數
生產環境中把命令的結果作為變數的內容進行賦值的方法在指令碼開發時很常見。有兩個方法可以實現。
變數名=$(命令) 或者: 變數名=`命令` [root@moli_linux1 ~] ls 192.168.229anaconda-ks.cfggit_dataservershell-100test-find [root@moli_linux1 ~] file=$(ls) [root@moli_linux1 ~] echo $file 192.168.229 anaconda-ks.cfg git_data server shell-100 test-find [root@moli_linux1 ~] file2=`ls` [root@moli_linux1 ~] echo $file2 192.168.229 anaconda-ks.cfg git_data server shell-100 test-find
Shell中的特殊變數
shell中特殊位置引數變數
要從命令列,函式或指令碼執行等處傳遞引數時,就要在shell指令碼中使用位置引數變數。
- $0 :獲取當前執行的shell指令碼的檔名,如果執行指令碼包含了路徑,那麼就包括指令碼路徑
- $1:獲得當前執行的shell指令碼的第n個引數值,n=1.......9,當n為0時表示指令碼的檔名,當n大於9時,則用大括號括起來,例如$(10),接的引數以空格隔開
- $# : 獲取當前執行的shell指令碼後面接的引數的總個數
- $* :獲取當前Shell指令碼所有傳參的引數,不加引號和$@相同,如果給$*加上雙引號,例如“$*”,則表示將所有的引數視為單個字串,相當於“$1$2$3”
- #@ :獲取當前shell指令碼所有傳參的引數,不加引號和$*相同;如果給$@加上雙引號,例如:“$@”,則表示將所有的引數視為不同獨立的字串,相當於“$1","$2"."$3”....這是將多引數傳遞給其他程式的最佳方式。
示例1,特殊位置變數$1
[root@moli_linux1 script] cat test.sh #!/bin/bash echo $1 #指令碼的功能是列印指令碼傳遞的第一個引數的值 [root@moli_linux1 script] sh test.sh laowan #傳入一個字串引數,賦值給$1 laowan [root@moli_linux1 script] sh test.sh laowan xiaoming #傳入多個引數,但指令碼不會接收多個引數,因此只輸出第一個引數的值 laowan [root@moli_linux1 script] sh test.sh "I am laowan" #用雙引號括起來代表一個引數 I am laowan
示例2,特殊位置變數$1,$2,$3....${10}
[root@moli_linux1 script] echo \${1..15} > test2.sh [root@moli_linux1 script] cat test2.sh #!/bin/bash echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 [root@moli_linux1 script] sh test2.sh {a..z}#傳入26個字母a~z,作為26個引數 a b c d e f g h i a0 a1 a2 a3 a4 a5 #位置引數的數字大於9後,輸出內容就不對了 [root@moli_linux1 script] vim test2.sh [root@moli_linux1 script] cat test2.sh #!/bin/bash #位置引數的數字大於9時,需要用大括號將數字括起來 echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} [root@moli_linux1 script] sh test2.sh {a..z} a b c d e f g h i j k l m n o #大於9的數字加上大括號後顯示正確的內容
示例3,特殊變數$0--獲取指令碼的名稱以及路徑:
[root@moli_linux1 shell_test] cat 05-getName.sh #!/bin/bash echo $0 [root@moli_linux1 shell_test] sh 05-getName.sh 05-getName.sh