Shell
所有 Linux 發行版預設的 shell 都是 bash shell
,在本文側重於基礎的 GNU bash shell 下面是其他幾種流行的 shell
-
ash: 簡單的輕量級 shell 完全相容 bash shell
-
korn: 相容 Bourne shell 的程式設計 shell
-
tcsh: 融入部分 C 語言特性
-
dash:
-
Debian Linux 發行版與其許多衍生產品 dash shell,它是 ash shell 的直系後裔,是 Unix 系統中 Bourne shell 的簡易複製品
-
在許多基於 Debian 的 Linux 發行版中,dash shell 實際上並不是預設 shell
-
由於 dash 以簡潔為目標,因此其使用的環境變數比 bash 明顯要少,但 dash 環境中無法使用的 bash 特性
- 算術運算
- test 命令不同
- 不支援 function 語句
-
-
zsh:
-
結合 bash, korn, tcsh 的特性的高階 shell
-
對比 bash 另一個流行的 shell,它汲取了所有現存 shell 的設計理念,增加了許多獨有的特性
-
是為程式設計師而設計的一款高階 shell
-
獨有特性
- 改進的 shell 選項處理
- shell 相容性模式
- 可載入模組
-
到目前為止,zsh shell 是所有 shell 中可定製性最強的
-
可以輕鬆地執行數學函式
-
進入命令列
在圖形化桌面出現之前,系統互動的唯一方式就是透過 shell 提供的 文字命令列介面 command line interface,CLI
-
控制檯終端
- 該模式只在顯示器上提供一個簡單的
shell CLI
,稱作 Linux 控制檯,因為它模擬的早期的硬接線控制檯終端 - Linux 系統啟動時會自動建立多個 虛擬控制檯,虛擬控制檯是執行在Linux系統記憶體中的終端會話,多數 Linux 發行版會啟動 5~6 個(甚至更多) 虛擬控制檯 代替 啞終端
- 在大多數 Linux 發行版中,可以使用簡單的按鍵組合來訪問某個 Linux 虛擬控制檯,通常必須按下
Ctrl+Alt
組合鍵再按一個功能鍵(F1~F7)來進入你要使用的虛擬控制檯
注意:在 Linux 虛擬控制檯中是無法執行任何圖形化程式的,儘管虛擬控制檯只是一個文字模式的控制檯終端,但你也可以修改文字和背景色
setterm --inversescreen on
作用是文字色和背景色交換,使用setterm --inversescreen off
可以關閉setterm -background
將終端的背景色改為指定顏色setterm -foreground
將終端的前景色改為指定顏色,引數: black, red, green, yellow, blue, magenta, cyan, white 共 8 種顏色setterm -reset
可以恢復預設設定
- 該模式只在顯示器上提供一個簡單的
-
圖形化終端
-
虛擬控制檯終端的另一種替代方案是使用 Linux 圖形化桌面環境中的 終端模擬軟體包,終端模擬軟體包會在桌面圖形化視窗中模擬控制檯終端
-
一些流行的圖形化終端模擬器軟體包
- Alacritty
- cool-retro-term
- GNOME Terminal
- Guake
- Konsole
- kitty
- rxvt-unicode
- Sakura
- st
- Terminator
- Terminology
- Termite
- Tilda
- xterm
- Xfce4-terminal
- Yakuake
-
常用的 GNOME Terminal, Konsole, xterm
-
啟動 shell
-
GNU bash shell 是一個程式,提供了對 Linux 系統的互動式訪問,系統啟動的 shell 程式取決於使用者賬戶的配置,在
/etc/passwd
檔案包含了所有系統使用者賬戶以及每個使用者的基本配置資訊 -
儘管 bash shell 會在登入時自行啟動,但是否會出現 CLI 取決於所使用的登入方式
- 採用的是虛擬控制檯終端登入,那麼 CLI 提示符會自動出現
- 透過圖形化桌面環境登入Linux系統,則需要啟動圖形化終端模擬器來訪問 shell CLI 提示符
- 預設的 bash shell 提示符是美元符號
$
,不同的 Linux 發行版會採用不同格式的提示符,shell 提示符並非一成不變 - 當你登入系統並獲得 shell CLI 提示符後,shell 會話會從你的主目錄開始
-
大多數 Linux 發行版自帶線上手冊,可用於查詢 shell 命令以及其他 GNU 實用工具的相關資訊,
man
命令可以訪問 Linux 系統的手冊頁。在
man
命令之後跟上想要檢視的命令名,就可以顯示相應的手冊頁man 命令名
-
當你使用 man 命令檢視命令手冊頁的時候,其中的資訊是由 分頁程式
pager
來顯示的 -
可以按 q 鍵 退出手冊頁
-
手冊頁將與命令相關的資訊分成了多段,每一段的慣用名標準,另外有些命令使用的段名並沒有在上面的慣用標準中列出
- Name: 命令名稱及簡要描述
- Synopsis: 命令語法
- Configuration: 命令配置資訊
- Description: 命令的基本描述
- Option: 命令選項描述
- Exit Status: 命令退出狀態
- Return Value: 返回值
- Errors: 錯誤資訊
- Environment: 環境變數
- Files: 使用的檔案
- Versions: 版本資訊
- Conforming To: 遵循的命名標準
- Notes: 其他幫助資料
- Bugs: 提交 Bug 的途徑
- Example: 命令用法示例
- Authors: 開發人員資訊
- Copyright: 原始碼版權資訊
- See Also: 類似命令
-
man 命令可以使用 關鍵字 來搜尋手冊頁
man -k keyword
-
手冊頁中還有不同的節,每節都分配了一個數字,從 1~9 章節
# 閱讀方法 man num intro # num 是每節的數字
- 1: 可執行程式或 shell 命令
- 2: 系統呼叫
- 3: 庫呼叫
- 4: 特殊檔案
- 5: 檔案格式約定
- 6: 遊戲
- 7: 概念,約定,雜項
- 8: 超級使用者和系統管理員相關命令
- 9: 核心執行緒 routine
Linux 系統手冊頁可能包含一些非標準的節編號
-
大多數命令接受 -h 或 --help 選項
-
-
瞭解如何在命令列中輸入該命令
COMMAND-NAME [OPTION]... [ARGUMENT]...
- COMMAND-NAME 命令名稱
- OPTION 修改命令列為的選項
- ARGUMENT 是傳遞給命令的引數
- [] 代表命令的必要性,有意味可選非必要
- ... 表示可以一次或指定多
常用命令
- cd: 目錄切換,允許絕對路徑或相對路徑
- pwd: 命令可以顯示出 shell 會話的當前目錄
- ls: 顯示當前目錄下的檔案和目錄,允許使用萬用字元
- touch: 建立好指定的檔案並將你的使用者名稱作為該檔案的屬主
- mkdir: 建立好指定的目錄並將你的使用者名稱作為該檔案的屬主
- ln: 建立連結檔案
- cp: 複製檔案,複製目錄需要 -R 選項,格式 cp src dest,其中 src 允許使用萬用字元
- mv: 移動目錄或檔案,可以起到重新命名作用,該操作不改變檔案的 inode 編號或時間戳
- rm: 刪除檔案或目錄
檢視檔案內容
- file: 能夠探測檔案的內部並判斷檔案型別
- cat: 顯示文字檔案中所有資料
- more: 分頁檢視
- less: more 升級版,能夠實現在文字檔案中前後翻動,還有一些高階搜尋功能,還可以在完成整個檔案的讀取之前顯示檔案的內容
- tail: 顯示檔案最後幾行的內容,預設 10 行
- head: 顯示檔案開頭幾行的內容,預設 10 行
系統管理命令
-
ps: 監測程式,預設只顯示執行在當前終端中屬於當前使用者的那些程式
- PID: 程式的 程式 ID
process ID,PID
- TTY: 從屬終端
- TIME: 其佔用的 CPU 時間
- CMD: 程式名稱
Linux 系統中使用的 GNU ps 命令支援以下3種型別的命令列選項:
-
Unix 風格選項,選項前加單連字元
需要檢視系統中執行的所有程式,可以使用
-ef
選項組合-
-e
選項指定顯示系統中執行的所有程式 -
-f
選項則擴充輸出內容以顯示一些有用的資訊列- UID: 啟動該程式的使用者
- PID: 程式 ID
- PPID: 父程式的 PID(如果該程式是由另一個程式啟動的)
- C: 程式生命期中的 CPU 利用率
- STIME: 程式啟動時的系統時間
- TTY: 程式是從哪個終端裝置啟動的
- TIME: 執行程式的累計 CPU 時間
- CMD: 啟動的程式名稱
-
-l
選項之後多出的資訊列-
F: 核心分配給程式的系統標誌
-
S: 程式的狀態
- O 代表正在執行
- S 代表在休眠
- R 代表可執行,正等待執行
- Z 代表僵化,已終止但找不到其父程式
- T 代表停止
-
PRI: 程式的優先順序(數字越大,優先順序越低)
-
NI: 謙讓度,用於決定優先順序
-
ADDR: 程式的記憶體地址
-
SZ: 程式被換出時所需交換空間的大致大小
-
WCHAN: 程式休眠的核心函式地址
-
-
-
BSD 風格選項,選項前不加連字元
在使用 BSD 風格的選項時,ps命令會自動改變輸出以模仿 BSD 格式,上述很多輸出列跟使用 Unix 風格選項時是一樣的,但還是有一些不同之處
-
VSZ: 程式佔用的虛擬記憶體大小(以 KB 為單位)
-
RSS: 程式在未被交換出時佔用的實體記憶體大小
-
STAT: 代表當前程式狀態的多字元狀態碼
程式狀態碼:第一個字元采用了與Unix風格的 S 輸出列 相同的值表明程式是在休眠、執行還是等待,第二個字元進一步說明了程式的狀態
- <: 該程式以高優先順序執行
- N: 該程式以低優先順序執行
- L: 該程式有鎖定在記憶體中的頁面
- s: 該程式是控制程式
- l: 該程式擁有多執行緒
- +: 該程式在前臺執行
-
-
GNU 長選項,選項前加雙連字元
GNU 開發人員在經過改進的新ps命令中加入了另外一些選項,其中一些 GNU 長選項複製了現有的 Unix 或 BSD 風格選項的效果,而另外一些則提供了新功能
--forest
選項能夠使用 ASCII 字元來繪製圖表以顯示程式的層級資訊
- PID: 程式的 程式 ID
-
top: 可以實時顯示程式資訊
在top命令執行時鍵入可改變top的行為
- 鍵入
f
允許你選擇用於對輸出進行排序的欄位 - 鍵入
d
允許你修改 輪詢間隔polling interval
- 鍵入
q
可以退出 top
利用該工具,可以輕易找出佔用系統大量資源的罪魁禍首
- 鍵入
-
kill: 會向命令列中列出的所有 PID 傳送 TERM 訊號,TERM 訊號會告訴程式終止執行
- 只能使用程式的 PID 而不能使用其對應的程式名
- 要傳送程式訊號,必須是程式的屬主或 root 使用者
-s
選項支援指定其他訊號
要檢查 kill 命令是否生效,可以再次執行 ps 命令或 top 命令,看看那些程式是否已經停止執行
-
pkill: 可以使用程式名代替 PID 來終止程式,允許使用萬用字元
注意:以 root 身份使用命令中的萬用字元很容易意外地將系統的重要程式終止,這可能會導致檔案系統損壞
-
mount: 用於掛載儲存裝置,預設情況下會輸出當前系統已掛載的裝置列表
命令提供了4部分資訊:
- 裝置檔名
- 裝置在虛擬目錄中的掛載點
- 檔案系統型別
- 已掛載裝置的訪問狀態
手動掛載裝置的基本命令:
mount -t type device directory
-
type: 磁碟格式化所使用的檔案系統型別
與
Windows PC
共用移動儲存裝置,通常需要使用下列檔案系統型別- vfat: Windows FAT32檔案系統,支援長檔名
- ntfs: Windows NT及後續作業系統中廣泛使用的高階檔案系統
- exfat: 專門為可移動儲存裝置最佳化的Windows檔案系統
- iso9660: 標準CD-ROM和DVD檔案系統
大多數 U 盤會使用 vfat 檔案系統 格式化,如果需要掛載資料 CD 或 DVD,則必須使用 iso9660 檔案系統 型別
-
device: 該儲存裝置的裝置檔案位置
-
directory: 掛載點在虛擬目錄中的位置
注意:儲存裝置被掛載到虛擬目錄,root 使用者就擁有了對該裝置的所有訪問許可權,而其他使用者的訪問則會被限制
-
umount: 移除可移動裝置時,不能直接將裝置拔下,應該先解除安裝
命令的格式:
umount [device | directory]
支援透過 裝置檔案 或者 掛載點 來指定要解除安裝的裝置,如果有任何程式正在使用裝置上的檔案,則系統將不允許解除安裝該裝置
-
df: 檢視所有已掛載磁碟的使用情況
-
du: 可以顯示某個特定目錄(預設情況下是當前目錄)的磁碟使用情況
處理資料命令
-
sort: 對資料進行排序
-t
選項指定欄位分隔符-k
選項指定排序欄位-n
選項將數字按值排序-M
選項將數字按月排序
-
grep: 會在輸入或指定檔案中逐行搜尋匹配指定模式的文字
-
gzip: 用於壓縮檔案
-
gzcat: 用於檢視壓縮過的文字檔案的內容
-
gunzip: 用於解壓檔案
Linux 基礎管理命令
使用者管理
-
useradd: 向 Linux 系統新增新使用者
- 預設值使用 /etc/default/useradd 檔案設定
- 安全設定在 /etc/login.defs 檔案中定義
- 使用者賬戶管理命令需要以 root 使用者賬戶登入或者透過
sudo
命令執行
-
userdel: 從系統中刪除使用者
- 預設情況下,userdel 命令只刪除 /etc/passwd 和 /etc/shadow 檔案中的使用者資訊,屬於該賬戶的檔案會被保留
-r
選項,則userdel會刪除使用者的 $HOME 目錄以及郵件目錄,然而系統中仍可能存有已刪除使用者的其他檔案
-
修改使用者
-
usermod: 提供了修改 /etc/passwd 檔案中大部分欄位的相關選項只需指定相應的選項即可,大部分選項與useradd命令的選項一樣
- -l: 修改使用者賬戶的登入名
- -p: 修改賬戶密碼
- -U: 解除鎖定,恢復使用者登入
- -L: 可以鎖定賬戶,使使用者無法登入,無須刪除賬戶和使用者資料
- -G: 提供向組中新增使用者不會影響主要組,更改了已登入系統的使用者所屬的組,則該使用者必須登出後重新登入,這樣新的組關係才能生效
- -g: 則指定的組名會替換掉在 /etc/passwd 檔案中為該使用者分配的主要組
-
passwd: 可以方便地修改使用者密碼,只有 root 使用者才有許可權修改別人的密碼
-
chpasswd: 能從標準輸入自動讀取一系列以冒號分隔的登入名和密碼對偶
-
chfn: 提供了在 /etc/passwd 檔案的備註欄位中儲存資訊的標準方法,會將用於 Unix 的 finger 命令的資訊存入備註欄位
-
finger: 可以非常方便地檢視 Linux 系統的使用者資訊,安裝該命令可能會使你的系統受到攻擊漏洞的影響
-
chage: 命令可用於幫助管理使用者賬戶的有效期
-
-
groupadd: 可用於建立新組
-
groupdel: 刪除組
-
groupmod: 可以修改已有組
-
檔案許可權:
-
檔案許可權符號
- r 代表物件是可讀的
- w 代表物件是可寫的
- x 代表物件是可執行的如果沒有某種許可權,則在該許可權位會出現連字元
-
組許可權分別對應物件安全級別
- 物件的屬主
- 物件的屬組
- 系統其他使用者
-
umask: 用來設定新建檔案和目錄的預設許可權
-
chmod: 可以修改檔案和目錄的安全設定,引數允許使用八進位制模式或符號模式來進行安全設定
-
chown: 前者可以修改檔案的屬主,可以修改檔案的所有符號連結檔案的所屬關係
命令的格式
chown options owner[.group] file
-
chgrp: 後者可以修改檔案的預設屬組
-
-
訪問控制列表 ACL
-
getfacl: 能夠檢視分配給檔案或目錄的 ACL
-
setfacl: 能夠設定分配給檔案或目錄的 ACL
-m
選項修改分配給檔案或目錄的許可權-x
選項刪除特定許可權
3 種格式定義規則
u[ser]:uid:perms g[roup]:gid:perms o[ther]::perms
- 要為使用者分配許可權,可以使用 user 格式
- 要為組分配許可權,可以使用 group 格式
- 要為其他使用者分配許可權,可以使用 other 格式
-
管理檔案系統
-
fdisk: 可以在任何儲存裝置上建立和管理分割槽,但是隻能處理最大 2TB 的硬碟
- 如果儲存裝置是首次分割槽,則會警告你該裝置沒有分割槽表
- 是一個互動式程式,允許你輸入命令來逐步完成硬碟分割槽操作
- 需要指定待分割槽的儲存裝置的名稱,同時還必須有超級使用者許可權
- 不允許調整現有分割槽的大小,你能做的是刪除現有分割槽後重新建立
-
gdisk: 如果儲存裝置要採用 GUID 分割槽表
GUID partition table,GPT
,就要用到- 會識別儲存裝置所採用的分割槽型別
- 在轉換儲存裝置分割槽型別的時候務必小心,所選擇的型別必須與系統韌體相容
- 提供了自己的命令列提示符,允許輸入命令進行分割槽操作
-
GNU parted: 操作命令偏向詞
- 允許調整現有的分割槽大小,所以可以很容易地收縮或擴大磁碟分割槽
將資料儲存到分割槽之前,必須使用某種檔案系統對其進行格式化,並非所有的檔案系統工具都已經預設安裝過,要想知道某個工具是否可用,可以使用 type 命令
- mkefs: ext
- mke2fs: ext2
- mkfs.ext3: ext3
- mkfs.ext4: ext4
- mkreiserfs: ReiserFS
- jfs_mkfs: JFS
- mkfs.xfs: XFS
- mkfs.zfs: ZFS
- mkfs.btrfs: Btrfs
為分割槽建立好檔案系統之後,下一步是將其掛載到虛擬目錄中的某個掛載點,以便在新分割槽中儲存資料
- mount 命令會將新分割槽的檔案系統新增到掛載點
- 掛載檔案系統的方法只能實現臨時掛載,重啟系統後就失效了,要強制 Linux 在啟動時自動掛載檔案系統可以將其新增到
/etc/fstab
檔案中
檔案系統的檢查與修復,每種檔案系統各自都有相應的恢復命令
-
fsck: 可以檢查和修復大部分Linux檔案系統型別
- 日誌檔案系統的使用者確實也要用到 fsck 命令,但對於 COW 檔案系統需要高階修復選項
- 只能對未掛載的檔案系統執行 fsck 命令,對大多數檔案系統只需先解除安裝檔案系統,檢查完成之後再重新掛載即可
LVM 管理
-
物理卷 PV
- pvscan: 掃描 PV
- pvcreate: 指定了一個未使用的磁碟分割槽(或整個驅動器)由 LVM 使用,在這個過程中 LVM 結構、卷標和後設資料都會被新增到該分割槽
- pvdisplay: 顯示 PV 資訊
- pvremove: 刪除 PV
-
卷組 VG
-
vgscan: 掃描 VG
-
vgcreate: 會將 物理卷
PV
加入儲存池,後者隨後用於構建各種邏輯卷- 可以存在多個卷組
- 將一個或多個 PV 加入 卷組
VG
時,也會同時新增捲組的後設資料 - 被指定為 PV 的分割槽只能屬於單個 VG,但被指定為 PV 的其他分割槽可以屬於其他 VG
-
vgdisplay: 顯示 VG 資訊
-
vgremove: 刪除 VG
-
vgextend: 擴充 VG
-
vgreduce: 縮小 VG
-
-
邏輯卷 LV
-
lvscan: 掃描 LV
-
lvcreate: 邏輯卷
LV
由 VG 的 儲存空間塊PE
組成- 可以使用檔案系統格式化 LV,然後將其掛載,像普通的磁碟分割槽那樣使用
- 可以有多個 VG,但 LV 只能從一個指定的 VG 中建立
- 多個 LV 可以共享單個 VG
-
lvdisplay: 顯示 LV 資訊,也可以使用 lvs 命令和 lvscan 命令顯示系統的 LV 資訊
-
lvremove: 刪除 LV
-
lvextend: 擴充 LV
-
lvreduce: 縮小 LV
-
要想了解所有的 LVM 命令,可以在命令列中輸入 lvm help
軟體包管理系統
-
基於 Debian 的系統
-
dpkg: 是基於 Debian 的軟體包管理器的核心,用於在Linux系統中安裝、更新、刪除 DEB 包檔案
-
APT 工具集
- apt-cache
- apt-get
- apt: 命令本質上是 apt-cache 命令和 apt-get 命令的前端
apt 倉庫: 倉庫位置儲存在檔案 /etc/apt/sources.list 中
-
-
基於 Red Hat 的系統
- rpm: 是基於 Debian 的軟體包管理器的核心
- yum: 用於 Red Hat, CentOS, Fedora
- zypper: 用於 openSUSE
- dnf: yum 的升級版,有一些新增的特性
dnf 倉庫:
- 配置檔案 /etc/dnf/dnf.conf
- /etc/yum.repos.d 目錄中的單獨檔案
使用容器管理軟體
-
snap: 管理 snap 格式的應用程式容器
- 在安裝 snap 的時候,snapd 程式會將其作為驅動器掛載
-
flatpak: 管理 flatpak 格式應用程式容器
理解 shell
-
shell 型別
- 預設的互動式 shell
default interactive shell
也稱 登入 shelllogin shell
,只要使用者登入某個虛擬控制檯終端或是在 GUI 中啟動終端模擬器,該 shell 就會啟動 - 預設的系統 shell
default system shell
,/bin/sh
用於那些需要在啟動時使用的系統shell指令碼
- 預設的互動式 shell
-
$0
當前 shell 的名稱 -
exit 可以退出 shell
子 shell
-
使用者登入某個 虛擬控制檯終端 或在 GUI 中執行 終端模擬器 時所啟動的預設的互動式 shell 之後,當 CLI 提示符處輸入 bash 命令(或是其他 shell 程式名)時會建立新的 shell 程式,這是一個 子 shell
-
生成子程式時,只有部分父程式的環境被複制到了子環境中
-
bash 常用選項
-c string
: 從 string 中讀取命令進行處理-i
: 啟動一個互動性 shell-l
: 做為 login shell-r
: 啟動一個受限 shell-s
: 從標準輸入讀取命令
-
-
命令分組
- 使用
()
圓括號程式列表,生成了一個子 shell 來執行這些命令 - 使用
{}
花括號進行命令分組並不會像程式列表那樣建立子 shell
- 使用
-
$BASH_SUBSHELL
變數判斷是否存在子 shell- 返回 0,那麼表明沒有子 shell
- 返回大於 0 的數字,則表明存在子 shell
-
子 shell 在 shell 指令碼中經常用於 多程式處理
-
在 互動式 shell 中,一種高效的子 shell 用法是 後臺模式
- 想將命令置入後臺模式,可以在命令末尾加上字元
&
- 當其被置入後臺時,在 shell CLI 提示符返回之前,螢幕上會出現 後臺作業號 和 程式 ID
jobs
命令能夠顯示當前執行在後臺模式中屬於你的所有程式
- 想將命令置入後臺模式,可以在命令末尾加上字元
-
coproc: 建立協程同時做兩件事:
- 在後臺生成一個子 shell
- 在該子 shell 中執行命令
- 除了會建立子 shell,協程基本上就是將命令置入後臺
-
外部命令(有時也稱為檔案系統命令)是存在於bash shell之外的程式
- 它並不屬於shell程式的一部分
- 外部命令程式通常位於 /bin, /usr/bin, /sbin, /usr/sbin 目錄中
- 每當執行外部命令時,就會建立一個子程式,這種操作稱為 衍生
forking
-
內建命令無須使用子程式來執行
- 已經和 shell 編譯成一體,作為 shell 的組成部分存在,無須藉助外部程式檔案來執行
type
命令來判斷某個命令是否為內建
-
history: 跟蹤你最近使用過的命令,是一個實用的內建命令,使用
!!
執行上一條命令 -
alias: 別名允許為常用命令及其引數建立另一個名稱,從而將輸入量減少到最低,另一個實用的shell內建命令
- 選項
-p
可以檢視當前可用的別名
- 選項
-
unalias: 刪除別名
環境變數
環境變數可以儲存 shell 會話和工作環境的相關資訊,允許在記憶體中儲存資料以便 shell 中執行的程式或指令碼能夠輕鬆訪問到這些資料
-
全域性變數:全域性環境變數對於 shell 會話和所有生成的子 shell 都是可見的
- 可以使用
env
命令來檢視全域性變數,使用printenv
命令顯示個別環境變數的值
- 可以使用
-
區域性變數:只對建立它的 shell 可見
set
命令可以顯示特定程式的所有環境變數,既包括區域性變數、全域性變數
-
引用某個環境變數時,必須在該變數名前加上美元符號
$
可以在 bash shell 中直接設定自己的變數
- 可以使用等號為變數賦值實現 區域性環境變數,值可以是數值或字串
- 在變數名、等號和值之間沒有空格,這一點非常重要
export
命令以及要匯出的變數名(不加$
符號)來實現 全域性環境變數- 修改子 shell 中的全域性環境變數並不會影響父 shell 中該變數的值
unset
命令能刪除已有的環境變數- 在子程式中刪除了一個全域性環境變數,那麼該操作 僅對子程式有效,該全域性環境變數在父程式中依然可用
- 任何由父 shell 設定但 未匯出的變數都是區域性變數,不會被子 shell 繼承
環境變數的另一個特性是可以作為陣列使用
- 環境變數的另一個特性是可以作為陣列使用
- 要為某個環境變數設定多個值,可以把值放在 圓括號 中,值與值之間以 空格分隔
- 要引用單個陣列元素,必須使用表示其在陣列中位置的 索引,索引要寫在 方括號 中,且 $ 符號 之後的所有內容都要放入 花括號 中
unset
命令可以刪除陣列中的某個值,後跟上陣列名來刪除整個陣列- 陣列並不太方便移植到其他 shell 環境,有時候陣列變數只會把事情搞得更復雜
預設的 shell 環境變數
- CDPATH: 以冒號分隔的目錄列表,做為 cd 命令的搜尋路徑
- HOME: 當前使用者主目錄
- IFS: shell 用來將文字字串分割為字元
- MAIL: 當前使用者收件箱的檔名
- MAILPATH: 當前使用者收件箱的檔名列表
- OPTARG: getop 命令處理的最後一個選項引數
- OPTIND: getop 命令處理的最後一個選項引數的索引
- PATH: shell 查詢命令的目錄列表,只需引用原來的 PATH 值新增冒號,然後再使用絕對路徑輸入新目錄,對於 PATH 變數的修改只能持續到退出或重啟系統
- PS1: shell 命令列主提示符
- PS2: shell 命令列次提示符
- HISTFILESIZE: 歷史記錄列表上限,位於記憶體中
- HISTSIZE: 歷史記錄檔案上限,位於硬碟上
當你登入 Linux 系統啟動 bash shell 時,預設情況下 bash 會在幾個檔案中查詢命令。這些檔案稱作 啟動檔案 或 環境檔案
-
登入 shell 通常會從 5 個不同的啟動檔案中讀取命令
-
/etc/profile
- 是系統中預設的 bash shell 的主啟動檔案,系統中的 每個使用者 登入時都會執行這個啟動檔案
- 每種發行版的 /etc/profile 檔案都有不同的設定和命令
-
$HOME/.bash_profile
- 先檢查 $HOME 目錄中是不是還有一個名為 .bashrc 的啟動檔案,有就先執行該檔案中的命令
-
$HOME/.bashrc
- 檢查 /etc 目錄下的通用 bashrc 檔案
- 為使用者提供一個定製自己的命令別名
-
$HOME/.bash_login
-
$HOME/.profile
$HOME
目錄下的啟動檔案:提供使用者專屬的啟動檔案來定義該使用者所用到的環境變數,Linux 發行版在環境檔案方面存在的差異非常大,有些使用者可能只有一個 $HOME/.bash_profile 檔案,順序 $HOME/.bash_profile -> $HOME/.bash_login -> $HOME/.profile 在 $HOME/.bashrc 檔案通常透過其他檔案執行-
作為互動式 shell 啟動的 bash 並不處理 /etc/profile 檔案,只檢查使用者 $HOME 目錄中的 .bashrc 檔案
-
非互動式 shell,系統執行shell指令碼時用的就是這種 shell
- bash shell 提供了
BASH_ENV
環境變數:當shell啟動一個 非互動式 shell 程式時,會檢查這個環境變數以檢視要執行的啟動檔名,如果有指定的檔案則 shell 會執行該檔案裡的命令,這通常包括 shell 指令碼變數設定
- bash shell 提供了
-
-
有些 Linux 發行版使用了 可拆卸式認證模組
pluggable authentication module,PAM
,這種情況下 PAM 檔案會在 bash shell 啟動之前被處理,前者中可能會包含環境變數/etc/environment
$HOME/.pam_environment
環境變數持久化
- 對全域性環境變數可能更傾向於將新的或修改過的變數設定放在 /etc/profile 檔案中,但升級了所用的發行版則該檔案也會隨之更新,好在
/etc/profile.d
目錄中建立一個以 .sh 結尾的檔案 - 對儲存個人使用者永久性 bash shell 變數的最佳地點是
$HOME/.bashrc
檔案,但如果設定了 BASH_ENV 變數除非值為$HOME/.bashrc
,否則應該將 非互動式 shell 的使用者變數放在別的地方
構建 shell 指令碼
基本使用
-
使用多個命令,彼此用 分號 隔開
-
建立 shell 指令碼檔案
-
建立 shell 指令碼檔案時,必須在檔案的第一行指定要使用的 shell
#!/bin/bash
- 第一行有時被稱為 shebang
基本是
#!
加 shell 絕對路徑 -
註釋使用
#
-
使用分號將兩個命令放在一行中,但在shell指令碼中,可以將命令放在獨立的行中
-
-
使用 shell 指令碼:需要 可執行許可權 和 下面查詢命令規則之一
- 將放置 shell 指令碼檔案的目錄新增到 PATH 環境變數中
- 在命令列中使用絕對路徑或相對路徑來引用 shell 指令碼檔案
-
echo: 輸出會顯示在指令碼所執行的控制檯顯示器,可用單引號或雙引號來劃定字串
-
變數使用
- 在指令碼中,可以在環境變數名之前加上
$
來引用這些環境變數 - 反斜線允許 shell 指令碼按照字面意義解釋 $
- 透過
${variable}
形式引用的變數,花括號 通常用於幫助界定 $ 後的變數名 - 變數賦值在變數、等號和值之間不能出現空格
- 引用變數值時要加 $,對變數賦值時則不用加 $
- 在指令碼中,可以在環境變數名之前加上
-
命令替換
-
可以從命令輸出中提取資訊並將其賦給變數
-
兩種方法可以將命令輸出賦給變數
- 反引號
$()
-
命令替換允許將 shell 命令的輸出賦給變數
-
命令替換會建立出子 shell 來執行指定命令,這是由執行指令碼的 shell 所生成的一個獨立的 shell,在子 shell 中執行的命令無法使用指令碼中的變數
-
-
輸出重定向
>
- 最基本的重定向會將命令的輸出傳送至檔案
- 如果輸出檔案已存在,則重定向運算子會用新資料覆蓋已有的檔案
- 不想覆蓋檔案原有內容,使用
>>
-
輸入重定向
<
- 輸入重定向會將檔案的內容重定向至命令
- 還有另外一種輸入重定向的方法稱為 內聯輸入重定向
<<
,這種方法無須使用檔案進行重定向,只需在命令列中指定用於輸入重定向的資料即可 - 除了
<<
符號,必須指定一個 文字標記 來劃分輸入資料的起止
-
管道
|
- 將一個命令的輸出作為另一個命令的輸入
- 管道可以串聯的命令數量沒有限制
-
執行數學運算
-
expr: 最初,Bourne shell 提供了一個專門用於處理數學表示式的命令
- 可在命令列中執行數學運算,但是特別笨拙
- 能夠識別少量算術運算子和字串運算子
- 標準運算子在 expr 命令中工作得很好,但在指令碼或命令列中使用時仍有問題出現
- 那些容易被 shell 錯誤解釋的字元被傳入 expr 命令之前,需要使用 跳脫字元 對其進行轉義
- 為了相容 Bourne shell,bash shell 保留了 expr 命令
-
使用方括號
- 在 bash 中,要將數學運算結果賦給變數,可以使用
$
和 方括號 - 在使用方括號執行數學運算時,無須擔心 shell 會誤解乘號或其他符號
- bash shell 的數學運算子只支援整數運算,但 zsh 提供了完整的浮點數操作
- 在 bash 中,要將數學運算結果賦給變數,可以使用
-
使用內建的 bash 計算器 bc
- 其中內建變數 scale 控制冗長
- 在指令碼中需要結合管道使用,允許你設定變數,如果需要多個變數可以用分號來分隔它們
- 表示式中不僅可以使用數字,還可以用shell指令碼中定義好的變數
- 這種方法適用於較短的運算,如果要進行大量運算,最好的辦法是使用內聯輸入重定向
-
-
變數
$?
來儲存最後一個已執行命令的退出狀態碼- 對於成功結束的命令,其退出狀態碼是 0
- 對於因錯誤而結束的命令,其退出狀態碼是一個正整數
- 退出狀態碼被縮減到了 0~255 的區間
結構化命令
-
if-then-elif-then-else
if command1 then commands elif command2 then commands else commands fi
-
if 或 elif 根據命令的退出狀態碼判斷 then 中的命令是否執行
- 退出狀態碼為 0 時執行 then 部分的命令
- 退出狀態碼為非 0 退出狀態碼時,執行 else 中程式碼
-
then 與 if, elif 是配套
-
fi 為閉合開始的 if
-
elif 和 else 為可選
-
-
test: 測試命令,目的是更好的進行條件判斷
- 如果 test 命令中列出的條件成立,那麼 test 命令就會退出並返回退出狀態碼 0
- 如果條件不成立,那麼 test 命令就會退出並返回非 0 的退出狀態碼
test condition
- condition 要測試的一系列引數和值
- condition 部分沒有會以非 0 的退出狀態碼
bash shell 提供了另一種條件測試方式,可以使用 中括號 替代 test,第一個方括號之後和第二個方括號之前 必須留有空格
test命令和測試條件可以判斷 3 類條件:
-
數值比較
使用 -eq, -ge, -gt, -le, -lt, -ne 替代數學中的比較運算子 ==, >=, >, <=, <, != 下面是記憶
- e 與等值相關
- g 與大於相關
- l 與小於相關
- n 有否相關
- q, t 基本比較
-
字串比較
-
=
比較字串是否相同 -
!=
比較字串是否相同 -
<
,>
比較兩個字串大小,使用時必須轉義- 在比較的時候使用的是每個字元的 Unicode 編碼值
- sort 命令處理大寫字母的方法剛好與 test 命令相反,比較測試中大寫字母被認為是小於小寫字母的
-
-n
判斷字串長度是否不為 0 -
-z
判斷字串長度是否為 0
-
-
檔案比較
- -e 是否存在
- -s 是否存在且非空
- -d 是否為目錄
- -f 是否為檔案
- -r 是否可讀
- -w 是否可寫
- -x 是否可執行
- -O 是否當前使用者是檔案屬主
- -G 是否當前使用者組
- 兩個檔案比較新舊,測試之前務必確保檔案存在
- -nt 是否前者新,new time
- -ot 是否前者舊,old time
-
複合條件測試
- && 與運算
- || 或運算
-
bash shell 在 if 語句中的高階特性
-
在子 shell 中執行命令的單括號
- test 語句中使用程式列表時,可能會出現意料之外的結果
-
用於數學表示式的雙括號
- 雙括號命令允許在比較過程中使用 高階數學表示式,任意的數學賦值或比較表示式
- test 命令在進行比較的時候只能使用簡單的算術操作
- 雙括號中表示式的不用轉義處理
-
用於高階字串處理功能的雙方括號
- 使用雙等號進行模式匹配,右邊定義匹配的表示式,支援萬用字元或正規表示式
- 不是所有的 shell 都支援雙方括號
-
-
case: 比較變數尋找特定的值
case variable in pattern1 | pattern2) commands1;; pattern3) commands2;; *) commands3;; esac
- 將指定變數與不同模式進行比較
- 豎線運算子在一行中分隔出多個模式
- 星號會捕獲所有與已知模式不匹配的值
- esac 進行閉合 case
-
for: 迴圈處理
for var in list do commands done
-
list 是迭代列表,每次迭代中變數 var 會包含列表中的當前值
-
list 中值之間是以 空格 分隔的
-環境變數 內部欄位分隔符
IFS
可以關閉分隔規則- 需要修改 IFS 的值時,注意將其恢復原狀
- 一種安全的做法是在修改IFS之前儲存原來的IFS值,之後再恢復它
- 指定多個 IFS 字元,則只需在賦值語句中將這些字元寫在一起即可
-
變數包含了用於迭代的值列表可以用於迭代列表,值列表中能追加或者拼接
-
do-done 中為迴圈體
-
最後一次迭代結束後,變數 var 的值在 shell 指令碼的剩餘部分依然有效
-
list 中複雜的資料處理
- 使用跳脫字元
- 使用雙引號來劃分值
-
從命令中讀取值列表
-
使用萬用字元讀取目錄
- 此時變數 var 放入雙引號內,目錄名和檔名中包含 空格 是完全合法的
- 允許列出多個目錄萬用字元
- 即使檔案或目錄不存在,for 語句也會嘗試把列表處理完,最好在處理之前先測試一下檔案或目錄
-
支援仿 C 語言風格的 for 命令,但注意是使用
(())
而不是 C 語言的()
,有些地方與bash shell 標準的 for 命令並不一致- 變數賦值可以有空格
- 迭代條件中的變數不以美元符號開頭
- 迭代過程的算式不使用expr命令格式
因此,在指令碼中使用仿 C 語言的 for 迴圈時要小心
-
-
while: 某種程度上糅合了 if 語句和 for 迴圈
該命令返回的退出狀態碼為0,就迴圈執行一組命令
while test command do commands done
- 判斷部分類似 if
- 迴圈體使用與 for 相同
- 修改測試條件中用到的變數,否則就會陷入死迴圈
- 允許在 while 語句行定義多個測試命令,但只有最後一個測試命令的退出狀態碼會被用於決定是否結束迴圈
- 支援巢狀
-
until: 與 while 命令工作的方式完全相反,注意測試部分是反的即可
-
迴圈控制
- break: 退出迴圈,後面可以指定數字,數字是要跳出的迴圈層級,預設 1
- continue: 提前中止某次迴圈,也允許透過命令列引數指定要繼續執行哪一級迴圈
-
處理迴圈的輸出
- 對迴圈的輸出使用管道或進行重定向,這可以透過在 done 命令之後新增一個處理命令來實現
處理輸入輸出
-
傳遞引數: 向 shell 指令碼傳遞資料的最基本方法是使用命令列引數,命令列引數允許執行指令碼時在命令列中新增資料
-
引數之間是以空格分隔的
-
bash shell 會將所有的命令列引數都指派給 位置變數
- 位置變數的名稱都是標準數字
- $0 對應指令碼名,$1 對應第一個命令列引數,以此類推直到 $9
- 在超過 9 個引數之後,必須在變數名兩側加上花括號,比如 ${10}
- 執行指令碼時使用的是絕對路徑,那麼位置變數 $0 就會包含整個路徑
- basename: 只要是用於去除路徑和檔案字尾部分的檔名或者目錄名
-
在使用位置變數之前一定要檢查是否為空
-
-
特殊引數變數
$#
含有指令碼執行時攜帶的命令列引數的個數- 那麼變數
${$#}
應該就代表了最後一個位置變數,不能在花括號內使用$
,必須將$
換成!
$*
變數會將所有的命令列引數視為一個單詞,變數會將這些引數視為一個整體$@
變數會將所有的命令列引數視為同一字串中的多個獨立的單詞,以便你能遍歷並處理全部引數$$
當前 PID
-
shift: 移動引數
- 會根據命令列引數的相對位置進行移動
- 預設情況下會將每個位置的變數值都向左移動一個位置
- 變數 $1 的值則會被刪除,變數 $0 的值不會改變
- 如果某個引數被移出,那麼它的值就被丟棄了無法再恢復
- 也可以一次性移動多個位置,指明要移動的位置數即可
-
處理選項
- 提取單個引數時,使用 case 語句
- 在Linux中這個特殊字元是 雙連字元
--
,shell 會用雙連字元表明選項部分結束 - 選項佔用了兩個位置,所以還需要使用shift命令多移動一次
getopt: 能夠識別命令列引數,簡化解析過程,將命令列中選項和引數處理後只生成一個輸出
getopt optstring parameters
-
optstring:
- 定義了有效的命令列選項字母以及是否需要引數值
- 需要引數值的選項字母后面加一個 冒號
- 未包含你指定的選項,則在預設情況下,getopt 命令會產生一條錯誤訊息,使用 -q 可以忽略
-
parameters: 引數列表
set: 有一個選項是 雙連字元
--
,可以將 位置變數 的值替換成 set 命令所指定的值set -- $(getopt optstring "$@")
- optstring: 是你設計的命令列選項
- getopt 命令並不擅長處理 帶空格和引號的引數值,它會將空格當作引數分隔符
getopts: 是 bash shell 的內建命令,比 getopt 多了一些擴充套件功能,能夠和已有的 shell 位置變數配合默契
getopts [:]optstring variable
-
getopts 每次只處理一個檢測到的命令列引數
-
在處理完所有的引數後,getopts 會退出並返回一個大於 0 的退出狀態碼,適合用在解析命令列引數的迴圈中
:
為可選,類似 getopt 命令 -p 引數,有則不顯示錯誤訊息- optstring 值與 getopt 命令中使用的值類似
- variable 每次處理時儲存它們的變數名
-
getopts 涉及兩個環境變數
OPTARG
環境變數儲存帶參選項的引數值OPTIND
環境變數儲存著引數列表中正在處理的引數位置
-
getopts 命令會移除起始的 連字元,所以在 case 語句中不用連字元
-
可以在引數值中加入空格判斷引號界限,能將選項字母和引數值寫在一起,在兩者之間不加空格
-
還可以將在命令列中找到的所有 未定義的選項 統一輸出成 問號
-
知道何時停止處理選項,並將引數留給你處理,處理每個選項時,getopts 會將 OPTIND 環境變數值增 1,可以使用 shift 命令和 OPTIND 值來移動引數
-
獲取使用者輸入
-
read: 從標準輸入或另一個檔案描述符中接受輸入
-
獲取輸入後,read 命令會將資料存入變數
-
如果指定多個變數,則輸入的每個資料值都會分配給變數列表中的下一個變數
-
如果變數數量不夠,那麼剩下的資料就全部分配給最後一個變數
-
不指定任何變數,這會將接收到的 所有資料 都放進特殊環境變數
REPLY
-
-p
選項,允許直接指定提示符 -
-t
選項,指定一個計時器判斷是否輸入超時,單位秒 -
-n
選項,統計輸入的字元數,當字元數達到預設值時,就自動退出 -
-s
選項,避免在輸入的資料出現在螢幕上
讀取檔案
- 從指定檔案中讀取一行文字,當檔案中沒有內容可讀時,會退出並返回非 0 退出狀態碼
-
-
-
標準檔案描述符:Linux 系統會將每個物件當作檔案來處理,這包括輸入和輸出
-
檔案描述符是一個非負整數,唯一會標識的是會話中開啟的檔案
- 0: STDIN 檔案描述符代表 shell 的標準輸入
- 1: STDOUT 檔案描述符代表 shell 的標準輸出
- 2: STDERR 檔案描述符處理錯誤訊息
-
每個程式一次最多可以開啟 9 個檔案描述符
-
在預設情況下,STDERR 和 STDOUT 指向同一個地方
-
STDERR 並不會隨著 STDOUT 的重定向發生改變
-
可以將 檔案描述符 索引值放在重定向符號之前,只重定向對應資訊,兩者必須緊挨著
1>
輸出重定向標準輸出2>
輸出重定向錯誤訊息
-
bash shell 提供特殊的重定向符
&>
將 STDERR 和 STDOUT 的輸出重定向
-
-
在指令碼中重定向輸出
-
臨時重定向 &
- 在重定向到檔案描述符時,必須在檔案描述符索引值之前加一個
&
- 非常適合在指令碼中生成錯誤訊息
- 在重定向到檔案描述符時,必須在檔案描述符索引值之前加一個
-
永久重定向 exec
- 在指令碼執行期間重定向某個特定檔案描述符
- exec 會啟動一個新 shell
- 適合指令碼中有大量資料需要重定向
- 允許將 STDIN 重定向為檔案
-
-
替代性檔案描述符
- 替代性檔案描述符從 3~8 共6個,均可用作輸入或輸出重定向,任意一個都可以分配給檔案並用在指令碼中
- 使用 exec 將替代性檔案描述符指向檔案,此重定向就會一直有效,直至重新分配
- 恢復已重定向的檔案描述符,你可以將另一個檔案描述符分配給標準檔案描述符
- 可以開啟單個檔案描述符兼做輸入和輸出,這樣就能用同一個檔案描述符對檔案進行讀和寫兩種操作,任何讀或寫都會從檔案指標上次的位置開始
-
關閉檔案描述符
- 如果建立了新的輸入檔案描述符或輸出檔案描述符,那麼 shell 會在指令碼退出時自動將其關閉
- 手動關閉檔案描述符,只需將其重定向到特殊符號
&-
- 一旦關閉了檔案描述符,就不能在指令碼中向其寫入任何資料,否則 shell 會發出錯誤訊息
-
lsof: 會列出整個 Linux 系統開啟的所有檔案描述符
- -p 允許指定 PID
- -d 允許指定要顯示的檔案描述符編號
- -a 可用於對另外兩個選項的結果執行 AND 運算
-
抑制命令輸出
- 重定向到一個名為 null 檔案的特殊檔案
- 輸出到 null 檔案的任何資料都不會被儲存,全部會被丟棄
- null檔案的標準位置是
/dev/null
- 輸入重定向中將 /dev/null,實現快速清除現有檔案中的資料
-
使用臨時檔案
-
Linux 系統有一個專供臨時檔案使用的 特殊目錄
/tmp
-
大多數 Linux 發行版配置系統在啟動時會自動刪除 /tmp 目錄的所有檔案
-
系統中的任何使用者都有許可權讀寫 /tmp 目錄中的檔案
-
mktemp: 專門用於建立臨時檔案
- 所建立的臨時檔案不使用預設的 umask 值
- 作為臨時檔案屬主,你擁有該檔案的讀寫許可權,但其他使用者無法訪問
- 使用方法只需指定一個檔名模板即可,同時在檔名末尾要加上 6 個 X
- 命令會任意地將 6 個 X 替換為同等數量的字元,以保證檔名在目錄中是唯一的
- 命令的輸出正是它所建立的檔名,方便在指令碼中使用
-t
選項會強制在系統的臨時目錄中建立檔案,返回所建立的臨時檔案的完整路徑名-d
選項會建立一個臨時目錄
-
-
記錄訊息
-
tee
-
就像是連線管道的 T 型接頭,它能將來自 STDIN 的資料同時送往兩處
- STDOUT
- 命令列所指定的檔名
-
預設情況下,會在每次使用時覆蓋指定檔案的原先內容
-
-a
選項: 將資料追加到指定檔案中
-
-
指令碼控制
-
處理訊號
-
Linux 系統和應用程式可以產生超過 30 個訊號,訊號與值在不同版本可能會存在差異,可以透過
kill
的-l
選項檢視 -
bash shell 會忽略收到的任何 SIGQUIT 訊號和 SIGTERM 訊號,保障互動式 shell 不會被意外終止
- SIGQUIT 訊號 3: 停止程式
- SIGTERM 訊號 15: 儘可能的終止程式,不一定成功比較溫和
-
bash shell 會處理收到的所有 SIGHUP 訊號和 SIGINT 訊號
- SIGHUP 訊號 1: 掛起程式
- SIGINT 訊號 2: 中斷程式,Linux 核心將不再為 shell 分配 CPU 處理時間
-
產生訊號: bash shell 允許使用鍵盤上的組合鍵來生成兩種基本的 Linux 訊號
-
Ctrl+C 組合鍵會生成 SIGINT 訊號
-
Ctrl+Z 組合鍵會生成 SIGTSTP 訊號
- SIGTSTP 訊號 20: 停止 shell 中執行的任何程式,還能從上次停止的位置繼續執行,可以使用 kill 傳送資訊 SIGKILL 訊號或 SIGCONT 訊號進行控制
- SIGKILL 訊號 9: 強制終止程式
- SIGCONT 訊號 18: 在 SIGSTOP, SIGTSTP 後恢復
- 用 ps 命令可以檢視已停止的程式,在 S 列停止狀態顯示為 T
-
-
捕獲訊號
trap
命令可以指定 shell 指令碼需要偵測並攔截的 Linux 訊號trap commands signals
-
commands 部分列出想要與訊號繫結的行為,如果是
--
會恢復訊號的預設行為 -
signals 部分列出想要捕獲的訊號,多個訊號之間以空格分隔,可以使用訊號的值或訊號名
-
為了保證指令碼中的關鍵操作不被打斷,請使用帶有空操作命令的 trap 以及要捕獲的訊號列表
-
要捕獲 shell 指令碼的退出,只需在 trap 命令後加上 EXIT 訊號,提前退出指令碼依然能捕獲
-
-
-
後臺模式執行
- 在後臺模式中,程式執行時不和終端會話的 STDIN, STDOUT, STDERR 關聯
- 指令碼在後臺執行,不佔用終端會話
- 後臺模式執行shell指令碼只需在指令碼名後面加上
&
- 當後臺程式執行時仍然會使用 終端顯示器 來顯示 STDOUT 和 STDERR 訊息,最好是進行重定向避免這種雜亂的輸出
-
在非控制檯下執行指令碼
-
即便退出了終端會話,也在終端會話讓指令碼一直以後臺模式執行到結束
-
nohup: 能阻斷髮給特定程式的 SIGHUP 訊號,當退出終端會話時可以避免程式退出
- 命令會解除終端與程式之間的關聯,因此程式不再同 STDOUT 和 STDERR 繫結在一起
- 命令會自動將 STDOUT 和 STDERR 產生的訊息重定向到一個名為
nohup.out
的檔案中 - nohup.out 檔案一般在 當前工作目錄 中建立,否則會在 $HOME 目錄 中建立
- 執行了另一個命令,那麼該命令的輸出會被追加到已有的 nohup.out 檔案中
-
-
作業控制: 包括啟動、停止、終止、恢復
-
jobs: 作業控制命令
-
命令輸出中的加號和減號
- 帶有加號的作業為預設作業,如果作業控制命令沒有指定作業號,則引用的就是該作業
- 帶有減號的作業會在預設作業結束之後成為下一個預設作業
- 帶加號的作業只能有一個,帶減號的作業也只能有一個
-
-l
選項: 檢視作業的 PID
-
-
刪除已停止的作業,那麼使用 kill 命令向其 PID 傳送 SIGKILL 訊號即可
-
bg: 以後臺模式重啟作業,存在多個作業需要在後加上作業號
-
fg: 以前臺模式重啟作業
-
-
調整謙讓度
-
排程優先順序是指核心為程式分配的 CPU 時間
-
shell 啟動的所有程式的排程優先順序預設都是相同的
-
排程優先順序是一個整數值,取值範圍從-20(最高優先順序)到+19(最低優先順序)
-
在預設情況下,bash shell 以優先順序 0 來啟動所有程式
-
nice: 允許在啟動命令時設定其排程優先順序
- 命令會阻止普通使用者提高命令的優先順序,只有 root 使用者或者特權使用者才能提高作業的優先順序
-
renice: 指定已執行程式的 PID 來改變其優先順序
- 只能對屬主為自己的程式使用 renice 且只能降低排程優先順序
- root 使用者和特權使用者可以使用任意程式的優先順序做任意調整
-
定時執行作業
-
at: 允許指定Linux系統何時執行指令碼
-
at 的守護程式 atd 在後臺執行,在作業佇列中檢查待執行的作業
-
atd 守護程式會檢查系統的一個特殊目錄,通常位於 /var/spool/at 或 /var/spool/cron/atjobs
-
預設情況下,atd 守護程式每隔 60 秒檢查一次這個目錄
-
在預設情況下,命令會將 STDIN 的輸入放入佇列
-
-f
選項: 指定用於從中讀取命令 -
命令能識別多種時間格式,具體參見 /usr/share/doc/at/timespec 檔案
-
使用命令時,該作業會被提交至 作業佇列,針對不同優先順序有 52 種作業佇列
- 作業佇列的字母排序越高,此佇列中的作業執行優先順序就越低
- 預設情況下,提交的作業會被放入 a 佇列
-
-q
選項: 指定其他的佇列 -
任何送往 STDOUT 或 STDERR 的輸出都會透過 郵件系統 傳給該使用者,最好在指令碼中進行重定向
-
-M
選項: 以禁止作業產生的輸出資訊
-
-
atq: 可以檢視系統中有哪些作業在等待
-
atrm: 刪除等待中的作業,指定要刪除的作業號即可
-
cron: 程式排程需要定期執行的作業,相比 at 具有周期性
- 在後臺執行,並會檢查一個特殊的表(時間表),從中獲知已安排執行的作業
- 時間表格式:
minutepasthour hourofday dayofmonth month dayofweek command
- 時間表允許使用特定值、取值範圍或者萬用字元來指定各個欄位
- 命令列表必須指定要執行的命令或指令碼的完整路徑
- 會以提交作業的使用者身份執行該指令碼,因此你必須有訪問該指令碼以及輸出檔案的合理許可權
- 每個使用者都可以使用自己的 cron 時間表執行已安排好的任務
- 在預設情況下,使用者的 cron 時間表檔案並不存在
-
anacron: 彌補 Linux 系統處於關閉狀態時,cron 程式不會再去執行那些錯過的作業
- anacron 判斷出某個作業錯過了設定的執行時間,它會盡快執行該作業
- 只處理位於 cron 目錄的程式
- 它透過時間戳來判斷作業是否在正確的計劃間隔內執行了,每個 cron 目錄都有一個時間戳檔案,該檔案位於 /var/spool/anacron
- 命令使用自己的時間表(通常位於 /etc/anacrontab)來檢查作業目錄
anacron 時間表的基本格式:
period delay identifier command
- period: 定義了作業的執行頻率,單位 day
- delay: 指定了在系統啟動後 anacron 程式需要等待多少分鐘再開始執行錯過的指令碼
- 不會執行位於 /etc/cron.hourly 目錄的指令碼,因為命令不處理執行時間需求少於一天的指令碼
- identifier: 是一個獨特的非空字串,作用是標識出現在日誌訊息和錯誤 email 中的作業
- command: 包含了 run-parts 程式和一個 cron 指令碼目錄名
-
啟動 shell 時執行指令碼
-
應該將需要在登入時執行的指令碼放在 $HOME/.bash_profile
-
如果需要某個指令碼在兩個時刻都執行可以將其放入
.bashrc
- 一次是當使用者登入 bash shell 時
- 另一次是當使用者啟動 bash shell 時
-
-
source: 這是另一種執行 bash 指令碼的方法,稱為 源引
shell 函式
-
bash shell 提供的使用者自定義函式功能
-
建立函式
-
使用關鍵字 function
function name{ commands }
- 函式名稱唯一,指令碼中的函式名不能重複
- 如果定義了同名函式,那麼新定義就會覆蓋函式原先的定義
-
bash shell 指令碼中定義函式的方式建立函式
name(){ commands }
- 函式名後的空括號表明正在定義的是一個函式,這種語法的命名規則和第一種語法一樣
-
-
呼叫函式
-
只需像其他 shell 命令一樣寫出函式名
-
函式可以視為一個小型指令碼,執行結束時會返回一個退出狀態碼
-
函式的退出狀態碼是函式中最後一個命令返回的退出狀態碼
-
$?
可以確定函式的退出狀態碼,提取函式返回值之前執行了其他命令,那麼函式的返回值會丟失 -
return: 以特定的退出狀態碼退出函式
- 函式執行一結束就立刻讀取返回值
- 退出狀態碼必須介於 0~255
-
-
可以將命令的輸出儲存到 shell 變數中一樣,也可以將函式的 STDOUT 輸出儲存到 shell 變數中
-
函式可以使用 標準的位置變數 來表示在命令列中傳給函式的任何引數
-
$0
變數儲存函式名 -
函式引數依次儲存在
$1
,$2
等變數中 -
$#
可以確定傳給函式的引數數量 -
要在函式中使用指令碼的命令列引數,必須在呼叫函式時手動將其傳入
-
向函式傳遞陣列
- 試圖將陣列變數作為函式引數進行傳遞,則函式只會提取陣列變數的第一個元素
- 須先將陣列變數拆解成多個陣列元素,然後將這些陣列元素作為函式引數傳遞,返回陣列變數也採用類似的方法
-
-
-
變數的作用域
-
全域性變數
- 在 shell 指令碼內任何地方都有效的變數
- 預設情況下,在指令碼中定義的任何變數都是全域性變數
- 在函式外定義的變數可在函式內正常訪問
-
區域性變數
- 無須在函式中使用全域性變數,任何在函式內部使用的變數都可以被宣告為區域性變數
- 變數宣告之前加上
local
關鍵字即可,保證了變數僅在該函式中有效,可以輕鬆地將函式變數和指令碼變數分離開
-
-
函式遞迴
- 函式可以呼叫自己來得到結果
- 透過遞迴對複雜的方程進行逐級規約,直到基準值
-
建立庫
- bash shell 允許建立函式庫檔案,然後在多個指令碼中引用此庫檔案
- source: 會在當前shell的上下文中執行命令,而不是建立新的shell並在其中執行命令,這樣指令碼就可以使用庫中的函式
- source命令有個別名,稱作 點號運算子
.
- 在 .bashrc 檔案中定義函式,可長期在命令列復用函式,只需將函式放在檔案末尾即可,也可以源引庫檔案
- GNU shtool shell 指令碼函式庫,提供了一些簡單的 shell 指令碼函式,可用於實現日常的 shell 功能
shell 指令碼高階技巧
sed & gawk
-
sed 編輯器
-
被稱作 流編輯器,根據事先設計好的一組規則編輯資料流
-
可以執行下列操作
- 從輸入中讀取 一行 資料
- 根據所提供的編輯器命令 匹配資料
- 按照命令 修改 資料流中的資料
- 將新的資料輸出到 STDOUT,編輯器並不會修改文字檔案的資料
-
在流編輯器匹配並針對一行資料執行所有命令之後,會重複這個過程直到處理完資料流後結束執行
-
命令的格式
sed options script file
-
options
-
-e
選項額外 sed 命令,執行多個命令- 兩個命令都應用於檔案的每一行資料,命令之間必須以 分號 分隔
- 命令末尾和分號之間不能出現 空格
-
-f
選項在單獨的檔案中指定 sed 命令,目的是大量要執行時使用- 指定檔案中一條命令應於檔案每一行
.sed
作為 sed 指令碼檔案的副檔名,便於識別
-
-n
選項會抑制 sed 編輯器的輸出
-
-
script: 指定了應用於流資料中的單個命令
-
-
預設情況下,會將指定的命令應用於 STDIN 輸入流中,可以直接將資料透過管道傳入
-
sed 命令
-
替換命令 s:
[address]s/替換目標/替換內容/flags
替換標識
- 數字: 指明新文字將替換行中的 第幾處匹配
- g: 指明新文字將替換行中 所有的匹配
- p: 指明列印出替換後的行
- w file: 將替換的結果寫入檔案
- sed 編輯器允許選擇其他字元作為替換命令的替代分隔符,
/
不是絕對的
行定址 address
-
數字模式
n
: 表示特定行,$ 識別符號表示最後一行n,m
: 表示 n 行到 m 行的範圍
-
正規表示式模式
/pattern/command
: pattern 匹配表示式
-
可以對特定地址的多個命令分組
address { sed commands }
-
刪除命令 d: 後面通常不接任何
[address]d
-
插入命令 i: 會在指定行前增加一行,每行新文字末尾使用反斜線
\
[address]i\ strings\ ...\ strings
-
附加命令 a: 會在指定行後增加一行,每行新文字末尾使用反斜線
\
[address]a\ strings\ ...\ strings
-
取代命令 c: 修改行,將範圍內取代內容,它跟插入和附加命令的工作機制一樣
[address]c\ strings\ ...\ strings
-
轉換命令 y: 唯一可以處理單個字元,inchars 和 outchars 進行一對一的對映
[address]y/inchars/outchars
-
寫入命令 w: 向檔案寫入行
[address]w filename
-
讀取命令 w: 將一條獨立檔案中的資料插入資料流
[address]r filename
-
命令 F: 告知 sed 列印出當前正在處理的檔名
[address]F
所以命令相同部分
[address]command
-
-
列印
p
命令: 列印文字行=
命令: 列印行號l
命令: 可以列印資料流中的文字和不可列印字元,行尾的美元符號表示換行符,
-
-
gawk 編輯器
-
相比 sed 增加了一種程式語言,而不僅僅是編輯器命令
- 定義變數 來儲存資料
- 使用算術和字串 運算子 來處理資料
- 使用 結構化程式設計概念 為資料處理新增處理邏輯
- 提取檔案中的資料將其 重新排列組合,最後生成 格式化 報告
-
-
命令的格式
gawk options program file
-
options
- -F 指定行中分隔符
- -f 從指令碼檔案中讀取 gawk 命令,gawk 指令碼建議以
.gawk
為字尾 - -v 定義變數
- -L 指定相容模式或警告級別
-
program: gawk 指令碼
-
file: 處理資料,沒有會從 STDIN 接收資料
-
-
gawk 指令碼用一對花括號來定義
- print: 會將文字列印到 STDOUT
- STDIN 接入資料,會會反覆直到 EOF 字元為止,EOF 字元表示檔案末尾
- Ctrl+D 組合鍵可以生成 EOF 字元
-
特性之一是會自動為每一行的各個資料元素分配一個變數
- $0 代表整個文字行
- $1 代表文字行中的第一個資料欄位,其中 $2, $3, ..., $n 以此內推
- 文字行中的 資料欄位 是透過 欄位分隔符 來劃分的
- 預設情況下,欄位分隔符是任意的 空白字元
-
BEGIN: 會強制 gawk 在讀取資料前執行 BEGIN 關鍵字之後指定的指令碼
-
END: 允許指定一段指令碼在 gawk 處理完資料後執行這段指令碼
-
特殊變數 FS: 這是定義欄位分隔符的另一種方法
sed, gawk 職能
- sed 更適合編輯匹配到的文字
- gawk 更適合格式化文字,對文字進行較複雜格式處理
正規表示式
-
正規表示式是由正規表示式引擎實現的,最流行的是以下兩種
- POSIX基礎正規表示式 BRE 引擎,大多數 Linux 工具至少符合 POSIX BRE 引擎規範
- POSIX擴充套件正規表示式 ERE 引擎,提供了高階模式符號和特殊符號
-
特殊字元
-
BRE 基礎 basic
-
\
跳脫字元 -
錨點字元
^
行首$
行尾
-
.
可以匹配除換行符之外的任意單個字元 -
[]
字元組,如果字元組中的某個字元出現在了資料流中,那就能匹配該模式 -
[^]
排除型字元組,匹配字元組中沒有的字元- 區間,比如
0-9
a-z
A-Z
等範圍化
- 區間,比如
-
特殊的字元組
[[:BRE:]]
其中的 BRE 允許下列詞- alnum: 任意字母或數字字元
- alpha: 任意字母字元
- digit: 0~9 的數字
- lower: 小寫字母
- upper: 大寫字母
- print: 可列印字元
- punct: 標點符號
- space: 任意空白符
- blank: 空格或製表符
-
*
表明該字元必須在匹配模式的文字中出現 0~n 次
-
-
ERE 擴充 extended
-
?
表明前面的字元可以出現 0~1 次 -
+
表明前面的字元可以出現 1~n 次 -
{}
允許為正規表示式指定具體的可重複次數{n}
恰好出現 n 次{n,m}
恰好出現 n~m 次
-
|
以或運算進行匹配 -
()
表示式分組,每一組會被視為一個整體
-
-
瞭解圖形化 shell 程式設計
-
建立文字選單
-
傳統思路
- clear: 清除使用終端會話的終端設定資訊
- echo 命令使用
-e
選項,可以列印非可列印字元 - read 獲取使用者輸入
-
select: 能夠幫助我們自動完成這些工作
select variable in list do commands done
- list: 是由空格分隔的選單項列表,該列表構成了整個選單
- 命令會將每個列表項顯示成一個帶編號的選單項
- PS3 環境變數 定義的特殊提示符,指示使用者做出選擇
- 字串才是要在 case 語句中進行比較的內容,而不是跟選單選項相關聯的數字
-
-
建立文字視窗部件
-
dialog 軟體包: 能夠用 ANSI 轉義控制字元,在文字環境中建立標準的視窗對話方塊
-
使用命令列選項來決定生成哪種視窗部件
-
要在命令列中指定某個特定部件,需要使用雙連字元格式
-
每個dialog部件都提供了兩種輸出形式
- 使用 STDERR,部件返回了資料會將資料傳送給 STDERR
- 使用退出狀態碼
- $? 變數可以確定使用者選擇了 dialog 部件中的哪個按鈕
-
-
-
圖形化視窗部件
- kdialog 軟體包為 KDE 桌面提供了圖形化視窗部件
- zenity 軟體包為 GNOME 桌面提供了圖形化視窗部件