跳至內容跳至頁面導覽:上一頁 [access key p]/下一頁 [access key n]
documentation.suse.com / SUSE Linux Enterprise Server 文件 / 管理指南 / 一般任務 / Bash 和 Bash 程序檔
適用範圍 SUSE Linux Enterprise Server 15 SP3

1 Bash 和 Bash 程序檔

當今時代,許多人都在使用裝有 GNOME 之類圖形使用者介面 (GUI) 的電腦。儘管 GUI 可提供許多功能,但執行自動化任務時,這些功能會受到限制。外圍程序是 GUI 的有效補充,本章概述了外圍程序 (以 Bash 外圍程序為例) 的一些方面。

1.1 什麼是外圍程序

一般而言,Linux 外圍程序就是 Bash (Bourne again Shell)。本章中提及的外圍程序指的是 Bash。可用的外圍程序不止 Bash (還有 ash、csh、ksh、zsh 等等),每個外圍程序都具有不同的功能和特性。如需有關其他外圍程序的詳細資訊,請在 YaST 中搜尋外圍程序

1.1.1 Bash 組態檔案

外圍程序可啟用為:

  1. 互動式登入外圍程序: 使用 --login 選項啟用 Bash 以登入機器,或使用 SSH 登入遠端機器時會採用這種方式。

  2. 一般互動式外圍程序: 啟動 xterm、konsole、gnome-terminal 或類似的指令行介面 (CLI) 工具時通常會呼叫此外圍程序。

  3. 非互動式外圍程序: 當在指令行呼叫外圍程序程序檔時,就會呼叫此外圍程序。

系統會讀取不同的組態檔案,視所使用的外圍程序類型而定。下面的表格顯示了登入與非登入外圍程序組態檔案。

表 1.1︰ 登入外圍程序的 Bash 組態檔案

檔案

描述

/etc/profile

請勿修改此檔案,否則當下次更新時,您的修改可能會被破壞!

/etc/profile.local

擴充 /etc/profile 時使用此檔案

/etc/profile.d/

包含特定程式的泛系統組態檔案

~/.profile

在此處插入登入外圍程序的使用者特定組態

請注意,登入外圍程序還會獲取表格 1.2 「非登入外圍程序的 Bash 組態檔案」中所列的組態檔案。

表 1.2︰ 非登入外圍程序的 Bash 組態檔案

/etc/bash.bashrc

請勿修改此檔案,否則當下次更新時,您的修改可能會被破壞!

/etc/bash.bashrc.local

使用此檔案只能插入 Bash 的泛系統修改

~/.bashrc

在此處插入使用者特定的組態

此外,Bash 還使用其他檔案:

表 1.3︰ 用於 Bash 的特殊檔案

檔案

描述

~/.bash_history

包含您輸入的所有指令清單

~/.bash_logout

登出時執行

~/.alias

使用者為常用指令定義的別名。如需定義別名的詳細資料,請參閱 man 1 alias

非登入外圍程序

下面兩個特殊外圍程序會阻擋使用者登入系統:/bin/false/sbin/nologin。當使用者嘗試登入系統時,這兩個外圍程序都將失敗且不會顯示訊息。這是一種針對系統使用者而特意設計的安全措施,雖然新版 Linux 作業系統已提供更有效的工具 (例如 PAM 和 AppArmor) 來控制系統存取。

SUSE Linux Enterprise Server 上的預設行為是將 /bin/bash 指定給人類使用者,將 /bin/false/sbin/nologin 指定給系統使用者。由於歷史原因,nobody 使用者擁有 /bin/bash,且曾是系統使用者預設的最低特權使用者。但是,如果有多個系統使用者使用 nobody,則將失去因使用 nobody 所獲得的任何安全性。應可將它變更為 /sbin/nologin;最快的測試方法是進行此變更,然後看看是否中斷了任何服務或應用程式。

使用以下指令列出 /etc/passwd 中已指定給所有使用者 (系統使用者和人類使用者) 的外圍程序。輸出視您系統上的服務和使用者而有所不同:

tux > sort -t: -k 7 /etc/passwd | awk -F: '{print $1"\t" $7}' | column -t
tux               /bin/bash
nobody            /bin/bash
root              /bin/bash
avahi             /bin/false
chrony            /bin/false
dhcpd             /bin/false
dnsmasq           /bin/false
ftpsecure         /bin/false
lightdm           /bin/false
mysql             /bin/false
postfix           /bin/false
rtkit             /bin/false
sshd              /bin/false
tftp              /bin/false
unbound           /bin/false
bin               /sbin/nologin
daemon            /sbin/nologin
ftp               /sbin/nologin
lp                /sbin/nologin
mail              /sbin/nologin
man               /sbin/nologin
nscd              /sbin/nologin
polkitd           /sbin/nologin
pulse             /sbin/nologin
qemu              /sbin/nologin
radvd             /sbin/nologin
rpc               /sbin/nologin
statd             /sbin/nologin
svn               /sbin/nologin
systemd-coredump  /sbin/nologin
systemd-network   /sbin/nologin
systemd-timesync  /sbin/nologin
usbmux            /sbin/nologin
vnc               /sbin/nologin
wwwrun            /sbin/nologin
messagebus        /usr/bin/false
scard             /usr/sbin/nologin

1.1.2 目錄結構

下表概述了 Linux 系統中最重要的較高層級目錄。下列清單中提供了關於目錄與重要子目錄的更多詳細資訊。

表 1.4︰ 標準目錄樹狀結構綜覽

目錄

內容

/

根目錄 — 目錄樹狀結構的起點。

/bin

基本的二進位檔案,例如系統管理員與一般使用者都需要使用的指令。通常還包含 Bash 等外圍程序。

/boot

開機載入程式的靜態檔案。

/dev

存取主機特定裝置所需的檔案。

/etc

主機特定系統的組態檔案。

/home

存放系統中所有擁有帳戶之使用者的主目錄。但是,root 的主目錄不在 /home 中,而是位於 /root 內。

/lib

基本的共用程式庫與核心模組。

/media

抽取式媒體的定點。

/mnt

用於暫時掛接檔案系統的定點。

/opt

附加應用程式軟體套件。

/root

超級使用者 root 的主目錄。

/sbin

基本的系統二進位檔案。

/srv

系統所提供之服務的資料。

/tmp

暫存檔案。

/usr

包含唯讀資料的次要階層。

/var

可變資料,例如記錄檔案。

/windows

僅當系統中同時安裝了 Microsoft Windows* 與 Linux 才可以使用。包含 Windows 資料。

以下清單提供了更多詳細資訊,以及目錄中包含的檔案與子目錄的一些範例:

/bin

包含 root 及其他使用者可能會使用的基本外圍程序指令。這些指令包括 lsmkdircpmvrm 以及 rmdir/bin 還包含 SUSE Linux Enterprise Server 中的預設外圍程序 Bash。

/boot

包含開機所需的資料,例如開機載入程式、核心及核心開始執行使用者模式程式之前所使用的其他資料。

/dev

存放代表硬體元件的裝置檔案。

/etc

包含控制 X Window System 等程式的操作的本地組態檔案。/etc/init.d 子目錄包含可在開機期間執行的 LSB init 程序檔。

/home/USERNAME

存放系統中每個擁有帳戶之使用者的個人資料。只有檔案擁有者或系統管理員才能修改位於此處的檔案。依預設,您的電子郵件目錄與個人桌面組態以隱藏檔案與目錄的形式存放於此,例如 .gconf/.config

注意
注意:網路環境中的主目錄

如果您是在網路環境中工作,您的主目錄可能會對應至檔案系統中 /home 以外的目錄。

/lib

包含啟動系統及執行根檔案系統中指令所需的基本共用程式庫。在 Windows 中,對應的共用程式庫為 DLL 檔案。

/media

包含 CD-ROM、隨身碟及數位相機 (若使用 USB) 等抽取式媒體的掛接點。/media 通常存放系統硬碟之外的任何類型磁碟機。抽取式媒體插入或連接到系統並進行掛接後,您就可以從此處存取該媒體。

/mnt

此目錄提供了暫時掛接之檔案系統的定點。root 可在此處掛接檔案系統。

/opt

為安裝協力廠商軟體而保留。這裡有選擇性軟體與大型附加程式套件。

/root

root 使用者的主目錄。此處存放 root 的個人資料。

/run

systemd 和各個元件使用的 tmpfs 目錄。/var/run/run 的符號連結。

/sbin

s 所指示,此目錄存放適用於超級使用者的公用程式。/sbin 不僅包含 /bin 中的二進位檔案,還包含啟動、還原及復原系統所必需的二進位檔案。

/srv

存放系統所提供之服務的資料,例如 FTP 與 HTTP。

/tmp

需要檔案暫時儲存區的程式會使用此目錄。

重要
重要:開機時清理 /tmp

無法保證在系統重新開機後,先前儲存於 /tmp 中的資料仍然存在。這視情況而定,例如,取決於 /etc/tmpfiles.d/tmp.conf 中的設定。

/usr

/usr 與使用者無關,是 UNIX 系統資源 (UNIX system resource) 的縮寫。/usr 中的資料是靜態的唯讀資料,可依照檔案系統階層標準 (Filesystem Hierarchy Standard,FHS) 在不同的主機之間共用。此目錄包含所有應用程式 (包括 GNOME 之類的圖形桌面),並且會在檔案系統中建立次要階層。/usr 存放了多個子目錄,例如 /usr/bin/usr/sbin/usr/local 以及 /usr/share/doc

/usr/bin

包含一般情況下可存取的程式。

/usr/sbin

包含為系統管理員保留的程式,例如修復功能。

/usr/local

在此目錄中,系統管理員可安裝獨立於套裝作業系統的本地延伸。

/usr/share/doc

存放系統的各種文件檔案與版本說明。在 manual 子目錄中,可找到此手冊的線上版本。如果安裝了多種語言,此目錄可能會包含不同語言的手冊版本。

packages 內,可找到系統上安裝之軟體套件所包含的文件。對於每個套件,都會建立一個子目錄 /usr/share/doc/packages/PACKAGENAME,通常用其儲存該套件的讀我檔案,有時儲存範例、組態檔案或其他程序檔。

如果系統中安裝了 HOWTO,/usr/share/doc 還會包含 howto 子目錄,其中有許多與 Linux 軟體設定及操作相關之任務的其他文件。

/var

/usr 存放的是靜態唯讀資料,而 /var 存放的是系統操作時寫入的資料,因此為可變資料,例如記錄檔案或多工緩衝處理資料。如需 /var/log/ 中包含之最重要記錄檔的綜覽,請參閱表格 40.1 「記錄檔」

1.2 撰寫外圍程序程序檔

使用外圍程序程序檔可以方便地完成各種任務:收集資料、搜尋文字中的單字或片語,以及執行其他有用的操作。以下範例顯示了一個列印文字的小型外圍程序程序檔:

範例 1.1︰ 用於列印文字的外圍程序程序檔
#!/bin/sh 1
# Output the following line: 2
echo "Hello World" 3

1

第一行以 Shebang 字元 (#! ) 開頭,指出此檔案為程序檔。在 Shebang 後面指定的解譯器將執行該程序檔。在本例中,指定的解譯器為 /bin/sh

2

第二行為備註,以 # 開頭。我們建議對難以理解的行提供註解。提供適當的註解可以記住該行的用途和功能。另外,可協助其他閱讀者理解您的程序檔。在開發社群中,註解被視為一種良好的做法。

3

第三行使用內建指令 echo 列印相應的文字。

在執行此程序檔之前,必須滿足幾項先決條件:

  1. 每個程序檔都應包含 Shebang 行 (如上面的範例所示)。如果缺少該行,您需要手動呼叫直譯器。

  2. 您可以將程序檔儲存於任何位置。但是,最好將其儲存於外圍程序可以找到的目錄中。外圍程序中的搜尋路徑由環境變數 PATH 決定。一般使用者通常沒有寫入 /usr/bin 的權限。因此,建議將程序檔儲存在使用者目錄 ~/bin/ 中。以上範例名為 hello.sh

  3. 程序檔需要執行權限。使用下列指令設定權限:

    tux > chmod +x ~/bin/hello.sh

如果滿足了上述所有先決條件,便可以按以下方式執行程序檔:

  1. 做為絕對路徑: 執行程序檔時可以使用絕對路徑。在此例中為 ~/bin/hello.sh

  2. 任何位置: 如果 PATH 環境變數包含程序檔所在的目錄,您可以使用 hello.sh 來執行程序檔。

1.3 重新導向指令事件

每條指令可以使用三個通道用於輸入或輸出:

  • 標準輸出: 這是預設的輸出通道。指令進行列印時會使用標準輸出通道。

  • 標準輸入: 如果指令需要使用者或其他指令的輸入,將會使用此通道。

  • 標準錯誤: 指令使用此通道報告錯誤。

要重新指向這些通道,可以使用以下幾種方式:

指令 > 檔案

將指令輸出儲存為檔案,現有的檔案將會刪除。例如,ls 指令將輸出寫入到檔案 listing.txt 中:

tux > ls > listing.txt
指令 >> 檔案

將指令輸出附加至檔案。例如,ls 指令將輸出附加至檔案 listing.txt 中:

tux > ls >> listing.txt
指令 < 檔案

讀取檔案,將其做為指定指令的輸入。例如,read 指令會將檔案內容讀取至變數中:

tux > read a < foo
指令1 | 指令2

將左邊指令的輸出重新指向為右邊指令的輸入。例如,cat 指令會輸出 /proc/cpuinfo 檔案的內容。再由 grep 使用此輸出內容單獨過濾出包含 cpu 的行:

tux > cat /proc/cpuinfo | grep cpu

每個通道都有一個檔案描述子:0 (零) 代表標準輸入,1 代表標準輸出,2 代表標準錯誤。您可以將此檔案描述子插入到 <> 字元的前面。例如,下行將搜尋以 foo 開始的檔案,但透過將檔案重新指向至 /dev/null 隱藏了錯誤:

tux > find / -name "foo*" 2>/dev/null

1.4 使用別名

別名為一或多條指令的簡短定義。別名的語法為:

alias NAME=DEFINITION

例如,下行定義了一個別名 lt,它會輸出一份較長的清單 (選項 -l),將其依修改時間排序 (-t),並依排好序的倒序列印 (-r):

tux > alias lt='ls -ltr'

要檢視所有的別名定義,請使用 alias。若要移除別名,請使用 unalias 和對應的別名名稱。

1.5 在 Bash 中使用變數

外圍程序變數可以是全域變數或本地變數。您可以在所有外圍程序中存取全域變數或環境變數。與此相反,本地變數僅顯示於目前的外圍程序中。

要檢視所有環境變數,請使用 printenv 指令。如需瞭解變數的值,則將變數名稱做為引數插入:

tux > printenv PATH

無論是全域變數還是本地變數,都可以使用 echo 進行檢視:

tux > echo $PATH

要設定本地變數,請使用變數名稱,後面跟上等號,再跟上值:

tux > PROJECT="SLED"

請不要在等號兩邊插入空格,否則將會出錯。要設定環境變數,請使用 export

tux > export NAME="tux"

若要移除變數,請使用 unset

tux > unset NAME

下表包含了部分可在外圍程序程序檔中使用的常用環境變數:

表 1.5︰ 有用的環境變數

HOME

目前使用者的主目錄

HOST

目前的主機名稱

LANG

工具當地化以後,會使用此環境變數指定的語言。也可將英語設定為 C

PATH

外圍程序的搜尋路徑,即以冒號分隔的目錄清單

PS1

指定在每條指令前列印的一般提示

PS2

指定執行多行指令時列印的輔助提示

PWD

目前的工作目錄

USER

目前的使用者

1.5.1 使用引數變數

例如,如果您有程序檔 foo.sh,可以按以下格式執行該程序檔:

tux > foo.sh "Tux Penguin" 2000

若要存取傳送至程序檔的所有引數,需要使用位置參數。$1 代表第一個引數的位置參數,$2 代表第二個引數的位置參數,依此類推。最多可以使用九個參數。要獲取程序檔名稱,請使用 $0

下面的程序檔 foo.sh 可列印從 1 到 4 的所有引數:

#!/bin/sh
echo \"$1\" \"$2\" \"$3\" \"$4\"

如果您使用以上引數執行此程序檔,所得結果為:

"Tux Penguin" "2000" "" ""

1.5.2 使用變數替代項

變數替代項會從左側或右側將模式套用至變數內容。以下清單包含了可用的語法格式:

${VAR#pattern}

從左側移除最短的相符項:

tux > file=/home/tux/book/book.tar.bz2
tux > echo ${file#*/}
home/tux/book/book.tar.bz2
${VAR##pattern}

從左側移除最長的相符項:

tux > file=/home/tux/book/book.tar.bz2
tux > echo ${file##*/}
book.tar.bz2
${VAR%pattern}

從右側移除最短的相符項:

tux > file=/home/tux/book/book.tar.bz2
tux > echo ${file%.*}
/home/tux/book/book.tar
${VAR%%pattern}

從右側移除最長的相符項:

tux > file=/home/tux/book/book.tar.bz2
tux > echo ${file%%.*}
/home/tux/book/book
${VAR/pattern_1/pattern_2}

PATTERN_2 取代 PATTERN_1VAR 的內容:

tux > file=/home/tux/book/book.tar.bz2
tux > echo ${file/tux/wilber}
/home/wilber/book/book.tar.bz2

1.6 分組和組合指令

外圍程序允許您組合及分組指令,以便按條件執行。每條指令都會傳回決定操作成功與否的離開碼。如果為 0 (零),則說明指令成功,任何其他離開碼都代表特定於指令的錯誤。

以下清單顯示了可對指令分組的方式:

指令1 ; 指令2

以順序執行指令。不檢查離開碼。下行透過 cat 顯示檔案內容,然後透過 ls 列印其檔案內容,而不管其離開碼為何:

tux > cat filelist.txt ; ls -l filelist.txt
指令1 && 指令2

如果左邊的指令成功,即會執行右邊的指令 (邏輯「與」)。下行顯示檔案內容,並且僅在前面的指令成功時才會列印其檔案內容 (將其與此清單中的上一個項目進行比較):

tux > cat filelist.txt && ls -l filelist.txt
指令1 || 指令2

如果左邊的指令失敗,即會執行右邊的指令 (邏輯「或」)。下行將只會在於 /home/tux/foo 中建立目錄失敗時,才會在 /home/wilber/bar 中建立目錄:

tux > mkdir /home/tux/foo || mkdir /home/wilber/bar
funcname(){ ... }

建立外圍程序函數。可以使用位置參數存取其引數。下行定義了可列印較短訊息的函數 hello

tux > hello() { echo "Hello $1"; }

可以按以下格式呼叫此函數:

tux > hello Tux

將會列印:

Hello Tux

1.7 使用通用流程建構元

為了控制程序檔的流程,外圍程序包含 whileifforcase 建構元。

1.7.1 if 控制指令

If 指令用於檢查運算式。例如,以下程式碼將測試目前的使用者是否為 Tux:

if test $USER = "tux"; then
  echo "Hello Tux."
else
  echo "You are not Tux."
fi

測試運算式可以很複雜,也可以很簡單。下面的運算式會檢查檔案 foo.txt 是否存在:

if test -e /tmp/foo.txt ; then
  echo "Found foo.txt"
fi

測試運算式也可以縮寫到方括弧中:

if [ -e /tmp/foo.txt ] ; then
  echo "Found foo.txt"
fi

如需更多有用的運算式,請參閱 https://bash.cyberciti.biz/guide/If..else..fi

1.7.2 使用 for 指令建立迴路

for 迴路可讓您對一組項目執行指令。例如,以下程式碼會列印目前目錄中關於 PNG 檔案的部分資訊:

for i in *.png; do
 ls -l $i
done

1.8 更多資訊

man 頁面 man bash 中提供了關於 Bash 的重要資訊。以下清單中提供了更多關於此主題的資訊: