首頁 > 軟體

Shell指令碼基礎知識與重定向與管道操作

2020-06-16 16:29:12

一、Shell指令碼基礎

Linux系統中的Shell指令碼是一個特殊的應用程式,它介於作業系統核心與使用者之間,充當了一個“命令直譯器”的角色,負責接收使用者輸入的操作命令並進行解釋,將需要執行的操作傳遞給核心執行,並輸出執行結果。

1、簡單編寫Shell指令碼

[root@CentOS01 ~]# vim aaa.sh    <!--新建aaa.sh檔案-->
#!/bin/bash
#Description E-Mail:2807489749@qq.com BY:LYX
cd /boot/
echo "顯示當前目錄:"
pwd
echo "檢視以vml開頭的檔案:"
ls -lh vml*
[root@centos01 ~]# chmod +x aaa.sh     <!--新增可執行許可權-->

上述aaa.sh指令碼檔案中,第一行“#!/bin/bash”是一行特殊的指令碼宣告,表示此行以後的語句通過/bin/bash程式來解釋執行;其他以“#”開頭的語句表示注釋資訊;echo命令用於輸出字串,以使指令碼的輸出資訊更容易讀懂。上述設定包括三條命令:cd /boot/、pwd、ls -lh vml*。執行此指令碼檔案後,輸出結果與依次單獨執行這三條命令是相同的,從而實現了“批次處理”的自動化過程。

通過“./aaa.sh”的方式執行指令碼,執行之前必須授權於檔案的X許可權。

[root@centos01 ~]# ./aaa.sh    <!--執行指令碼檔案-->
/boot
-rwxr-xr-x. 1 root root 5.7M 10月 23 22:35 vmlinuz-0-rescue-2b580d1a2e8348b8aa9f78be11137b41
-rwxr-xr-x. 1 root root 5.7M 8月  23 2017 vmlinuz-3.10.0-693.el7.x86_64
[root@centos01 ~]# source aaa.sh  <!--通過source來解釋指令碼-->
[root@centos01 ~]# sh aaa.sh     <!--通過/bin/sh來解釋指令碼-->

二、重定向與管道操作

1、重定向輸出

表示將命令的正常輸出結果儲存到指定的檔案中,並覆蓋檔案中的原有內容,若檔案不存在,則會新建一個檔案使用 “>”操作符號。

表示將命令的正常輸出結果追加到指定的檔案中sh使用“>>”操作符號。

舉個例子:

[root@centos01 ~]# echo "aaa"  <!--資料輸出到顯示器上顯示-->
aaa
[root@centos01 ~]# echo "aaa" > 1.txt    <!--將資料輸出到檔案中-->
[root@centos01 ~]# cat 1.txt      <!--檢視檔案中資料-->
aaa
[root@centos01 ~]# echo "bbb" >> 1.txt      <!--將資料追加輸出到1.txt檔案中-->
[root@centos01 ~]# cat 1.txt         <!--檢視檔案-->
aaa
bbb

2、重定向輸入

重定向輸入指的是將命令中接收輸入的途徑由預設的鍵盤改為指定的檔案,而不是等待從鍵盤輸入。重定向輸入使用“<”操作符。

舉個例子:
使用passwd命令為使用者設定密碼時,每次都必須根據提示輸入兩次密碼字串,非常繁瑣,若改用重定向輸入將可以省略互動式的過程,而自動完成密碼設定。

[root@centos01 ~]# useradd bob  <!--建立bob使用者-->
[root@centos01 ~]# vim password.txt     <!--新增初始密碼串-->
pwd@123                    <!--密碼為pwd@123-->
[root@centos01 ~]# passwd --stdin bob < password.txt      <!--從password.txt檔案中取密碼-->
更改使用者 bob 的密碼 。
passwd:所有的身份驗證令牌已經成功更新。

3、錯誤重定向

錯誤重定向指的是將執行命令過程中出現的錯誤資訊(如選項或引數錯誤等)儲存到指定的檔案,而不是直接顯示在螢幕上。錯誤重定向使用 “2>”操作符,其中“2”是指錯誤檔案的編號(在使用標準輸出、標準輸入重定向時,實際上省略了1、0編號)。

舉個例子:
執行以下操作可以將使用tar命令進行備份時出現的錯誤資訊儲存到3.txt檔案中。

[root@centos01 ~]# tar jcf /nonedir/etc.tgz /etc/ 2> 3.txt
[root@centos01 ~]# 
[root@centos01 ~]# cat 3.txt
tar: 從成員名中刪除開頭的“/”
tar (child): /nonedir/etc.tgz:無法 open: 沒有那個檔案或目錄
tar (child): Error is not recoverable: exiting now

使用“2>”操作符時,會像使用“>”操作符一樣覆蓋目標檔案的內容,若要追加內容而不是覆蓋檔案,則應改用“2>>”操作符。
當命令輸出的結果可能即包括標準輸出(正常執行)資訊,又包括錯誤輸出資訊時,可以使用操作符“>” “2>”將兩類輸出資訊分別儲存到不同的檔案,也可以使用“&>”操作符兩兩類輸出資訊儲存到同一個檔案。
舉個例子:

[root@centos01 ~]# vim httpd.sh   <!--新建httpd.sh檔案-->
#!/bin/bash
#自動編譯安裝httpd伺服器
cd /usr/src/httpd-2.2.17/
echo "1.設定Apache服務:"
./configure --prefix=/usr/local/httpd --enable-so --enable-rewrite --enable-charset-lite --enable-cgi &> /dev/null
echo "2.編譯Apache服務:"
make &> /dev/null
echo "3.安裝Apache服務:"
make install &> /dev/null
[root@centos01 ~]# chmod +x httpd.sh   <!--新增X許可權-->
[root@centos01 ~]# ./httpd.sh     <!--執行指令碼檔案-->
1.設定Apache服務:
2.編譯Apache服務:
3.安裝Apache服務:

4、管道操作

管道(pipe)操作為不同命令之間的協同工作提供了一種機制,位於管道符號“|”左側的命令輸出的結果,將作為右側命令的輸入(處理物件),同一行命令中可以使用多個管道。

舉個例子:

[root@centos01 ~]# grep "/bin/bash$" /etc/passwd  <!--提取前-->
root:x:0:0:root:/root:/bin/bash
test:x:1000:1000:test:/home/test:/bin/bash
bob:x:1002:1002::/home/bob:/bin/bash
[root@centos01 ~]# grep "/bin/bash$" /etc/passwd | awk -F: '{print $1,$7}'   <!--提取後-->
root /bin/bash
test /bin/bash
bob /bin/bash
[root@centos01 ~]# df -hT     <!--提取之前-->
檔案系統       型別      容量  已用  可用 已用% 掛載點
/dev/sda3      xfs        76G  5.2G   71G    7% /
devtmpfs       devtmpfs  474M     0  474M    0% /dev
tmpfs          tmpfs     489M     0  489M    0% /dev/shm
tmpfs          tmpfs     489M  6.9M  482M    2% /run
tmpfs          tmpfs     489M     0  489M    0% /sys/fs/cgroup
/dev/sda1      xfs       197M  136M   61M   70% /boot
tmpfs          tmpfs      98M     0   98M    0% /run/user/0
/dev/sr0       iso9660   664M  664M     0  100% /mnt
[root@centos01 ~]# df -hT | grep "/$" |awk '{print $6}'   <!--提取之後其中grep “/$”表示提取以“/”結尾的行-->
7%

上述中awk命令的作用是以冒號“:”作為分隔,輸出第1個,第7個區域的字串。其中的“-F”部分用來指定分割符號(未指定時,預設以空格或製表符分隔)。

三、使用Shell變數

各種Shell環境中都使用到了“變數”的概念。Shell變數用來存放系統和使用者需要使用的特定引數(值),而且這些引數可以根據使用者的設定或系統環境的變化而相應變化。通過使用變數,Shell程式能夠提供更加靈活的功能,適應性更強。
常見Shell變數的型別包括自定義變數、環境變數、位置變數、預定義變數。

1、自定義變數

自定義變數是由系統使用者自己定義的變數,只在使用者自己的Shell環境中有效,因此又稱為本地變數。在編寫Shell指令碼程式時,通常會設定一些特定的自定義變數,以適應程式執行過程中的各種變化,滿足不同的需求。

1)定義新的變數

定義變數的基本格式為“變數名=變數值”,等號兩邊沒有空格。變數名稱需以字母或下劃線開頭,名稱中不要包含特殊字元(如+、-、*、/、?、%、&、#等)。

[root@centos01 ~]# li=Python
[root@centos01 ~]# version=2.7.13

2)檢視和參照變數的值

通過在變數名稱前新增前導符號“$”,可以參照一個變數的值。使用echo命令可以檢視變數,可以在一條echo命令中同時檢視多個變數值。

[root@centos01 ~]# echo $li
python
[root@centos01 ~]# echo $version
2.7.13
[root@centos01 ~]# echo $li $version
python 2.7.13

3)變數賦值的特殊操作

在等號“=”後邊直接指定變數內容是為變數賦值的最基本方法,除此之外,還有一些特殊的賦值操作,可以更靈活地位變數賦值,以便適用於各種複雜的管理任務。

①雙引號(" ")

[root@centos01 ~]# PYTHON=python 2.7.13  <!--錯誤賦值-->
bash: 2.7.13: 未找到命令...
[root@centos01 ~]# PYTHON="python 2.7.13" <!--正確的賦值-->
[root@centos01 ~]# echo $PYTHON   <!--檢視值-->
python 2.7.13

在雙引號範圍內,使用“$”符號可以參照其他變數的值(變數參照),從而能夠直接呼叫現有變數的值來賦給新的變數。

[root@centos01 ~]# echo $version
2.7.13
[root@centos01 ~]# sqlserver="sqlserver $version" 
                                       <!--以變數的值進行賦值-->
[root@centos01 ~]# echo $sqlserver    <!--檢視值-->
sqlserver 2.7.13

②單引號(' ')

當要賦值的內容中包含$、“、等具有特殊含義的字元時,應使用單引號括起來。在單引號的範圍內,將無法參照其他變數的值,任何字元均作為普通字元看待。

[root@centos01 ~]# sqlserver='sqlserver $version'  <!--$符號不能再參照變數-->
[root@centos01 ~]# echo $sqlserver      <!--原樣輸出字串-->
sqlserver $version

③反撇號(`)

反撇號主要用於命令替換,允許將執行某個命令的螢幕輸出結果賦值給變數。反撇號括起來的範圍必須能夠執行的命令列,否則將會出錯。

[root@centos01 ~]# ls -lh `which useradd`
-rwxr-x---. 1 root root 116K 11月  6 2016 /usr/sbin/useradd

上述操作相當於連續執行了兩條命令——先通過which useradd命令查詢出useradd命令的程式位置,然後根據查詢結果列出檔案屬性。執行過程中,會用which useradd命令的輸出結果替換整個反撇號範圍。

④read命令

除了上述賦值操作以外,還可以使用bash的內建命令read來給變數賦值。read命令用來提示使用者輸入資訊,從而實現簡單的互動過程。執行時將從標準輸入裝置(鍵盤)讀入一行內容,並以空格為分隔符,將讀入的各欄位依次賦值給指定的變數(多餘的內容賦值給最後一個變數)。若指定的變數只有一個,則將整行內容賦值給此變數。

[root@centos01 ~]# read -p "輸入需要的內容:" insert
輸入需要的內容:您好!  <!--將您好!賦值給變數insert-->
[root@centos01 ~]# echo $insert
您好!

4)設定變數的作用範圍

預設情況下,新定義的變數只在當前的Shell環境中有效,因此稱為區域性變數。當進入子程式或新的子Shell環境時,區域性變數將無法再使用。例如,直接執行Bash進入一個新的子Shell指令碼後,將無法參照父級Shell環境中定義的li、version等變數。

[root@centos01 ~]# echo "$li $version"   <!--檢視當前定義的變數值-->
python 2.7.13
[root@centos01 ~]# bash            <!--進入子shell環境-->
[root@centos01 ~]# echo "$li $version"        <!--無法呼叫父shell環境中的變數-->
[root@centos01 ~]# exit        <!--返回原有的shell環境-->
exit
[root@centos01 ~]# echo "$li $version"   <!--檢視當前定義的變數值-->
[root@centos01 ~]# export li version     <!--設定為全域性變數-->
[root@centos01 ~]# bash          <!--進入子shell環境-->
[root@centos01 ~]# echo "$li $version" <!--可以呼叫父shell的全域性變數-->
python 2.7.13
[root@centos01 ~]# exit     <!--返回原有的shell環境-->
exit

5)數值變數的運算

Shell變數的數值運算多用於指令碼程式的過程控制(如迴圈次數、使用量比較等)再Bash shell環境中,只能進行簡單的證書運算,不支援小數運算。整數值的運算主要通過內部命令expr進行,基本格式如下:

expr 變數1 運算子 變數2 [運算子 變數3]...

其中,變數1、變數2......對應為需要計算的數值變數(需要以“$”符號呼叫),常用的幾種運算子如下所述
+:加法運算;
-:減法運算;
*:乘法運算;注意不能僅使用“*”符號,否則將被當成檔案萬用字元;
/:除法運算;
%:求模運算,又稱為取餘運算,用來計算數值相除後的餘數;

舉個例子:

[root@centos01 ~]# x=35
[root@centos01 ~]# y=16
[root@centos01 ~]# expr $x + $y
51
[root@centos01 ~]# expr $x - $y
19
[root@centos01 ~]# expr $x * $y
560
[root@centos01 ~]# expr $x / $y
2
[root@centos01 ~]# expr $x % $y
3

2、特殊的shell變數

1)環境變數:

使用命令“env”可以檢視到當前工作環境下的環境變數。環境變數的值由Linux系統自動維護,會隨著使用者狀態的改變而改變。
其中PATH變數用於設定可執行程式的預設搜尋路徑,如將root目錄新增到預設搜尋路徑:PATH="$PATH:/root"如果找不到則會提示“command not found”

環境變數的全域性組態檔為:/etc/profile,在此檔案中定義的變數作用於所有使用者。

使用者獨立設定未見位於:~/.bash_profile

修改變數檔案後,須使用source命令重新讀取載入或重新啟動才會生效。

2)位置變數:

位置變數也稱位置引數,在命令 “ls -lh /boot” 中,ls的位置變數為$0,-lh的位置變數為$1,/boot的位置變數為$2。以此類推。

3)預定義變數:

預定義變數是由bash程式預先定義好的一類特殊變數,使用者只能使用預定義變數,而不能建立新的預定義變數,也不能直接為預定義變數賦值。預定義變數使用“$”符號和另一個符號組合表示,經常用的幾個預定義變數含義如下:

  • $#:表示命令列中位置引數的個數。

  • $*:表示所有位置引數的內容。

  • $?:表示前一條命令執行後返回的狀態,返回0表示執行正確,返回任何非0的數值表示執行出現異常。

  • $0:表示當前執行的指令碼或程式的名稱。

IT145.com E-mail:sddin#qq.com