Linux管理員 - Shell指令碼



Bash Shell簡介

像GNU Linux的不同版本一樣,Shell也有很多種類,並且相容性各不相同。CentOS中的預設Shell稱為Bash或Bourne Again Shell。Bash Shell是Stephen Bourne開發的Bourne Shell的現代化修改版本。Bash是Bell Labs的Ken Thompson和Dennis Ritchie在Unix作業系統上開發的原始Thompson Shell的直接替代品(Stephen Bourne也受僱於Bell Labs)

每個人都有自己喜歡的Shell,每個Shell都有其優勢和劣勢。但總的來說,Bash將成為所有Linux發行版中的預設Shell,並且是最常用的。隨著經驗的積累,每個人都會希望探索和使用最適合自己的Shell。但同時,每個人也希望掌握Bash Shell。

其他Linux Shell包括:Tcsh、Csh、Ksh、Zsh和Fish。

培養使用任何Linux Shell達到專家級別的技能對於CentOS管理員來說極其重要。正如我們之前提到的,與Windows不同,Linux的核心是一個命令列作業系統。Shell只是一個使用者介面,允許管理員(或使用者)向作業系統發出命令。如果Linux系統管理員是一位航空公司飛行員,那麼使用Shell就像將飛機從自動駕駛儀上移開,並抓住手動控制桿以進行更靈活的飛行。

像Bash這樣的Linux Shell在計算機科學術語中被稱為命令列直譯器。Microsoft Windows也有兩個命令列直譯器,稱為DOS(不要與原始DOS作業系統混淆)和PowerShell。

大多數現代Shell(如Bash)提供結構,允許更復雜的Shell指令碼自動化常見和複雜的任務。

結構包括 -

  • 指令碼流程控制(ifthen和else)
  • 邏輯比較運算(大於、小於、等於)
  • 迴圈
  • 變數
  • 定義操作的引數(類似於命令的開關)

使用Shell指令碼與指令碼語言

在考慮執行任務時,管理員常常會問自己:我應該使用Shell指令碼還是使用Perl、Ruby或Python等指令碼語言?

這裡沒有固定的規則。Shell與指令碼語言之間只有典型的區別。

Shell

Shell允許使用Linux命令,如sedgrepteecat以及Linux作業系統上的所有其他基於命令列的實用程式。事實上,幾乎所有命令列Linux實用程式都可以在您的Shell中編寫指令碼。

使用Shell的一個很好的例子是快速檢查主機列表以進行DNS解析的指令碼。

我們用於檢查DNS名稱的簡單Bash指令碼 -

#!/bin/bash 
for name in $(cat $1);
   do 
      host $name.$2 | grep "has address" 
   done 
exit

用於測試DNS解析的小型詞表 -

dns 
www 
test 
dev 
mail 
rdp 
remote

針對google.com域的輸出 -

[rdc@centos ~]$  ./dns-check.sh dns-names.txt google.com
-doing dns
dns.google.com has address 172.217.6.46
-doing www
www.google.com has address 172.217.6.36
-doing test
-doing dev
-doing mail
googlemail.l.google.com has address 172.217.6.37
-doing rdp
-doing remote

[rdc@centos ~]$

利用我們Shell中的簡單Linux命令,我們能夠製作一個簡單的5行指令碼,用於從詞表中稽核DNS名稱。即使使用良好實現的DNS庫,這在Perl、Python或Ruby中也需要花費相當長的時間。

指令碼語言

指令碼語言將提供Shell之外的更多控制。上面的Bash指令碼使用了Linuxhost命令的包裝器。如果我們想做更多的事情,並製作我們自己的類似於host的應用程式來與Shell之外互動呢?這就是我們使用指令碼語言的地方。

此外,對於高度維護的指令碼語言,我們知道我們的操作在很大程度上可以在不同的系統上工作。例如,Python 3.5可以在任何其他執行Python 3.5並安裝相同庫的系統上工作。如果我們想在Linux和HP-UX上執行我們的BASH指令碼,情況就不一樣了。

有時,指令碼語言和強大的Shell之間的界限可能會變得模糊。可以使用Python、Perl或Ruby自動化CentOS Linux管理任務。這樣做實際上非常普遍。此外,富有的Shell指令碼開發人員已經用Bash製作了一個簡單但功能齊全的Web伺服器守護程式。

透過指令碼語言和在Shell中自動化任務的經驗,CentOS管理員能夠快速確定在需要解決問題時從哪裡開始。從Shell指令碼開始一個專案是很常見的。然後,隨著專案變得越來越複雜,再轉向指令碼(或編譯)語言。

此外,對於專案的不同部分,同時使用指令碼語言和Shell指令碼也是可以的。例如,可以使用Perl指令碼抓取網站。然後,使用Shell指令碼使用sedawkegrep進行解析和格式化。最後,使用PHP指令碼透過Web GUI將格式化資料插入MySQL資料庫。

在瞭解了一些Shell的理論知識後,讓我們開始學習從CentOS中的Bash Shell自動化任務的基本構建塊。

輸入輸出和重定向

將stdout處理到另一個命令 -

[rdc@centos ~]$ cat ~/output.txt | wc -l 
6039 
[rdc@centos ~]$

上面,我們使用pipe字元將catstdout傳遞給wc進行處理。然後,wc處理來自cat的輸出,將output.txt的行數列印到終端。將pipe字元視為一個“管道”,將一個命令的輸出傳遞給另一個命令進行處理。

以下是處理命令重定向時需要記住的關鍵概念 -

編號 檔案描述符 字元
0 標準輸入 <
1 標準輸出 >
2 標準錯誤
追加stdout >>
分配重定向 &
將stdout管道到stdin |

我們在第一章中介紹了這一點,但並沒有真正談論重定向或分配重定向。在Linux中開啟終端時,您的Shell被視為以下內容的預設目標 -

  • 標準輸入 < 0
  • 標準輸出 > 1
  • 標準錯誤 2

讓我們看看它是如何工作的 -

[rdc@centos ~]$ lsof -ap $BASHPID -d 0,1,2 
 COMMAND   PID   USER    **FD**   TYPE DEVICE   SIZE/OFF   NODE      NAME 
 bash    13684    rdc    **0u**   CHR  136,0      0t0     3      /dev/pts/0 
 bash    13684    rdc    **1u**   CHR  136,0      0t0     3      /dev/pts/0 
 bash    13684    rdc    **2u**   CHR  136,0      0t0     3      /dev/pts/0
 
[rdc@centos ~]$  

/dev/pts/0是我們的偽終端。CentOS Linux檢視此內容並將其視為我們的開放終端應用程式,就像透過序列介面插入的真實終端,帶有鍵盤和顯示器。但是,就像虛擬機器管理程式將硬體抽象到作業系統一樣,/dev/pts將我們的終端抽象到應用程式中。

從上面的lsof命令中,我們可以在FD列中看到所有三個檔案描述符都設定為我們的虛擬終端(0、1、2)。我們現在可以傳送命令、檢視命令輸出以及與命令相關的任何錯誤。

以下是STDIN和STDOUT的示例 -

STDOUT

[root@centosLocal centos]# echo "I am coming from Standard output or STDOUT." >
output.txt && cat output.txt
I am coming from Standard output or STDOUT. 
[root@centosLocal centos]#

也可以將stdoutstderr都發送到不同的檔案 -

bash-3.2# find / -name passwd 1> good.txt 2> err.txt
bash-3.2# cat good.txt
/etc/pam.d/passwd
/etc/passwd
bash-3.2# cat err.txt 
find: /dev/fd/3: Not a directory
find: /dev/fd/4: Not a directory
bash-3.2#

在搜尋整個檔案系統時,遇到了兩個錯誤。每個錯誤都被髮送到一個單獨的檔案以供以後檢視,而返回的結果被放置到一個單獨的文字檔案中。

在執行輸出大量資料到終端的操作(如編譯應用程式)時,將stderr傳送到文字檔案可能很有用。這將允許檢視可能從終端回滾歷史記錄中丟失的錯誤。

將STDOUT傳遞到文字檔案時需要注意的一點是>>>之間的區別。雙“>>”將追加到檔案,而單數形式將覆蓋檔案並寫入新內容(因此所有先前的資料都將丟失)。

STDIN

[root@centosLocal centos]# cat < stdin.txt
Hello,
I am being read form Standard input, STDIN.

[root@centosLocal centos]#

在上面的命令中,文字檔案stdin.txt被重定向到cat命令,該命令將其內容回顯到STDOUT

管道字元“|”

管道字元將獲取第一個命令的輸出,將其作為輸入傳遞到下一個命令,允許第二個命令對輸出執行操作。

現在,讓我們將cat的stdout“管道”到另一個命令 -

[root@centosLocal centos]# cat output.txt | wc -l
2
[root@centosLocal centos]#

上面,wc對來自cat的輸出執行計算,該輸出是從管道傳遞的。管道命令在過濾grepegrep的輸出時特別有用 -

[root@centosLocal centos]# egrep "^[0-9]{4}$" /usr/dicts/nums | wc -l  
9000 
[root@centosLocal centos]#

在上面的命令中,我們將每個4位數字從包含從65535傳遞的所有數字的文字檔案中傳遞給wc,並透過egrep過濾器。

使用&重定向輸出

可以使用&字元重定向輸出。如果我們想將STDOUT和STDERR的輸出都重定向到同一個檔案,可以按如下方式完成 -

[root@centosLocal centos]# find / -name passwd > out.txt 2>&1
[root@centosLocal centos]# cat out.txt  
find: /dev/fd/3: Not a directory 
find: /dev/fd/4: Not a directory 
/etc/passwd

[root@centosLocal centos]#

使用&字元進行重定向的工作原理如下:首先,輸出被重定向到out.txt。其次,STDERR或檔案描述符2被重新分配到與STDOUT相同的位置,在本例中為out.txt

重定向非常有用,並且在處理操作大型文字檔案、編譯原始碼、在Shell指令碼中重定向輸出以及發出複雜的Linux命令時出現的各種問題時非常方便。

雖然功能強大,但對於較新的CentOS管理員來說,重定向可能會變得複雜。練習、研究以及偶爾向Linux論壇(如Stack Overflow Linux)提問將有助於解決高階解決方案。

Bash Shell結構

現在我們已經瞭解了Bash Shell的工作原理,讓我們學習一些常用的基本結構來編寫指令碼。在本節中,我們將探討 -

BASH故障排除提示

與專用的指令碼語言相比,BASH可能有點棘手。BASH指令碼中一些最大的障礙來自錯誤的轉義或未轉義傳遞給Shell的指令碼操作。如果您已經檢視過指令碼幾次,但它沒有按預期工作,請不要擔心。即使對於那些每天使用BASH建立複雜指令碼的人來說,這也是很常見的。

在Google上快速搜尋或註冊專家Linux論壇以提出問題將導致快速解決問題。很有可能有人遇到過完全相同的問題,並且已經解決了。

BASH指令碼是一種快速建立強大指令碼的絕佳方法,這些指令碼可用於從自動化管理任務到建立實用工具的所有方面。成為專家級BASH指令碼開發人員需要時間和實踐。因此,儘可能使用BASH指令碼,它是您CentOS管理工具箱中的一款很棒的工具。

linux_admin_shell_scripting.htm
廣告