Linux運維:Shell腳本(1)

將本身以前的shell腳本筆記搬到segmentfault,順帶複習一下shell基礎。筆記大可能是讀<<跟老男孩學Linux運維:Shell編程實站>>時所記錄,推薦想學shell的能夠去看看。2019-1-26

系列筆記傳送門:linux

shell腳本介紹

Shell介紹
Shell是一個命令解釋器,做用是解釋執行用戶輸入的命令程序等,用戶每輸入一條命令,Shell就執行解釋一條。這種從鍵盤輸入命令就能夠獲得迴應的方式叫作交互的方式。git

Shell存在於操做系統的最外層,負責與用戶直接對話,把用戶的輸入解釋給操做系統,並處理各類操做系統的輸出結果,而後輸出到屏幕給用戶。shell

Shell腳本
當命令或程序語句不在命令行下執行,而是經過一個程序文件來執行,這個文件就叫作Shell腳本。
Shell腳本很適合用於處理純文本類型的數據,而Linux系統中幾乎全部的配置文件,日誌文件(NFS,Rsync,Httpd,Nginx,LVS 等),以及絕大多數的啓動文件都是純文本類型的文件。所以,學好shell語言,就能夠利用它在linux系統中發揮巨大的做業。編程

查看CentOS系統默認的Shellvim

[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編程中通常爲:segmentfault

#!/bin/bash

或者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.229  anaconda-ks.cfg  git_data  server  shell-100  test-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

示例4,$#獲取腳本傳遞參數個數:

[root@moli_linux1 shell_test] cat 06-getNum.sh 
#!/bin/bash
echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
echo $# #傳遞的參數個數
[root@moli_linux1 shell_test] ./06-getNum.sh {a..z} #傳遞了26個字母,即26個參數
./06-getNum.sh a b c d e f g h i #接受了9個參數,所以打印9個字母
26 #傳遞了26個參數,打印出26

示例5,$#的常見實際應用
根據用戶在命令行傳參的個數判斷用戶的輸入,不符合的給出提示並退出,符合的打印出傳入的參數內容。

[root@moli_linux1 shell_test] cat t1.sh 
#!/bin/bash
if [  $# -ne 2 ] #若是執行腳本傳參的個數不等於2
    then
      echo "USAGE:/bin/sh $0 arg1 arg2" #則給用戶提示正確的用法,此處$0,打印腳本名字和路徑

      exit 1 #不滿要求,則退出腳本,返回值爲1
fi
    echo $1 $2 #符合要求,則打印$1 $2所獲取到的傳參的字符串

[root@moli_linux1 shell_test] sh t1.sh arg1 agr2  #符合傳參個數=2,打印出傳入參數的內容
arg1 agr2
[root@moli_linux1 shell_test] sh t1.sh arg1 agr2 arg3 #不符合傳參個數=2,給出提示並退出
USAGE:/bin/sh t1.sh arg1 arg2

Shell中特殊狀態變量

  • $? : 獲取執行上一個指令的執行狀態返回值(0爲成功,非0爲失敗),這個變量最經常使用。
  • $$ : 獲取當前執行的shell腳本的進程號(PID),不經常使用。
  • $! : 獲取上一個在後臺工做的進程號(PID),不經常使用。
  • $_ : 獲取在此以前執行的命令或腳本的最後一個參數,不經常使用。

$?的實踐1

[root@moli_linux1 ~] pwd  #執行pwd獲取當前路徑,用echo $?查看執行命令的狀態返回值
/root
[root@moli_linux1 ~] echo $?  
0 #返回0表示上一條命令執行成功

[root@moli_linux1 ~] rm shell_test/ #刪除目錄shell_test
rm: 沒法刪除"shell_test/": 是一個目錄 #沒加參數-r ,沒法刪除

[root@moli_linux1 ~] echo $?
1 #狀態碼非0,表示上一條執行不成功或者錯誤

$?的實踐2

[root@moli_linux1 ~] cat test1.sh 
#!/bin/bash
[  $# -ne 2 ] && {       #若是參數個數不=2
echo "must be two args." #則輸出提示
exit 119                 #終止程序並以指定的119狀態碼退出程序,賦值給當前shell的「$?」變量。
}
echo "success!"

[root@moli_linux1 ~]# sh test1.sh 1 2 3 #參數個數不=2
must be two args.
[root@moli_linux1 ~]# echo $?
119 #狀態碼爲119

"$?"的注意點:

  1. 判斷命令,腳本或函數等程序是否執行成功。經常使用於源碼編譯安裝軟件,在每一個步驟獲 取「$?」的狀態碼來判斷命令執行是否成功。
  2. 如果在腳本中調用執行"exit 數字",則會返回這個數字給"$?"變量。
  3. 若是是在函數裏,經過"return 數字"把這個數字以函數返回值的形式傳給"$?"。

Shell變量字串

變量字串表達式

表達式 說明
${parameter} 返回變量${parameter}的內容
${#parameter} 返回變量${parameter}內容的長度(按字符)
${parameter:offset} 在變量${parameter}的內容中,從位置offset以後開始提取字串到結尾
${parameter:offset:length} 在變量${parameter}中,從位置offset以後開始提取長度爲length的字串
${parameter#word} 從變量${parameter}開頭開始刪除最短匹配的word字串
${parameter##word} 從變量${parameter}開頭開始刪除最長匹配的word字串
${parameter%word} 從變量${parameter}結尾開始刪除最短匹配的word字串
${parameter%%word} 從變量${parameter}結尾開始刪除最短匹配的word字串
${parameter/pattern/string} 使用string替換第一個匹配的pattern
${parameter//pattern/string} 使用string替換全部匹配的pattern
  • 單獨一個「#」:表示從開頭刪除最短匹配
  • 兩個「##」:表示從開頭刪除最長匹配
  • 一個「%」:表示從結尾開始刪除最短匹配
  • 兩個「%%」:表示從結尾開始刪除最長匹配
  • 一個「/」:表示替換第一個
  • 兩個「//」:表示替換全部

示例1,變量的打印和提取切片:

# 定義變量parameter,內容爲abc123ABC456
[root@moli_linux1 script]# parameter="abc123ABC456" 

# 變量的兩種打印方式
[root@moli_linux1 script]# echo $parameter
abc123ABC456
[root@moli_linux1 script]# echo ${parameter}
abc123ABC456

# 打印這個變量內容的長度,一共12個字符 
[root@moli_linux1 script]# echo ${#parameter}
12

# 從變量內容的第三個開始,提取剩下的全部內容
[root@moli_linux1 script]# echo ${parameter:3}
123ABC456

# 從變量內容的第三個開始,提取接下來的6個字符
[root@moli_linux1 script]# echo ${parameter:3:6}
123ABC

示例2,變量的截取與替換:

# 定義變量,mori
[root@moli_linux1 script]# echo $mori
abc123ABC456abc

# 從開頭刪除了最短的a*c字串爲abc
[root@moli_linux1 script]# echo ${mori#a*c}
123ABC456abc

# 從開頭刪除了最長的a*c字串爲abc123ABC456abc,所有刪除了
[root@moli_linux1 script]# echo ${mori##a*c}

[root@moli_linux1 script]# 

# 從左到右將第一個遇到的小寫a替換爲大寫A
[root@moli_linux1 script]# echo ${mori/a/A}
Abc123ABC456abc

# 將變量裏全部的小寫a替換爲大寫A
[root@moli_linux1 script]# echo ${mori//a/A}
Abc123ABC456Abc
相關文章
相關標籤/搜索