Shell腳本編程與文件系統修復

導讀 Linux基金會發起了LFCS認證(Linux 基金會認證系統管理員)Linux Foundation Certified Sysadmin,這是一個全新的認證體系,旨在讓世界各地的人可以參與到中等水平的Linux系統的基本管理操做的認證考試中去,這項認證包括:維護正在運行的系統和服務的能力、全面監控和分析的能力以及什麼時候向上遊團隊請求支持的決策能力。

shell_file_repair_logo

Linux 基金會認證程序。

本講集中講解簡單的 Shell 腳本編程和文件系統修復。這兩塊內容都是 LFCS 認證中的必備考點。linux

理解終端 (Terminals)和 Shell

首先要聲明一些概念。shell

  • Shell 是一個程序,它將命令傳遞給操做系統來執行。
  • Terminal 也是一個程序,容許最終用戶使用它與 Shell 來交互。好比,下邊的圖片是 GNOME Terminal。


Gnome Terminal編程

啓動 Shell 以後,會呈現一個命令提示符 (也稱爲命令行) 提示咱們 Shell 已經作好了準備,接受標準輸入設備輸入的命令,這個標準輸入設備一般是鍵盤。你能夠參考該系列文章的 「如何在Linux上使用GNU sed等命令來建立、編輯和操做文件」來溫習一些經常使用的命令。
Linux 爲提供了許多能夠選用的 Shell,下面列出一些經常使用的:vim

bash
Shell

Bash 表明 Bourne Again Shell,它是 GNU 項目默認的 Shell。它借鑑了 Korn shell(ksh) 和 C shell (csh) 中有用的特性,並同時對性能進行了提高。它同時也是 LFCS 認證中所涵蓋的各發行版中默認 Shell,也是本系列教程將使用的 Shell。bash

sh
Shell

Bourne SHell 是一個比較古老的 shell,多年來一直都是不少類 Unix 系統的默認 shell。服務器

ksh
Shell

Korn SHell (ksh shell) 也是一個 Unix shell,是 貝爾實驗室 ( Bell Labs ) 的David Korn 在 19 世紀 80 年代初的時候開發的。它兼容 Bourne shell ,並同時包含了 C-shell 中的多數特性。
一個 shell 腳本僅僅只是一個可執行的文本文件,裏邊包含一條條可執行命令。網絡

簡單的 Shell 腳本編程

如前所述,一個 shell 腳本就是一個純文本文件,所以,可使用本身喜歡的文本編輯器來建立和編輯。你能夠考慮使用 vi/vim (參考本系列 「如何安裝和使用純文本編輯器 vi/vim」它的語法高亮讓個人編輯工做很是方便。
輸入以下命令來建立一個名爲 myscript.sh 的腳本文件:ssh

# vim myscript.sh

shell 腳本的第一行 (著名的釋伴行(shebang line)) 必須以下:編輯器

#!/bin/bash()

這條語句「告訴」操做系統須要用哪一個解釋器來運行這個腳本文件以後命令。
如今能夠添加須要執行的命令了。經過註釋,咱們能夠聲明每一條命令或者整個腳本的具體含義。注意,shell 會忽略掉以井號 (#) 開始的註釋語句。ide

#!/bin/bash
echo 這是關於 LFCS 認證系列的第十部分
echo 今天是 $(date +%Y-%m-%d)

編寫並保存腳本以後,經過如下命令來使腳本文件成爲可執行文件:

# chmod 755 myscript.sh

在執行腳本以前,咱們須要說一下環境變量 ($PATH),運行:

echo $PATH

咱們就會看到環境變量 ($PATH) 的具體內容:這是當輸入命令時系統所搜索可執行程序的目錄,每一項之間使用冒號 (:) 隔開。稱它爲環境變量,是由於它本是就是 shell 環境的一部分 —— 這是當 shell 每次啓動時 shell 及其子進程能夠獲取的一系列信息。
當咱們輸入一個命令並按下回車時,shell 會搜索 $PATH 變量中列出的目錄並執行第一個知道的實例。請看以下例子:

環境變量
假如存在兩個同名的可執行程序,一個在 /usr/local/bin,另外一個在 /usr/bin,則會執行環境變量中最早列出的那個,並忽略另一個。
若是咱們本身編寫的腳本沒有放在 $PATH 變量列出目錄中的任何一個,則須要輸入./filename 來執行它。而若是存儲在 $PATH 變量中的任意一個目錄,咱們就能夠像運行其餘命令同樣來運行以前編寫的腳本了。

# pwd
# ./myscript.sh
# cp myscript.sh ../bin
# cd ../bin
# pwd
# myscript.sh


執行腳本

if 條件語句

不管什麼時候,當你須要在腳本中根據某個命令的運行結果來採起相應動做時,你應該使用 if結構來定義條件。基本語法以下:

if CONDITION; then
    COMMANDS;
else
    OTHER-COMMANDS
fi

其中,CONDITION 能夠是以下情形的任意一項 (僅列出經常使用的),而且達到如下條件時返回
true:

  • [ -a file ]

    → 指定文件存在。

  • [ -d file ]

    → 指定文件存在,而且是一個目錄。

  • [ -f file ]

    → 指定文件存在,而且是一個普通文件。

  • [ -u file ]

    → 指定文件存在,並設置了 SUID 權限位。

  • [ -g file ]

    → 指定文件存在,並設置了 SGID 權限位。

  • [ -k file ]

    → 指定文件存在,並設置了「黏連 (Sticky)」位。

  • [ -r file ]

    → 指定文件存在,而且文件可讀。

  • [ -s file ]

    → 指定文件存在,而且文件不爲空。

  • [ -w file ]

    → 指定文件存在,而且文件可寫入。

  • [ -x file ]

    → 指定文件存在,而且可執行。

  • [ string1 = string2 ]

    → 字符串相同。

  • [ string1 != string2 ]

    → 字符串不相同。

[ int1 op int2 ] 爲前述列表中的一部分 (例如: -eq –> int1 與 int2 相同時返回true) ,其中比較項也能夠是一個列表子項, 其中 op 爲如下比較操做符。

  • -eq

    –> int1 等於 int2 時返回 true。

  • -ne

    –> int1 不等於 int2 時返回 true。

  • -lt

    –> int1 小於 int2 時返回 true。

  • -le

    –> int1 小於或等於 int2 時返回 true。

  • -gt

    –> int1 大於 int2 時返回 true。

  • -ge

    –> int1 大於或等於 int2 時返回 true。

for 循環語句

循環語句能夠在某個條件下重複執行某個命令。基本語法以下:

for item in SEQUENCE; do
        COMMANDS;
done

其中,item 爲每次執行 COMMANDS 時,在 SEQUENCE 中匹配到的值。

While 循環語句

該循環結構會一直執行重複的命令,直到控制命令(EVALUATION_COMMAND)執行的退出狀態值等於 0 時 (即執行成功) 中止。基本語法以下:

while EVALUATION_COMMAND; do
        EXECUTE_COMMANDS;
done

其中,EVALUATION_COMMAND 能夠是任何可以返回成功 (0) 或失敗 (0 之外的值) 的退出狀態值的命令,EXECUTE_COMMANDS 則能夠是任何的程序、腳本或者 shell 結構體,包括其餘的嵌套循環。

綜合使用

咱們會經過如下例子來演示 if 條件語句和 for 循環語句。
在基於 systemd 的發行版中探測某個服務是否在運行
先創建一個文件,列出咱們想要想要查看的服務名。

# cat myservices.txt
sshd
mariadb
httpd
crond
firewalld


使用腳本監控 Linux 服務
咱們編寫的腳本看起來應該是這樣的:

#!/bin/bash
# This script iterates over a list of services and
# is used to determine whether they are running or not.
for service in $(cat myservices.txt); do
        systemctl status $service | grep --quiet "running"
        if [ $? -eq 0 ]; then
                echo $service "is [ACTIVE]"
        else
                echo $service "is [INACTIVE or NOT INSTALLED]"
        fi
done


Linux 服務監控腳本
咱們來解釋一下這個腳本的工做流程
1). for 循環每次讀取 myservices.txt 文件中的一項記錄,每一項紀錄表示一個服務的通用變量名。各項記錄組成以下:

# cat myservices.txt

2). 以上命令由圓括號括着,並在前面添加美圓符,表示它須要從 myservices.txt 的記錄列表中取值並做爲變量傳遞給 for 循環。
3). 對於記錄列表中的每一項紀錄 (即每一項紀錄的服務變量),都會執行如下動做:

# systemctl status $service | grep --quiet "running"

此時,須要在每一個通用變量名 (即每一項紀錄的服務變量) 的前面添加美圓符,以代表它是做爲變量來傳遞的。其輸出則經過管道符傳給 grep。其中,-quiet 選項用於阻止 grep 命令將發現的 「running」 的行回顯到屏幕。當 grep捕獲到 「running」 時,則會返回一個退出狀態碼 「0」 (在 if 結構體表示爲 $?),由此確認某個服務正在運行中。
若是退出狀態碼是非零值 (即 systemctl status $service 命令中的回顯中沒有出現「running」),則代表某個服務未運行。

服務監控腳本
咱們能夠增長一步,在開始循環以前,先確認 myservices.txt 是否存在。

#!/bin/bash
# This script iterates over a list of services and
# is used to determine whether they are running or not.
if [ -f myservices.txt ]; then
        for service in $(cat myservices.txt); do
                systemctl status $service | grep --quiet "running"
                if [ $? -eq 0 ]; then
                        echo $service "is [ACTIVE]"
                else
                        echo $service "is [INACTIVE or NOT INSTALLED]"
                fi
        done
else
        echo "myservices.txt is missing"
fi

Ping 一系列網絡或者 Internet 主機名以獲取應答數據
你可能想把本身維護的主機寫入一個文本文件,並使用腳本探測它們是否可以 ping 得通 (腳本中的 myhosts 能夠隨意替換爲你想要的名稱)。
shell 的內置 read 命令將告訴 while 循環一行行的讀取 myhosts,並將讀取的每行內容傳給 host 變量,隨後 host 變量傳遞給 ping 命令。

#!/bin/bash
# This script is used to demonstrate the use of a while loop
while read host; do
        ping -c 2 $host
done < myhosts


使用腳本 Ping 服務器
擴展閱讀:

文件系統排錯

儘管 Linux 是一個很穩定的操做系統,但仍然會由於某些緣由出現崩潰時 (好比由於斷電等),正好你有一個 (或者更多個) 文件系統未能正確卸載,Linux 重啓的時候就會自動檢測其中可能發生的錯誤。
此外,每次系統正常啓動的時候,都會在文件系統掛載以前校驗它們的完整度。而這些所有都依賴於 fsck 工具 ( 文件系統校驗 ( file system check ) )。
若是對 fsck 進行設定,它除了校驗文件系統的完整性以外,還能夠嘗試修復錯誤。fsck 可否成功修復錯誤,取決於文件系統的損傷程度;若是能夠修復,被損壞部分的文件會恢復到位於每一個文件系統根目錄的 lost+found。
最後但一樣重要的是,咱們必須注意,若是拔掉系統正在寫入數據的 USB 設備一樣會發生錯誤,甚至可能發生硬件損壞。
fsck 的基本用以下:

# fsck [options] filesystem

檢查文件系統錯誤並嘗試自動修復
想要使用 fsck 檢查文件系統,咱們須要首先卸載文件系統。

# mount | grep sdg1
# umount /mnt
# fsck -y /dev/sdg1

檢查文件系統錯誤
除了 -y 選項,咱們也可使用 -a 選項來自動修復文件系統錯誤,而沒必要作出交互式應答,並在文件系統看起來 「乾淨」 卸載的狀況下強制校驗。

# fsck -af /dev/sdg1

若是隻是要找出什麼地方發生了錯誤 (不用在檢測到錯誤的時候修復),咱們可使用 -n 選項,這樣只會將文件系統錯誤輸出到標準輸出設備上。

# fsck -n /dev/sdg1

根據 fsck 輸出的錯誤信息,咱們能夠知道是否能夠本身修復或者須要將問題提交給工程師團隊來作詳細的硬件校驗。

總結

至此,系列教程的第十講就所有結束了,全系列教程涵蓋了經過 LFCS 測試所需的基礎內容。
但顯而易見的,本系列的十講並不足以在單個主題方面作到全面描述,咱們但願這一系列教程能夠成爲你學習的基礎素材,並一直保持學習的熱情(LCTT 譯註:還有後繼補充的幾篇)。

咱們歡迎你提出任何問題或者建議,因此你能夠堅決果斷的經過如下連接聯繫到咱們: 成爲一個 Linux 認證系統工程師 。

相關文章
相關標籤/搜索