防僞碼:長風破浪會有時,直挂雲帆濟滄海。
1.1 l Shell 簡介
Shell 是一個 C 語言編寫的腳本語言,它是使用者與 Linux 的橋梁,使用者輸入指令交給 Shell 處理,
Shell 将相應的操作傳遞給核心(Kernel),核心把處理的結果輸出給使用者。
下面是處理流程示意圖:

Shell 既然是工作在 Linux 核心之上,那我們也有必要知道下 Linux 相關知識。
Linux 是一套免費試用和自由傳播的類 Unix 作業系統,是一個基于 POSIX 和 UNIX 的多使用者、多任
務、支援多線程和多 CPU 的作業系統。
1983 年 9 月 27 日,Richard Stallman(理查德-馬修-斯托曼)發起 GNU 計劃,它的目标是建立一
套完全自由的作業系統。為保證 GNU 軟體可以自由的使用、複制、修改和釋出,所有的 GNU 軟體都
有一份在禁止其他人添加任何限制的情況下授權所有權利給任何人的協定條款,GNU 通用公共許可
證(GNU General Plubic License,GPL),說白了就是不能做商業用途。
GNU 是"GNU is Not Unix"的遞歸縮寫。UNIX 是一種廣泛使用的商業作業系統的名稱。
1985 年,Richard Stallman 又創立了自由軟體基金會(Free Software Foundation,FSF)來為
GNU 計劃提供技術、法律以及财政支援。
1990 年,GNU 計劃開發主要項目有 Emacs(文本編輯器)、GCC(GNU Compiler Collection,GNU 編
譯器集合)、Bash 等,GCC 是一套 GNU 開發的程式設計語言編譯器。還有開發一些 UNIX 系統的程式庫和
工具。
1991 年,Linuxs Torvalds(林納斯- 托瓦茲)開發出了與 UNIX 相容的 Linux 作業系統核心并在
GPL 條款下釋出。
1992 年,Linux 與其他 GUN 軟體結合,完全自由的 GUN/Linux 作業系統正式誕生,簡稱 Linux。
1995 年 1 月,Bob Young 創辦 ACC 公司,以 GNU/Linux 為核心,開發出了 RedHat Linux 商業版。
Linux 基本思想有兩點:第一,一切都是檔案;第二,每個軟體都有确定的用途。與 Unix 思想十分
相近。
l 1.2 Shell 基本分兩大類
1.2.1 圖形界面 Shell(GUI Shell)
GUI 為 Unix 或者類 Unix 作業系統構造一個功能完善、操作簡單以及界面友好的桌面環境。
主流桌面環境有 KDE,Gnome 等。
1.2.2 指令行界面 Shell(CLI Shell)
CLI 是在使用者提示符下鍵入可執行指令的界面,使用者通過鍵盤輸入指令,完成一系列操作。
在 Linux 系統上主流的 CLI 實作是 Bash,是許多 Linux 發行版預設的 Shell。還有許多 Unix
上用的 Shell,例如 tcsh、csh、ash、bsh、ksh 等等。
1.3 第一個 l Shell 腳本
本教程主要講解在大多 Linux 發行版下預設 Bash Shell。Linux 系統是 RedHat 下的 CentOS 操作系
統,完全免費。與其商業版 RHEL(Red Hat Enterprise Linux)出自同樣的源代碼,不同的是
CentOS 并不包含封閉源代碼軟體和售後支援。
用 vi 打開 test.sh,編寫:
# vi test.sh
#!/bin/bash
echo "Hello world!"
第一行設定運作環境,第二行列印 Hello world!
寫好後,開始執行,執行 Shell 腳本有三種方法:
方法 1:直接用 bash 解釋器執行
# bash test.sh
Hello world!
方法 2:添加可執行權限
# ll test.sh
-rw-r--r--. 1 root root 32 Aug 18 01:07 test.sh
# chmod +x test.sh
# ./test.sh
-bash: ./test.sh: Permission denied
# ./test.sh # ./在目前目錄
方法 3:source 指令執行,以目前預設 Shell 執行
# source test.sh
l 1.4 Shell 變量
1.4.1 系統變量
在指令行提示符直接執行 env、set 檢視系統或環境變量。env 顯示使用者環境變量,set 顯示 Shell
預先定義好的變量以及使用者變量。可以通過 export 導出成使用者變量。
一些寫 Shell 腳本時常用的系統變量:
$SHELL | 預設Shell |
$HOME | 目前使用者家目錄 |
$IFS | 内部字段分隔符 |
$LANG | 預設語言 |
$PATH | 預設可執行程式路徑 |
$PWD | 目前目錄 |
$UID | 目前使用者ID |
$USER | 目前使用者 |
$HISTSIZE | 曆史指令大小,可通過HISTTIMEFO 變量設定指令執行時間 |
$RANDOM | 随機生成一個 0 至 32767 的整數 |
$HOSTNAME | 主機名 |
1.4.2 普通變量與臨時環境變量
普通變量定義:VAR=value
臨時環境變量定義:export VAR=value
變量引用:$VAR
下面看下他們之間差別:
Shell 程序的環境變量作用域是 Shell 程序,當 export 導入到系統變量時,則作用域是 Shell 程序
及其 Shell 子程序。、
ps axjf 輸出的第一列是 PPID(父程序 ID),第二列是 PID(子程序 ID)
當 SSH 連接配接 Shell 時,目前終端 PPID(-bash)是 sshd 守護程式的 PID(root@pts/0),是以在當
前終端下的所有程序的 PPID 都是-bash 的 PID,比如執行指令、運作腳本。
是以當在-bash 下設定的變量,隻在-bash 程序下有效,而-bash 下的子程序 bash 是無效的,當
export 後才有效。
進一步說明:再重新連接配接 SSH,去除上面定義的變量測試下
是以在目前 shell 定義的變量一定要 export,否則在寫腳本時,會引用不到。
還需要注意的是退出終端後,所有使用者定義的變量都會清除。
在/etc/profile 下定義的變量就是這個原理,後面有章節會講解 Linux 常用變量檔案。
1.4.3 位置變量
位置變量指的是函數或腳本後跟的第 n 個參數。
$1-$n,需要注意的是從第 10 個開始要用花括号調用,例如${10}
shift 可對位置變量控制,例如:
echo "1: $1"
shift
echo "2: $2"
echo "3: $3"
# bash test.sh a b c
1: a
2: c
3:
每執行一次 shift 指令,位置變量個數就會減一,而變量值則提前一位。shift n,可設定向前移動
n 位。
1.4.4 特殊變量
$0 | 腳本自身名字 |
$? | 傳回上一條指令是 否執行成功,0 為 執行成功,非 0 則 為執行失敗 |
$# | 位置參數總數 |
$* | 所有的位置參數被 看做一個字元串 |
$@ | 每個位置參數被看 做獨立的字元串 |
$$ | 目前程序 PID |
$! | 上一條運作背景進 程的 PID |
1.5 變量引用
指派運算符 | 示例 |
= | 變量指派 |
+= | 兩個變量相加 |
# VAR=123
# echo $VAR
123
# VAR+=456
123456
Shell 中所有變量引用使用$符,後跟變量名。
有時個别特殊字元會影響正常引用,那麼需要使用${VAR},例如:
# echo $VAR_ # Shell 允許 VAR_為變量名,是以此引用認為這是一個有效的變量名,故此傳回
空
# echo ${VAR}
還有時候變量名與其他字元串緊礙着,也會誤認為是整個變量:
# echo $VAR456
# echo ${VAR}456
1.5.2 将指令結果作為變量值
# VAR=`echo 123`
# VAR=$(echo 123)
這裡的反撇号等效于$(),都是用于執行 Shell 指令。
1.6 雙引号和單引号
在變量指派時,如果值有空格,Shell 會把空格後面的字元串解釋為指令:
# VAR=1 2 3
-bash: 2: command not found
# VAR="1 2 3"
1 2 3
# VAR='1 2 3'
看不出什麼差別,再舉個說明:
# N=3
# VAR="1 2 $N"
# VAR='1 2 $N'
1 2 $N
單引号是告訴 Shell 忽略特殊字元,而雙引号則解釋特殊符号原有的意義,比如$、!。