《Linux命令行與shell腳本大全》筆記

初識Linux Shell

什麼是Linux

Linux可劃分爲以下四部分:

  • Linux內核
  • GNU工具
  • 圖形化桌面環境
  • 應用軟件

深入探究Linux內核

內核主要負責以下四種功能:

  • 系統內存管理
  • 軟件程序管理
  • 硬件設備管理
  • 文件系統管理
系統內存管理

不公管理服務器上的可用物理內存,還可以創建和不容易理虛擬內存。

內核通過硬盤上的存儲空間來實現虛擬內存,這塊區域稱爲交換空間(swap space)。

內豐存儲單元按組劃分成很多塊,這些塊稱作頁面(page)。內核將每個存在 頁面放在物理內存或交換空間。然後, 內核 會維護一個內存頁面表。指明哪些頁面位於物理內存內,哪些頁面被換到硬盤上。

內核會記錄哪些內存頁面正在使用中,並自動把一段時間未訪問的內存頁面複製 到交換空間區域(稱爲換出,swapping out_)即使不宜可用內存。當程序要訪問一個已被換出的內存頁面時,內核必需從物理內存換出另外一個內存頁面給它讓出空間,然後從交換空間換入請求的內存頁面。顯然,這個過程 要花時間,拖慢運行的進程。只要Linux系統在運行,爲運行中的程序換出內存面對面的的過程 就不會停歇。

軟件程序管理

Linux操作系統將運行中的程序稱爲進程。可分爲前臺運行和後臺運行。內核控制着Linux系統管理運行在系統上的所有進程。

內核創建了第一個進程(稱爲init進程)來啓動系統上所有的其他進程。當內核啓動時,它會將init進程加載到虛擬 內存中。內核 在啓動任何其他進程時,都 會在虛擬 內存中給新進程分配 一塊發你的區域 來存儲該 進程用到的數據和代碼。

一些Linux發行版使用一個表來管理在系統開機時要自動 啓動的進程。在Linux系統上,這個表通常位於專門文件/etc/inittab中。有的系統(如Ubuntu)則採用/etc/init.d目錄將開機時啓動或停止某個應用的腳本 放在之個目錄 下。這些腳本通過/etc/rcX.d目錄下的入口 啓動。X代表運行級別。

運行級別:

​ 1.單用戶

​ 3.標準啓動

​ 5.X Windows

​ 6.重啓

硬件設備管理

內核的另一職責 是管理硬件設備。

任何Linux系統需要 與之通信的設備,都需要在內核 代碼 中加入其驅動程序 代碼。程序 代碼相當 於應用程序 和硬件設備的中間人,允許內核 與設備之間交換數據。在Linux內核 中有兩種方法用於插入設備驅動代碼:

  • 編譯進內核 的設備驅動 代碼
  • 可插入內核 的設備驅動 模塊

Linxu系統將硬件設備當成特殊 的文件,稱爲設備文件,設備文件有3種分類:

  • 字符型 設備誰的

    指處理數據時每次只能處理一個字符 的設備。大多數類型的調制解調器和終端都是作爲字符型設備文件創建 的。

  • 塊設備文件

    塊設備是指處理數據時每次能處理大塊數據 的設備,比如硬盤。

  • 網絡設備文件

    是指採用數據包發送和接收數據 的設備,包括各種網卡和一個特殊 的迴環設備。

Linux爲系統上的每個設備都創建 一種稱爲節點的特殊文件。與設備的所有通信都 通過設備節點完成。每個節點都 有唯一 的數值 對供Linux內核 標識 它。數值 對包括一個主設備號和一個次設備號。類似的設備被劃分到同樣的主設備號下。次設備號用於標識 主設備組下的某個特定設備。

文件系統管理

不同於其他一些操作系統,Linux內核 支持通過不同類型的文件系統從硬盤中讀寫數據。如下列出了Linux系統用來讀寫數據的標準的文件系統。

文件系統 描述
ext Linux擴展文件系統,最早的Linux文件系統
ext2 第二擴展文件系統,在ext的基礎上提供了更多 的功能
ext3 第三擴展文件系統,支持日誌功能
ext4 第四擴展文件系統,支持高級日誌功能
hgfs OS/2高性能文件系統
ISO9660 ISO 9660文件系統(CD-ROM)
minix minix文件系統
msdos 微軟的FAT16
ncp Netware文件系統
nfs 網絡文件系統
ntfs 支持Microsoft NT文件系統
proc 訪問系統信息
ReiserFS 高級Linux文件系統,能提供性能和硬盤恢復功能
smb 支持網絡訪問的Samba SMB文件系統
sysv 軟早期的Unix文件系統
ufs BSD文件系統
umsdos 建立在msdos上的類Unix文件系統
vfat Windows95文件系統(FAT32)
XFS 高性能 64位日誌文件系統

GNU工具

GNU是GNU’s Not Unix的縮寫。

GNU組織開發了一套完整的Unix工具。

核心GNU工具

被稱爲coreutils軟件包,它由三部分構成:

  • 用以處理文件的工具
  • 用以操作文本的工具
  • 用以管理進程的工具
shell

GNU/Linux shell 是一種特殊的交互式工具。它爲用戶提供了啓動程序,管理文件系統中的誶反及運行在Linux系統上的進程的途徑。shell的核心是命令行提示符。命令行提示符是shell負責交互 的部分。它允許你輸入 文本命令,然後解釋 命令,並在內核中執行。

你也可以將多個shell命令放入文件中作爲程序執行。這些文件被稱作shell腳本。

在Linux,通常有好幾中Linux shell可用。不同的shell有不同的特性,有些更利於創建腳本,有些則更利於管理進程。所有Linux發行版默認的shell都是bash shell。

shell 描述
ash 一種運行在內存受限環境中簡單輕量的shell,但與bash shell完全兼容。
korn 一種與Bourne shell兼容的編程shell,但關聯數組和浮點運算待一些高級的編程特性。
tcsh 一種將C語言中的一些元素引入 到shell腳本 中的shell
zsh 一種結合 了bash,tcsh和korn的特性,同時提供高級編程特性,共享 歷史 文件和主題化提示符的高級shell
Linux桌面環境
X Window系統
KDE桌面
GNOME桌面
Unity桌面
其他桌面
  • Fluxbox
  • Xfce
  • JWM
  • Fvwm
  • fvwm95

Linux發行版

不同的Linux發行版通常歸類爲3種:

  • 完整的核心Linux發行版
  • 特定用途的Linux發行版
  • LiveCD測試發行版

核心Linux發行版

發行版 描述
Slackware 最早的LInux發行版中的一員,在Linux極客中比較流行
Red Hat 主要用於Internet服務器商業發行版
Fedora 從Red Hat分享出的家用發行版
Gentoo 爲高級Linux用戶設計 的發行版,公包含linux源代碼
openSUSE 用於商用和家用的發行版
Debian 在Linux專家和商用 linux產品中流行的發行版

特定用途的Linux發行版

  • CentOD
  • Ubuntu
  • PCLinuxOS
  • Mint
  • dyne:bolic
  • Puppy Linux

Linux LiveCD

走進Shell

進入命令行

控制檯終端

圖形化終端

通過Linux控制檯終端訪問CLI

在大多數Linux發行版中,你可以使用簡單按鍵組合訪問某個Linux虛擬控制檯。通常必須按下Ctrl + Alt組合鍵,然後按功能鍵F1 - F7進入要使用的虛擬控制檯。

可以將終端的背景色設置成白色,其中一種方法是

setterm -inversescreen on

setterm -background white

setterm -foreground black

共有八種顏色可供選擇,分別是black, red, green, yeallow, blue, magenta, cyan, white

選項 參數 描述
-background black, red, green, yellow, blue, magenta, cyan, white 將終端的背景色改爲指定顏色
-foreground black, red, green, yellow, blue, magenta, cyan, white 將終端的前景色改爲指定顏色
-inversescreen on或off 交換背景色和前景色
-reset 將終端外觀恢復成默認設置並清屏
-store 將終端當前的前景色和背景色設置成-reset選項的值

通過圖形化終端仿真訪問CLI

使用GNOME Terminal仿真器

使用Konsole Terminal仿真器

使用Xterm

基本Bash shell命令

啓動Shell

shell提示符

默認bash shell提示符是美元符號($),這個符號表明shell在等待用戶輸入。

bash手冊

大多數Linux發行版自帶用以查找shell命令及其他GNU工具信息的在線手冊 。

man命令用來訪問存儲在Linux系統上的手冊的頁面。

Linux手冊頁慣用的節名

描述
Name 顯示命令名和一段簡短的描述
Synopsis 命令的語法
Configuration 命令配置信息
Description 命令的一般性描述
Options 命令選項描述
Exit Status 命令的退出狀態指示
Return Value 命令的返回值
Errors 命令的錯誤的消息
Environment 描述所使用的環境變量
Files 命令用到的文件
Versions 命令的版本信息
Conforming To 命名所遵從的標準
Notes 其他有幫助的資料
Bugs 提供提交Bug的途徑
Example 展示命令的用法
Authors 命令開以人員的信息
Copyright 命令源代碼 的版權狀況
See Also 與該 命令類型的其他命令

Linux手冊頁的內容區域

區域號 所涵蓋的內容
1 可執行程序或shell命令
2 系統調用
3 庫調用
4 特殊文件
5 文件格式與約定
6 遊戲
7 概覽,約定及雜項
8 超級用戶和系統管理員命令
9 內核例程

手冊頁不是唯一 的資料。還有另一種叫作info頁面的信息。

另外大多數命令都可以接受-help或–help選項。

瀏覽文件系統

Linux文件系統

Linux路徑本身並沒有提供任何有關文件空間存放在哪個物理磁盤上的信息。

在Linux PC上安裝的第一塊硬盤稱爲根驅動器。根驅動器包含了虛擬目錄的核心,其他目錄都是從那裏開始構建的。

常見Linux目錄名稱

目錄 用途
/ 虛擬目錄的根目錄。通常不會在這裏存儲文件
/bin 二進制目錄,存放許多用戶級的GNU工具
/boot 啓動目錄,存放啓動文件
/etc 系統配置文件目錄
/home 主目錄,Linux在這裏創建用戶的目錄
/lib 庫目錄,存放系統和應用程序的庫文件
/media 媒體目錄,可移動媒體設備的常用掛載點
/mnt 掛載目錄,另一個可移動 媒體設備的常用掛載點
/opt 可選目錄,常用於存放第三方軟件包和數據文件
/proc 進程目錄,存放現有硬件及當前相關信息
/root root用戶的主目錄
/sbin 系統二進程目錄,存放許多GNU管理員級工具
/run 運行目錄,存放系統動作時的運行時數據
/srv 服務目錄,存放本地服務的相關文件
/sys 系統目錄,存放系統硬件信息的相關文件
/tmp 臨時目錄,可以在該目錄中創建和刪除臨時工作文件
/usr 用戶二進制目錄,大量用戶級的GNU工具和數據文件都存儲在這裏
/var 可變目錄,用以存放經常變化的文件,比如日誌文件

遍歷目錄

cd destination

  • 絕對文件路徑

絕對文件路徑總是以正斜線作爲起始,指明虛擬文件系統的根目錄。

  • 顯示shell會話的當前目錄

pwd

  • 相對文件路徑

相對文件路徑允許用戶指定一個基於當前位置的目錄文件路徑。

單點(.): 表示當前目錄

雙點(…):表示當前目錄的父目錄

文件和目錄列表

基本列表功能

ls命令最基本的形式會顯示當前目錄下的文件和目錄

參數:

-F: 可以輕鬆區分文件和目錄,它會在目錄後邊加/,還會在可執行文件後邊星號。

-a: 可以把隱藏文件和普通文件及目錄一起顯示出來。

-R: 遞歸選項

-l: 長列表格式輸出

-i: 顯示inode

會顯示如下內容:

  • 文件類型,比如目錄(d),文件(-), 字符型文件(c)或塊設備(b);
  • 文件的權限
  • 文件的硬鏈接總數
  • 文件屬主的用戶名
  • 文件屬組的組名
  • 文件的大小(以字節爲單位)
  • 文件的上次修改時間
  • 文件名或目錄名

-h: 以容易識別的文件大小顯示

過濾輸出列表

ls xxx

  • ?: 代表一個字符
  • *:代表零個或多個字符

處理文件

創建文件

touch filename

會創建一個空文件

如果只想改變文件的訪問時間可以使用-a參數

touch -a filename

複製文件

cp source destination

參數:

-i: 重名需要確認

-R: 遞歸

製表鍵自動補全

鏈接文件

Linux中有兩種不同類型的文件鏈接

  • 符號鏈接

ls -s source lnFile

lnFile是指向source的一個新文件,可以通過inode編號查看

  • 硬鏈接

硬鏈接會創建獨立的虛擬文件,其中包含了原始文件的信息及位置。但是它們從根本上而言是同一個文件。引用硬鏈接文件等同於引用了源文件。要創建硬鏈接,原始文件也必須事先存在,只不過這次使用ln命令時不再需要加入額外的參數了。

重命名文件

mv命令,可以將目錄移動到另一個位置或重新命名

mv source destination

mv oldfilename newfilename

刪除文件

rm -i file

-i: 刪除文件時需要確認一次纔會刪除

-f:強制刪除文件

-r:級聯刪除文件夾

處理目錄

創建目錄

mkdir newDir

參數:

-p:創建多級目錄

刪除目錄

rm -ri

查看文件內容

查看文件類型

file my_file

my_file: ASCII text

查看整個文件

  • cat

    • -n: 顯示行號
    • -b: 只給有文本的行加上行號
    • -T: 用^I替換製表符
  • more

    以分頁的形式顯示文件內容

  • less

查看部分文件

  • tail

    tail命令默認會顯示文件最後10行內容

    -n 2: 顯示最後兩行內容

    -f: 使tail保持活動狀態,並不斷顯示添加到文件中的內容

  • head

    默認顯示文件的前10行

    head -num: 顯示前num行內容

更多的Bash shell

監測程序

探查進程

默認ps只會顯示運行在當前控制檯下的屬於當前用記的進程。

Linux系統中使用的GNU ps命令支持3種不同類型的命令行參數:

  • Unix風格的參數,前面加單破折線
  • BSD風格的參數,前面不加破折線
  • GNU風格的長參數,前面加雙破折線

Unix風格的ps命令參數

參數 描述
-A 顯示所有進程
-N 顯示與指定參數不符的所有進程
-a 顯示除控制進程和無終端進程外的所有進程
-d 顯示除控制進程外的所有進程
-e 顯示所有進程
-C cmdlist 顯示包含在cmdlist列表中的進程
-G grplist 顯示組ID在grplist列表中的進程
-U userlist 顯示屬主的用戶ID在userlist列表中的進程
-g grplist 顯示會話或組ID在grplist列表
-p pidlist 顯示PID在pidlist列表中的進程
-s sesslist 顯示會話ID在sesslist列表中的進程
-t ttylist 顯示終端ID在ttylist列表中的進程
-u userlist 顯示有效用戶iD在userlist列表中的進程
-F 顯示更多額外輸出(相對於-f參數而言)
-O format 顯示默認的輸出列以及format列表指定的特定列
-M 顯示進程的安全信息
-c 顯示進程額外調試器信息
-f 顯示完整格式的輸出
-j 顯示任務信息
-l 顯示長列表
-o format 公顯示由format指定的列
-y 不要顯示進程標記(process flag, 表明進程狀態的標記)
-Z 顯示安全標籤(security context)信息
-H 用層級格式來顯示進程(樹狀,用來顯示父進程)
-n namelist 定義了WCHAN列顯示的值
-w 採用寬輸出模式,不限寬度顯示
-L 顯示進程中的線程
-V 顯示ps命令的版本號

e.g.

ps -ef

顯示內容:

  • UID: 啓動這些進程的用戶
  • PID: 進程的進程ID
  • PPID: 父進程的進程號(如果該 進程是由另一個進程啓動的)
  • C: 進程生命週期中的CPU利用率
  • STIME: 進程啓動時的系統時間
  • TTY: 進程啓動時的終端設備
  • TIME: 運行進程需要的累計CPU時間
  • CMD: 啓動的程序名稱

-l參數:

多出的列:

  • F: 內核分配給進程的系統標記
  • S: 進程的狀態(O代表正在運行;S代表在休眠;R代表可運行,正等待運行;Z代表僵化,進程已結束但父進程已不存在;T代表停止)
  • PRI: 進程的優先級(越大的數字低的優先級)
  • NI: 謙讓度值 用來參與決定優先級
  • ADDR: 進程的內存地址
  • SZ: 假如進程被換出, 所需要交換空間的大致大小
  • WCHAN: 進程休眠的內核函數的地址

BSD風格

主要命令參數:

參數 描述
T 顯示跟當前終端關聯的所有進程
a 顯示跟任意終端關聯的所有進程
g 顯示所有的進程,包括控制進程
r 僅顯示運行中的進程
x 顯示所有的進程,甚至包括未分配任何終端的進程
U userlist 顯示歸userlist列表中的某用戶ID所有的進程
p pidlist 顯示PID在pidlist列表中的進程
t ttylist 顯示所關聯的終端在ttylist列表中的進程
O format 除了默認輸出的列之外,還輸出由format指定的列
X 按過去的Linux i386寄存器格式顯示
Z 將安全信息添加到輸出中
j 顯示任務信息
l 採用長模式
o format 公顯示由format指定的列
s 採用信號格式顯示
u 採用基於用戶的格式顯示
v 採用虛擬內存格式顯示
N namelist 定義在WCHAN列中使用的值
O order 定義顯示信息列的順序
S 將數值信息從子進程加到父進程上,比如CPU和內存的使用情況
c 顯示真實的命令名稱 (用以啓動進程的程序名稱)
e 顯示命令使用的環境變量
f 用分層格式來顯示進程,表明哪些進程啓動了哪些進程
h 不顯示頭信息
k sort 指定用以將輸出排序的列
n 和WCHAN信息一起顯示出來,用數值來表示用戶ID和組ID
w 爲較寬屏幕顯示寬輸出
H 將線程按進程來顯示
m 在進程後顯示線程
L 列出所有格式指定符
V 顯示ps命令的版本號

輸出結果中的大部分的輸出列跟使用Unix風格參數時的輸出是一樣的,只有一小部分如下:

  • VSZ: 進程在內存中的大小以KB爲單位

  • RSS: 進程在未換出時佔用的物理內存

  • STAT: 代表當前進程狀態 的雙字符狀態碼

    • 第一個字符采用了和Unix風格S列相同的值,表明進程是在休眠,運行還是等待。

    • 第二個參數進一步說明進程的狀態

      <: 該進程運行在高優先級上

      N:該進程運行在低優先級上

      L: 該進程有頁面鎖定在內存中

      s: 該 進程是控制進程

      l: 該進程是多線程的

      +: 該進程運行在前臺

GNU長參數

常用參數

參數 描述
–deselect 顯示所有進程,命令行中列出的進程
–Group grplist 顯示組ID在grplist列表中的進程
–User userlist 顯示用戶ID在userlist列表中的進程
–group grplist 顯示有效組ID在grplist列表中的進程
–pid pidlist 顯示PID在pidlist列表中的進程
–ppid pidlist 顯示父PID在pidlist列表中的進程
–sid sidlist 顯示會話ID在sidlist列表中的進程
–tty ttylist 顯示終端設備號在ttylist列表中的進程
–user userlist 顯示有效用戶ID的userlist列表中的進程
–format format 僅顯示由format指定的列
–context 顯示額外的安全信息
–cols n 將屏幕寬度設置爲n列
–columns n 將屏幕寬度設置爲n列
–cumulative 包含已停止的子進程的信息
–forest 用層級結構顯示出進程和父進程之間的關係
–headers 在每頁輸出中都顯示列的頭
–no-headers 不顯示列的頭
–lines n 將屏幕高度設爲n行
–rows n 將屏幕高度設爲n排
–sort order 指定將輸出按哪列排序
–width n 將屏幕寬度設爲N列
–help 顯示幫助信息
–info 顯示調試信息
–version 顯示ps命令的版本號

實時監測進程

top

輸出的第一部分顯示的是系統的概況:

第一行顯示了當前時間,系統的運行時間,登錄的用戶數以及系統的平均負載。

​ 平均負載有3個值,最近1分鐘的,最近5分鐘的和最近15分鐘的平均負載。值越大說明系統的負載越高。

​ 通常,如果系統的負載值超過2,就說明系統比較繁忙了。

第二行顯示了進程概要信息–top命令的輸出中將進程叫作任務(task):

​ 有多少進程處在運行,休眠,停止或僵化狀態

第三行顯示了Cpu的概要信息。

緊跟其後的兩行說明了系統內存的狀態。

​ 第一行是系統的物理內存: 總共有多少內存,當前使用了多少,還有多少空閒。後一行說的是同樣的信息,不過是針對系統交換空間。

最後一部分顯示了當前運行中的進程的詳細列表。有些跟ps命令的輸出類似。

  • PID:進程的ID
  • USER: 進程屬主的名字
  • PR: 進程的優先級
  • NI: 進程的謙讓度值
  • VIRT: 進程佔用的虛擬內存總量
  • RES: 進程佔用的物理內存總量
  • SHR: 進程和其他進程共享 的內存總量
  • S: 進程的狀態(D代表可中斷的休眠狀態,R代表在運行狀態,S代表休眠狀態,T代表跟蹤狀態或停止狀態,Z代表僵化狀態)
  • %CPU: 進程使用的CPU時間比例
  • %MEM: 進程使用的內存佔可用內存的比例
  • TIME+: 自進程啓動到目前爲止的CPU時間總量
  • COMMAND: 進程所對應的命令行名稱,也就是啓動的程序名。

默認top命令會對按昭%cpu值對進程排序。可以在top運行時使用多種交互命令重新排序。每個交互式命令都 是單字符,在top命令運行時鍵入可改變top的行爲。鍵入f允許你選擇對輸出進行排序的字段,鍵入d允許你修改輪詢間隔。鍵入q可以退出top。用戶在top命令的輸出上有很大的控制權。

結束進程

在Linux中進程之間通過信號來通信。

Linux進程信號:

信號 名稱 描述
1 HUP 掛起
2 INT 中斷
3 QUIT 結束運行
9 KILL 無條件終止
11 SEGV 段錯誤
15 TERM 儘可能終止
17 STOP 無條件停止運行,但不終止
18 TSTP 停止或暫停,但繼續在後臺運行
19 CONT 在STOP或TSTP之後恢復執行

在Linux中有兩個命令可以向運行中的進程發出進程信號

kill

kill -option pid pid pid…

killall

killall命令支持通過進程名而不是PID來結束進程。

killall也支持通配符。

e.g.

killall http* # 結束所有以http開頭的進程

監測磁盤空間

掛載存儲媒體

mount

默認情況下,mount命令會輸出當前系統上掛載的設備列表

默認提供如下四部分信息:

  • 媒體的設備文件名
  • 媒體掛載到虛擬目錄的掛載點
  • 文件系統類型
  • 已掛載媒體的訪問狀態

需要手動在虛擬目錄中掛載設備,需要以root用戶身價登錄,或是以root用戶身份運行sudo命令。

mount -t type device directory

如果Type是VindowsPC共用的存儲設備,通常類型如下:

  • vfat: Windows長文件系統
  • ntfs: windows NT, XP, Vistra和Windows7中廣泛使用的高級文件系統
  • iso9660: 標準Cd-ROM文件系統

mount命令的參數

參數 描述
-a 掛載/etc/fstab文件中指定的所有文件系統
-f 使用mount命令模擬掛載設備,但並不真的掛載
-F 和-a參數一起使用時,會同時掛載所有文件系統
-v 詳細模式,將會說明掛載設備的每一步
-I 不啓用任何/sbin/mount.filesystem下的文件系統幫助文件
-l 給ext2,ext3或XFS文件系統自動 添加文件系統標籤
-n 掛載設備,但不註冊到/etc/mtab已掛載設備文件中
-p num 進行加密掛載時,從文件描述符num中獲得密碼短語
-s 忽略該文件系統不支持的掛載選項
-r 將設備掛載爲只讀的
-w 將設備掛載爲可讀寫的(默認參數)
-L label 將設備按指定 的label掛載
-U uuid 將設備按指定的uuid掛載
-O 和-a參數一起使用,限制命令只作用到特定的一組文件系統上
-o 給文件系統添加特定的選項

以下爲-o常用參數

  • ro: 以只讀形式掛載
  • rw: 以讀寫形式掛載
  • user: 允許普通用戶掛載文件系統
  • check=none: 掛載文件系統時不進行完整校驗
  • loop: 掛載一個文件
umount

從Linux系統上移除一個可移動設備時,不能直接從系統上移除,而應該先卸載。

umount [directory | device]

df

用來查看所有已掛載磁盤的使用情況

命令輸出格式:

  • 設備的設備文件位置
  • 能容納多少個1024字節大小的塊
  • 已用了多少個1024字節大小的塊
  • 還有多少個1024字節大小的塊可用
  • 已用空間所佔比例
  • 設備掛載到了哪個掛載點上

常用參數:

  • -h: 以可讀的方式顯示容量

du

此命令可以顯示某個特定目錄(默認情況下是當前目錄)的磁盤使用情況

常用參數

  • -c : 顯示所有已列出文件總的大小
  • -h: 按用戶易讀的格式輸出大小
  • -s: 顯示每個輸出參數的總計
  • –max-depth=num: 只統計num深度的目錄

處理數據文件

排序數據

sort

常用參數:

單破折線 雙破折線 描述
-b –ignore-leading-blanks 排序時忽略起始的空白
-C –check-quiet 不排序,如果數據無序也不要報告
-c –check 不排序,但檢查輸入數據是不是已排序;未排序的話,報告
-d –dictionary-order 僅考慮空白和字母,不考慮特殊字符
-f –ignore-case 默認情況下,會將大寫字母排在前面;這個參數會忽略大小寫
-g –general-number-sort 按通用數值來排序(跟-n不同,把值當浮點數來排序,支持科學計數法表示的值)
-i –ignore-nonprinting 在排序時忽略不可打印字符
-k –key=POST1 [, POS2] 排序從POS1位置開始,如果指定了POS2的話,到POS2位置結束
-M –month-sort 用三個字符月份名按月份排序
-m –mrege 將兩個已排序數據文件合併
-n –numeric-sort 按字符串數值來排序(並不轉換爲浮點數)
-o –output=file 將排序結果寫出到指定的文件中
-R –random-sort --random-source=FILE 按隨機生成的散列表的鍵值排序。 指定 -R參數用到的隨機字節的源文件
-r –reverse 反序排序
-S –buffer-size=SIZE 指定使用的內存大小
-s –stable 禁用最後重排序比較
-T –temporary-directory=DIR 指定一個位置來存儲臨時工作文件
-t –field-separator=SEP 指定一個用來區分鍵位置的字符
-u –unique 和-c參數一起使用時, 檢查嚴格排序;不和-c參數一起使用時,公輸出第一例相似的兩行
-z –zero-terminated 用NULL字符作爲行尾,而不是用換行符

搜索數據

grep

grep [option] pattern [file]

常用參數:

  • -v: 輸入不匹配該模式的行
  • -n: 顯示行號
  • -c: 統計符合匹配的行數
  • -e:多模式匹配,每個參數使用-e來標識
  • parttern支持正則表達式
fgrep

壓縮數據

Linux文件壓縮工具

工具 文件擴展名 描述
bzip2 .bz2 採用Burrows-Wheeler塊排序文本壓縮算法和霍夫曼編碼
compress .Z 最初的Unix文件壓縮工具,已經快沒人用了
gzip .gz GNU壓縮工具,用Lempel-Ziv編碼
zip .zip Windows上PKZIP工具的Unix實現
gzip

這個軟件意在編寫一個能夠替代原先Unix中compress工具的免費版。它包含以下工具

  • gzip: 用來壓縮文件
  • gzcat: 用來查看壓縮過的文本文件的內容
  • gunzip: 用來解壓縮

歸檔數據

tar

tar function [options] object1 object2 …

function參數定義了tar命令應該做什麼,如下:

功能 長名稱 描述
-A –concatenate 將一個已有的tar歸檔文件追加到另一個已有tar歸檔文件
-d –create 創建一個新的tar歸檔文件
-d –diff 檢查歸檔文件和文件系統的不同之年
–delete 從已有tar歸檔文件中刪除
-r –append 追加文件到已有tar歸檔文件末尾
-t –list 列出已有tar歸檔文件中的內容
-u –update 將比tar歸檔文件中已有的同名文件新的文件追加到該 tar歸檔文件中
-x –extract 從已有tar歸檔文件中提取文件

tar命令選項

選項 描述
-C dir 切換到指定目錄
-f file 輸出結果到時文件或設備file
-j 將輸出重定向給bzip2命令來壓縮內容
-p 保留所有文件權限
-v 在處理文件時顯示文件
-z 將輸出重定向給gzip命令來壓縮內容

理解 Shell

shell的類型

系統啓動什麼樣的shell程序取決於你個人的用戶配置。在/etc/passwd文件中,在用記ID記錄的第7個字段中列出了默認的shell程序。

shell的父子關係

bash shell程序可使用命令行參數修改shell啓動方式。

常用參數:

參數 描述
-c string 從string中讀取命令並進行處理
-i 啓動一個能夠接收用戶輸入 的交互式shell
-l 以登錄shell的形式啓動
-r 啓動一個受限shell,用戶會被限制在默認目錄中
-s 從標準輸入中讀取命令

進程列表

將所有命令寫在一行並以分號分隔,最後使用圓括號括起所有命令。

(pwd; cd; ls; echo $BASH_SUBSHELL)

加入括號使命令列表變成了進程列表,生成了一個子shell來執行對應的命令。

進程列表是一種命令分組(command grouping)。另一種命令分組是將命令放入花括號中,並在命令列表尾部加上分號(;)。語法爲{command; }。使用花括號進行命令分組並不會像進程列表那樣創建出子shell.

別出心裁的子shell用法

探索後臺模式
sleep

在後臺模式中運行命令可以在處理命令的同時讓出CLI,以供使用。

演示後臺模式的一個經典命令就是sleep。

sleep接受一個cdvo,yynw參數是你希望進程等待的秒數。

sleep 10 &

想要將命令置入後臺模式,可以在命令末尾加上字符&。

jobs

可以顯示出當前運行在後臺模式中的所有用戶的進程。

參數:

  • -l: 顯示後臺進程的PID
將進程列表置入後臺

&

協程

協程可以同時做兩件事。它在後臺生成一個子shell,並在這個子shell中執行命令。

要進程協程處理,得使用coproc命令,還有要在子shell中執行的命令。

e.g.

coproc My_job { sleep 10; }
[1] 2570
jobs
[1]+ Running 		coproc My_job { sleep 10; } &

理解shell的內建命令

外部命令

外部命令,有時候也被稱爲文件系統命令,是存在於bash shell之外的程序。它們並不是sheel程序的一部分。外部命令程序通常位於/bin,/usr/bin,/sbin或者/usr/bin中。

我們可以使用which和type命令找到它們。

當外部命令執行時,會創建一個子進程。這種操作被稱爲衍生(forking)。

內建命令

內建命令與外部命令的區別在於前都不需要使用子進程來執行。它們已經和shell編譯成了一體,作爲shell工具的組成部分存在。不需要藉助外部程序文件來運行。

因爲不既不需要通過衍生出子進程來執行,也不需要打開程序文件,內建命令的執行速度要更快,效率也高。

history

可以查看最近用過的命令列表,通常歷史記錄中會保存最近的1000條命令。你也可以修改這個數字,你需要修改名爲HISTSIZE的環境變量。

  • history -a: 可以將命令歷史強制寫入.bash_history文件。
命令別名

alias命令是另一個shell的內建命令。它允許你爲常用的命令及其參數創建另一個名稱,從而將輸入量減少到最低。

很多Linux發行版很有可能已經爲你設置好了一些常用命令的別名。可以使用alias -p查看。

使用Linux環境變量

Linux環境變量能幫你提升Linux shell體驗。很多程序和腳本都通過環境變量來獲取系統信息、存儲臨時數據和配置信息。

什麼是環境變量

在bash shell中,環境變量分爲兩類:

  • 全局變量
  • 局部變量

全局環境變量

全局環境變量對於shell會話和所有生成的子shell都是可見的。局部變量則只對創建他們的shell可見。

查看全局變量,可以使用env或printenv命令。

要顯示個別環境變量的值,可以使用printenv命令。

printenv HOME

也可以使用echo $環境變量名

echo $HOME

局部環境變量

局部變量只能在定義它們的進程中可見。

在Linux系統中沒有一個只顯示局部環境變量的命令。

set命令會顯示爲某個特定進程設置的所有環境變量,包括局部變量,全局變量以及用戶定義變量。

設置用戶定義變量

可以在bash shell中直接設置自己的變量。

設置局部用戶定義變量

我們可以通過等號給環境變量賦值,值可以是數值或字符串。

my_variable=Hello

echo $my_variable

如果要給變量賦一個含有空格的字符串值,必須用單引號來界定字符串的首和尾。

變量名,等號和值之間不能有空格。

設置全局環境變量

方法是:先創建一個局部環境變量,然後再把它導出到全局環境中。

使用export命令完成命令導出到全局環境,變量名前不需要加$.

刪除環境變量

unset

注意: 在涉及環境變量名時,如果要用到變量,使用;如果要操作變量,不加。這條規則的一個例外就是使用printenv顯示某個變量的值。

默認的shell環境變量

bash shell支持的Bourne變量

變量 描述
CDPATH 冒號分隔的目錄列表, 作爲cd命令的搜索路徑
HOME 當前用戶的主目錄
IFS shell用來將文本字符串分割成字段的一系列字符
MAIL 當前用戶收件箱的文件名
MAILPATH 冒號分隔當前用戶收件箱的文件名列表
OPTARG getopts命令處理的最後一個選項參數值
OPTIND getopts命令處理的最後一個參數的索引號
PATH shell查找命令的目錄列表,由冒號分隔
PS1 shell命令行界面的主提示符
PS2 shell命令行界面的次提示

bash shell環境變量

變量 描述
BASH 當前shell實例的全路徑名
BASH_ALIASES 含有當前已設置別名的關聯數組
BASH_ARGC 含有傳入子函數或shell腳本 的參數總數的數組變量
BASH_ARCV 含有傳入子函數或shell腳本的參數的數組變量
BASH_CMDS 關聯數組,包含shell執行過的命令的所有位置
BASH_COMMAND shell正在執行的命令或馬上就執行的命令
BASH_ENV 設置了的話,每個bash腳本會在運行前先嚐試運行該 變量定義的啓動文件
BASH_EXECUTION_STRING 使用bash -c選項傳遞過來的命令
BASH_LINENO 含有當前執行的shell函數的源代碼秸的數組變量
BASH_REMATCH 只讀數組,在使用正則表達式的比較運算符=~進行肯定匹配(positive math)時,包含了匹配到的模式和子模式
BASH_SOURCE 含有當前正在 執行的shell函數所在源文件名的數組變量
BASH_SUBSHELL 當前子shell環境的嵌套級別(初始是0)
BASH_VERSINFO 含有當前運行的bash shell的主版本號和次版本號和數組變量
BASH_VERSION 當前運行的bash shell的版本號
BASH_XTRACEFD 若設置成了有效的文件描述符(0,1,2),則’set -x’調試選項生成的跟蹤輸出可被重定向。通常用來將跟蹤輸出到一個文件中
BASHOPTS 當前啓動的bash shell選項的列表
BASHPID 當前bash進程的PID
COLUMNS 當前bash shell實例所有終端的寬度
COMP_CWORD COMP_WORDS變量的索引值,後者含有當前光標的位置
COMP_LINE 當前命令行
COMP_POINT 當前光標位置相對於當前命令起始索引
COMP_KEY 用來調用shell函數補全功能 的最後一個鍵
COMP_TYPE 一個整數值,表示所嘗試的補全類型,用以完成shell函數補全。
COMP_WORDBREAKS Readline庫中用於單詞補全的詞分隔字符
COMP_WORDS 含有當前命令行所有單詞的數組變量
COMPREPLY 含有由shell函數生成的可能填充代碼的數組變量
COPROC 佔用未命名的協進程的I/O文件描述 符的數組變量
DIRSTACK 含有目錄棧當前內容的數組變量
EMACS 設置爲‘t’時,表明emacs shell緩衝區正在工作,而行編輯功能被禁止
ENV 如果設置了該 環境變量,在bash shell腳本 運行之前會先執行已定義的啓動文件(僅用於當bash shell以POSIX模式被調用時)
EUID 當前用戶的有效用戶ID(數字形式)
FCEDIT 供fc命令使用的默認編輯器
FIGNORE 在進行文件名補全時可以忽略後綴名列表,由冒號分隔
FUNCANME 當前執行的shell函數名稱
FUNCNEST 當設置成非零時,表示所允許的最大函數嵌套級數(一旦超出,當前命令即被終止)
GLOBIGNORE 冒號分隔的模式列表,定義了在進行文件名擴展時可以忽略的一組文件名
GOUPS 含有當前用戶屬組列表的數組變量
HISTCHARS 控制歷史記錄擴展,最多可有3個字符
HISTCMD 當前命令在歷史記錄中的編號
HISTCONTROL 控制哪些命令留在歷史記錄列表中
HISTFILE 保存shell歷史記錄列表 的文件名(默認是.bash_hisotry)
HISTFILESIZE 最多在歷史文件中存多少行
HISTTIMEFORMAT 如果設置了且非空,就用作格式化字符串,以顯示bash歷史中每條命令的時間戳
HISTIGNORE 同冒號分隔的模式列表,同用來決定 歷史文件中哪些命令會被忽略
HISTSIZE 最多在歷史文件中存多少條命令
HISTFILE shell在補全主機名時讀取的文件名
HOSTNAME 當前主機的名稱
HOSTTYPE 當前運行bash shell的機器
IGNOREEOF shell在退出前必須收到連續的EOF字符的數量(如果這個值不存在,默認是1)
INPUTRC Readline初始化文件名(默認是.inputrc)
LANG shell的語言環境類別
LC_ALL 定義了一個語言環境類別,能夠覆蓋LANG變量
LC_COLLATE 設置對字符串排序時用的排序規則
LC_CTYPE 決定如何解釋出現在文件名擴展和模式匹配中的字符
LC_MESSAGES 在解釋前面帶有$的雙引號字符串時,該環境變量決定了所採用的語言環境設置
LC_NUMERIC 決定着格式化數字時採用的語言環境設置
LINENO 當前執行的腳本 的行號
LINES 定義了終端上可見的行數
MACHTYPE 用“CPU-公司-系統”(Cpu-company-system)格式定義的系統類型
MAPFILE 一個數組變量,當mapfile命令未指定數組變量作爲參數時, 它存儲了mapfile所講稿的文本
MAILCHECK shell查看新郵件的頻率 (以秒爲單位,默認是60)
OLDPWD shell之前的工作目錄
OPTERR 設置爲1時,bash shell會顯示getopts命令產生的錯誤
OSTYPE 定義了shell所在的操作系統
PIPESTATUS 含有前臺進程的能出狀態列表 的數組變量
POSIXLY_CORRECT 設置了的話,bash會以POSIX模式啓動
PPID bash shell父進程的PID
PROMPT_COMMAND 設置了的話,在命令行主提示符顯示之前會執行這條命令
PROMPT_DIRTRIM 用來定義當啓用了\w或\W提示符字符串轉義時顯示的尾部目錄名的數量。被刪除的目錄名會用一組英文句點替換
PS3 select命令的提示符
PS4 如果使用了bash的-x選項,在命令行之前顯示的提示信息
PWD 當前工作目錄
RANDOM 返回一個0~32767的隨機數(對其的賦值可作爲隨機數生成器的種子)
READLINE_LINE 當使用bind -x命令時,存儲Readline緩衝區的內容
READLINE_POINT 當使用bind -x命令時,表示 Readline緩衝區內容插入點的當前位置
REPLY read命令的默認變量
SECONDS 自從shell啓動到現在的秒數(對其賦值將重置計數器)
SHELL bash shell的全路徑名
SHELLOPTS 已啓用bash shell選項列表,列表薦這間以冒號分隔
SHLVL shell的層級;每次啓動一個新bash shell,該值增加1
TIMEFORMAT 指定了shell的時間顯示格式
TMOUT select和read命令在沒輸入的情況下等待多久(以秒爲單位),默認值 爲0,表示無限長
TMPDIR 目錄名,保存bash shell創建 的臨時文件
UID 當前用戶的真實用記ID(數字形式)

設置PATH環境變量

PATH環境變量定義了用於進行命令和程序查找的目錄。如果命令或者程序的位置沒有包括 在PATH變量中,那麼如果使用的不是絕對路徑 的話,shell是沒法找到的。所以把新的搜索目錄添加到現有的PATH環境變量中。

PATH中各個目錄之間是用冒號分隔的。你只需要引用原來的PATH值,然後再給這個字符串添加新目錄就行了。

定位系統環境變量

登錄shell

當你登錄Linux系統時,bash shell會作爲登錄shell啓動。登錄shell會從5個不同的啓動文件時讀取命令:

  • /etc/profile
  • $HOME/.bash_profile
  • $HOME/.bashrc
  • $HOME/.bash_login
  • $HOME/.profile

/etc/profile文件是系統上默認的bash shell的主啓動文件。系統上的每個用戶登錄時都會執行啓動這個文件。

另外4個啓動文件是針對 用戶的,可根據個人需求定製。

/etc/profile

每個發行版的/etc/profile文件都有不同的設置和命令

$HOME目錄下的啓動文件

交互式shell進程

非交互式shell

環境變量持久化

最好不要修改/etc/profile文件,如果你升級了所用的發行版,這個文件也會跟着更新,你所定製的變量就沒有了。

最好是在/etc/profile.d目錄中創建一個以.sh結尾的文件。把所有新的或修改過的全局環境變量設置放在這個文件中。

數組變量

數組是能夠存儲多個值的變量。這些值可以單獨引用,也可以作爲整個數組來引用。

要給某個環境變量設置多個值,可以把值 放在括號裏,值 與值之間用空格分隔

mytest=(one two three foru five)

echo $mytest

one

echo ${myest[2]}

three

echo ${mytest[*]}

one two three four five

myest[2] =seven

echo ${mytest[*]}

one two seven four five

unset mytest[2]

echo ${mytest[*]}

one two four five

echo ${mytest[2]}

echo ${mytest[3]}

four

理解Linux文件權限

Linux的安全性

/etc/passwd文件

此文件包含如下信息:

  • 登錄用戶名
  • 用戶密碼(X)
  • 用戶賬戶的UID(數字形式)
  • 用戶賬戶的組ID(GID)(數字形式)
  • 用戶賬戶的文本描述(稱爲備註字段)
  • 用戶HOME目錄的位置
  • 用戶的默認shell

/etc/shadow文件

此文件對Linux系統密碼管理提供了更多的控制。只有root用戶才能訪問/etc/shadow文件

它包含如下信息:

  • 與/etc/passwd文件中的登錄名字段對應的登錄名
  • 加密後的密碼
  • 自上次修改密碼後過去的天數密碼(自1970年1月1日開始計算)
  • 多少天后才能更改密碼
  • 多少天后必須更改密碼
  • 密碼過期前提前多少天提醒用戶更改密碼
  • 密碼過期後多少天禁用用戶賬戶
  • 用戶賬戶被禁用的日期(自1970年1月1日到當天的天數表示)
  • 預留字段給將來使用

添加新用戶

用來向系統添加新用戶的主要工具是useradd。這個命令可一次性創建新用戶賬戶及設置用戶HOME目錄結構。

useradd命令使用系統的默認值 以及命令行參數來設置用戶賬戶。

系統默認值 被設置在/etc/default/useradd文件中。可以使用加入了-D選項的useradd命令查看所用Linux系統中的這些默認值 。

在創建新用戶時,如果你不在命令行中指定具體的值 ,useradd命令就會使用-D選項所顯示的那些默認值。

  • 新用戶會被添加 到GID爲100的公共組
  • 新用戶的HOME目錄將會位於/home/loginname
  • 新用戶賬戶密碼在過期後不會被禁用
  • 新用戶賬戶未被設置過期日期
  • 新用戶賬戶將bash shell作爲默認shell
  • 系統會將/etc/skel目錄下的內容複製到新用戶的HOME目錄下
  • 系統爲該 用戶賬戶在mail目錄下創建 一個用於接收郵件的文件

要想在創建用戶時改變默認值或默認行爲,可以使用命令行參數,常用的如下:

參數 描述
-c comment 給新用戶添加備註
-d home_dir 爲主目錄指定一個名字(如果不想用登錄名作爲主目錄名的話)
-e expire_date 用YYYY-MM-dd格式指定一個賬戶過期的日期
-f inactive_days 指定這個用戶密碼過期 後多少天這個賬戶被禁用;0表示密碼一過期就立即禁用,1表示禁用這個功能
-g initial_group 指定用戶登錄組的GID或組名
-G goup … 指定用戶除登錄組之外所屬的一個或多個附加組
-k 必須和-m一起使用,將/etc/skel目錄的內容複製到用戶的HOME目錄
-m 創建用戶的HOME目錄
-M 不創建用戶的HOME目錄(當默認設置裏要求創建時才使用這個選項)
-n 創建一個與用戶登錄名同名的新組
-r 創建系統賬戶
-p passwd 爲用戶賬戶指定默認密碼
-s shell 指定默認的登錄shell
-u uid 爲賬戶指定唯一 的UID

刪除用戶

userdel

默認userdel只會刪除/etc/passwd文件中的用戶信息,而不會刪除系統中屬於該 賬戶的任何文件。

-r: 會刪除用戶的HOME目錄以及郵件目錄。

修改用戶

用戶賬戶修改工具:

命令 描述
usermod 修改用戶賬戶的字段,還可以指定主要組以及附加組的所屬關係
passwd 修改已有用戶的密碼
chpasswd 從文件中讀取登錄名密碼對,並更新密碼
chage 修改密碼的過期日期
chfn 修改用戶賬戶的備註信息
chsh 修改用戶賬戶的默認登錄shell
usermod

它能用來修改/etc/passwd文件中的大部分字段,參數大部分跟useradd命令的參數一樣(比如,-c修改備註字段,-e修改過期日期,-g修改默認登錄組)。另外還有一些

  • -l修改用戶賬戶的登錄名
  • -L鎖定賬戶,使用戶無法登錄
  • -p修改賬戶的密碼
  • -U解除鎖定,使用戶能夠登錄
passwd和chpasswd

如果只用passwd命令,它會改你自己的密碼,系統上的任何用戶都能修改自己的密碼,但只有root用戶纔有權限修改別人的密碼。

-e選項能強制用戶下次登錄時修改密碼。

如果需要爲系統中大量用戶修改密碼,chpasswd命令可以事半功倍。chpasswd命令能從標準輸入自動密碼對(由冒號分割)列表,給密碼加密,然後爲用戶賬戶設置。

chsh、chfn和chage

此三個工具專門用來修改特定的賬戶信息。

chsh用來修改默認的用戶登錄shell。使用時必須用shell的全路徑名作爲參數。

chsh -s /bin/zsh username

chfn命令提供了在/etc/passwd文件的備註字段中存儲信息的標準方法。

chage命令用來幫助管理用戶賬戶的有效期。你需要對每個值設置多個參數

參數 描述
-d 設置上次修改密碼到現在的天數
-E 設置密碼過期的日期
-I 設置密碼過期到鎖定賬戶的天數
-m 設置悠 密碼之間最少要多少天
-W 設置密碼過期前多久天開始出現提醒信息

chage命令的日期值 可以用下面兩咱方式的任意一種:

  • YYYY-MM-DD格式的日期
  • 代表從1970年1月1日到該 日期天數的數值

使用Linux組

/etc/group文件

和UID一樣,GID在分配 時也採用了特定的格式。系統賬戶用的組通常會分配低於500的GID值。而用戶組的GID則會從500開始分配。

/etc/group文件有4個字段:

  • 組名
  • 組密碼
  • GID
  • 屬於該 組的用戶列表

組密碼允許非組內成功通過它臨時成爲該 組成員。

創建新組

groupadd命令可以在系統上創建新組

修改組

組需要修改的信息不多。groupmod命令可以修改已有組的GID(加-g選項)或組名(加-n選項)

理解文件權限

使用文件權限符

ls可以用來查看Linux系統上的文件,目錄和設備的權限

輸出的第一個字段就是描述文件和目錄權限的編碼。

  • -代表文件
  • d代表目錄
  • l代表鏈接
  • c代表字符型設備
  • b代表塊設備
  • n代表網絡設備

之後有3組三字符的編碼。每一組定義了3種訪問權限:

  • r代表對象是可讀的
  • w代表對象是可寫的
  • x代表對象是可執行的

若沒有某種權限,在該權限位會出現單破折線。這三組權限分別對應3個安全級別

  • 對象的屬主的權限
  • 對象的屬組的權限
  • 系統其它用戶的權限

默認文件權限

umask命令用來設置所創建文件和目錄的默認權限。

umask是一個掩碼。它會屏幕掉不想授予該 安全級別的權限。

要把umask值從對象的全權限值 中減掉。對文件來說,全權限的值是777;而對目錄來說,則是666。所以要看明白默認權限需要使用全權限減去umask的值 。

改變安全性設置

改變權限

chmod options mode file

chmod參數可以使用八進制模式或符號 模式進行安全性設置。

e.g.

chmod 760 newfile

另一種方式:符號模式

ugoa ±= rwxXstugo…

第一組字符定義了權限的作用對象:

  • u代表用戶
  • g代表組
  • o代表其它
  • a代表所有

第二組:

  • +代表增加權限
  • -代表移除權限
  • =將權限設置成後面的值

第三組代表做得到設置對象上的權限。除rwx之外的意思

  • X:如果對象是目錄或者它已有執行權限,賦予執行權限
  • s: 運行時重新設置UID或GID
  • t: 保留文件或目錄
  • u: 將權限設置爲跟屬主一樣
  • g: 將權限設置爲跟屬組一樣
  • o:將權限設置爲跟其他用戶一樣

改變所屬關係

chown

chown options owner [ .group] file

共享文件

Linux每戶上共享文件的方法是創建組。

Linux爲每個文件和目錄存儲了3個額外的信息位

  • 設置用戶ID(SUID): 當文件被用戶使用時,程序會以文件屬主的權限運行
  • 設置組ID(SGID):對文件來說,程序會以文件屬組的權限運行;對目錄來說,目錄中創建的新文件會以目錄的默認屬組作爲默認屬組
  • 粘着位:進程結束後文件還駐留(粘着)在內存中

要創建一個共享目錄,使目錄裏的新文件都能沿用目錄的屬組,只需要將該目錄的SGID位置位打開

chmod g+s dirname

管理文件系統

探索Linux文件系統

基本的Linux文件系統

ext文件系統

Linux最初採用的是一種簡單的文件系統,它模仿了Unix的文件系統的功能。

使用虛擬目錄來操作硬件設備,在物理設備上按定長的塊來存儲數據。

ext文件系統採用名爲索引節點的系統來豐放虛擬 目錄中所存儲文件的信息。索引 節點系統在每個物理設備中創建 一個單獨的表來存儲這些文件的信息。ext文件系統名稱中的extended部分來自其跟蹤的每個文件的額外數據,包括:

  • 文件名
  • 文件大小
  • 文件的屬主
  • 文件的屬組
  • 文件的訪問權限
  • 指向豐有文件數據的每個硬盤塊的指針

Linux通過唯一數據(稱作索引節點號)來引用索引節點表中的每個索引節點,這個值是創建文件時由文件系統分配 的。文件系統通過索引節點爲號而不是文件全名及路徑 來標識 文件。

ext2文件系統

ext2的索引節點表爲文件添加了創建時間值,修改時間值 和最後訪問時間值 來幫助系統管理員追蹤文件的訪問情況。ext2文件系統還將允許最大文件大小增加到了2TB(在ext2後期的版本中增加到了32TB)

除了擴展索引節點表外,ext2文件系統還改變了文件在數據塊中存儲的方式。保存文件時,ext2文件系統通過按 組分配磁盤塊來減輕碎片化。通過將數據塊組組,文件系統在讀取文件時不需要爲數據塊查找整個物理設備。

日誌文件系統

日誌文件系統爲Linux系統增加了一層安全性。它不再使用之前先將數據寫入存儲設備再更新索引節點表的做法,而是先將文件的更改寫入到臨時文件(稱作日誌,journal)中。在數據成功寫到存儲設備和索引節點表之後,再刪除對應的日誌條目。

Linux中有3種廣泛使用的日誌方法:

方法 描述
數據模式 索引節點和文件都會被寫入日誌;丟失數據風險低,但性能差
有序模式 只有索引節點數據會被寫入日誌,但只有數據成功寫入後才刪除;在性能和安全性之間取得了良好的折中
回寫模式 只有索引節點數據會被寫入日誌,但不控制文件數據何時寫入;丟失數據風險高,但仍比不用日誌好。
ext3文件系統

默認情況下ext3採用了有充模式的日誌功能。

ext4文件系統

ext3的基礎上支持了數據加密,還支持區段的特性(區段在存儲設備上按塊分配空間,但在索引節點表中只保存塊起始位置。)

ext4還引入了塊預分配技術。

Reiser文件系統
JFS文件系統
XFS文件系統

寫時複製文件系統

copy-on-write

ZFS文件系統

ZFS是一個穩定 的文件系統,與Resier4,Btrfs和ext4勢均力敵。它最大的弱項就是沒有使用GPL許可。自2013年發起的OpenZFS項目有可能改變這種書面。但是,在獲得GPL許可之前,ZFS有可能終無法成爲Linux默認的文件系統。

Btrf文件系統

也被稱爲B樹文件系統。

特點:穩定性,易用性以及能夠動態調整已掛載文件系統的大小。

操作文件系統

創建分區

fdisk工具來幫助管理安裝在系統上的任何存儲設備,但得具有Root權限。

fdisk主要命令

命令 描述
a 設置活動分區標誌
b 編輯BSD Unix系統用的磁盤標籤
c 設置DOS兼容標誌
d 刪除分區
l 顯示可用的分區類型
m 顯示命令選項
n 添加一個新分區
o 創建DOS分區表
p 顯示當前分區表
q 退出,不保存更改
s 爲Sun Unix系統創建
t 修改分區的系統ID
u 改變使用的存儲單位
v 驗證分區表
w 將分區表寫入磁盤
x 高級功能

創建文件系統

在將數據存儲到分區之前,你必須用某種文件系統對其進行格式化,這樣Linux才能使用它。每種文件系統類型都有自己的命令行程序來格式化分區。

工具 用途
mkefs 創建一個ext文件系統
mke2fs 創建一個ext2文件系統
mkfs.ext3 創建一個ext3文件系統
mkfs.ext4 創建一個ext4文件系統
mkreiserfs 創建一個ReiserFS文件系統
jfs_mkfs 創建一個JFS文件系統
mkfs.xfs 創建一個XFS文件系統
mkfs.zfs 創建一個ZFS文件系統
mkfs.btrfs 創建一個Btrfs文件系統

文件系統的檢查與修復

fsck options filesystem

fsck能檢查和修復大部分類型的Linux文件系統。文件系統可以通過設備名,在虛擬目錄中的掛載點以及分配給文件系統的唯一UUID值來引用。

fsck的命令行選項:

選項 描述
-a 如果檢測到錯誤,自動覆文件系統
-A 檢查/etc/fstab文件中列出的所有文件系統
-C 給支持進度條功能的文件系統顯示一個進度條
-N 不進行檢查,只顯示哪些檢查會執行
-r 出現錯誤時提示
-R 使用-A選項時路過根文件系統
-s 檢查多個文件系統時,依次進行檢查
-t 指定要檢查的文件系統類型
-T 啓動時不顯示頭部信息
-V 在檢查時產生詳細輸出
-y 檢測到錯誤 時自動 修改文件系統

fsck只能在未掛載的文件系統上運行。對大多數文件系統來說,你只需要卸載文件系統來進行檢查,檢查完成 之後重新掛載就好了。但是因爲根文件系統含有所有核心的Linux命令和日誌文件,所以你無法在處理於運行狀態的系統上卸載它。這時你可以使用Linux LiveCD。

邏輯卷管理

如果用標準分區在硬盤 上創建了文件系統,爲已有文件系統添加額外的空間多少是一種痛苦的體驗。你只能在同一個物理硬盤的可用空間範圍內調整分區大小。如果 硬盤上沒有地方了,你就必須弄一個更大的硬盤,然後手動將已有的文件系統移動到新的硬盤上。

這時候可以通過將另外一個硬盤 上的分區加入已有文件系統,動態地添加存儲空間。Linux邏輯卷管理器(logical volumn manage LVM)軟件下好可以用來做這個。

邏輯卷管理佈局

邏輯卷管理的核心在於如何處理安裝在系統上的硬盤 分區。在邏輯卷管理的世界裏,硬盤 稱作物理卷(physical volumn, PV)。每個物理卷都會映射到硬盤 上特定的物理分區。

多個物理卷集中在一起可以形成一個卷組(volume group, VG)。邏輯卷管理系統將卷組視爲一個物理硬盤,但事實 上卷組可能是由分佈在多個物理硬盤 上的多個物理分區組成的。卷組提供了一個創建邏輯分區的平臺,而這些邏輯分區則包含了文件系統

整個結構中的最後一層是邏輯卷(logical volume,LV)邏輯卷爲Linux提供了創建文件系統的分區環境,作用類似於到目前爲止我們一直在探討 的Linux中的物理硬盤分區。Linux系統將邏輯卷視爲物理分區。

Linux中的LVM

Linux LVM有兩個可用的版本: LVM1, LVM2

快照

最初的Linux LVM允許你在邏輯卷在線的狀態 下將其複製到另一個設備。

條帶化

LVM2提供,條帶化,可跨多個物理硬盤創建邏輯卷。當LinuxLVM將文件寫入邏輯卷時,文件中的數據塊會被分散到多個硬盤上。每個後繼數據塊會被寫到下一個硬盤上。

條帶化有助於提高硬盤性能。因爲Linux可以將一個文件的多個數據塊同時寫入多個硬盤而無需等待單個硬盤移動讀寫磁頭到多個不同位置。

鏡像

LVM鏡像是一個實時更新的邏輯卷的完整副本。

使用Linux LVM

  1. 定義物理卷

    創建過程的第一步就是將硬盤上的物理分區轉換成Linux LVM使用的物理卷區段。在創建了基本的Linux分區後,你需要通過t命令改變分區的類型。

    fdisk /dev/sdX

    t

    8e

    p

    w

    q

    下一步是用分區來創建實際的物理卷。可以通過pvcreate命令

    sudo pvcreate /dev/sda1

    如果你想查看創建進度的話,你可以使用pvdisplay命令來顯示已創建的物理卷列表

    sudo pvdisplay /dev/sda1

  2. 創建卷組

    vgcreate命令

    sudo vgcreate Vol1 /dev/sdb1

    vgdisplay Vol1

  3. 創建邏輯卷

    Linux系統使用邏輯捲來模擬物理分區,並在其中保存文件系統。Linux系統會像處理物理分區一個處理邏輯卷,允許你定義邏輯卷中的文件系統,然後將文件系統掛載到虛擬目錄上。

    要創建邏輯卷,使用lvcreate命令,lvcreate命令的選項如下:

選項 長選項名 描述
-c –chunksize 指定快照邏輯卷的單位大小
-C –contiguous 設置或重置連續分配策略
-i –stripes 指定條帶數
-I –stripesize 指定每個條帶的大小
-l –extents 指定分配給新邏輯卷的邏輯區段數,或者要用的邏輯區段的百分比
-L –size 指定分配給新邏輯卷的硬盤大小
–mirror 指定的次設備號
-m –mirrors 創建邏輯卷鏡像
-M –persistent 讓次設備號一直有效
-n –name 指定新邏輯卷的名稱
-p –permission 爲邏輯卷設置讀/寫權限
-r –readahead 設置預讀扇區數
-R –regionsize 指定將鏡像分成多大的區
-s snapshot 創建快照邏輯卷
-Z –zero 將新邏輯卷的前1KB數據設置爲零

e.g.

sudo lvcreate -l 100%FREE -n lvtest Vol1

  1. 創建文件系統

    sudo mkfs.ext4 /dev/Vol1/lvtest

  2. 修改LVM

    Linux LVM常用命令

    命令 功能
    vgchange 激活和禁用卷組
    vgremove 刪除卷組
    vgextend 將物理卷加到卷組中
    vgreduce 從卷組中刪除物理卷
    lvextend 增加邏輯卷的大小
    lvreduce 減小邏輯卷的大小

安裝軟件程序

包管理基礎

PMS(package Management System, PMS)會利用一個數據庫來記錄各種相關內容:

  • Linux系統上已安裝了什麼軟件包
  • 每個包安裝了什麼文件
  • 每個已安裝軟件包的版本

基於debian的系統

dpkg命令是Debian每戶PMS的工具的核心。包含在這個PMS中的其他工具有:

  • apt-get
  • apt-cache
  • aptitude

使用apt管理軟件包

基於Red Hat的系統

yum

從源碼安裝

使用編輯器

vim編輯器

nano編輯器

emacs編輯器

KDE系統編輯器

KWrite編輯器

Kate編輯器

GNOME編輯器

gedit

Shell腳本編程基礎

構建基本腳本

使用多個命令

shell腳本的關鍵在於輸入多個命令並處理每個命令的結果,甚至需要將一個命令的傳給另一個命令。shell可以讓你將多個命令串起來,一次執行完成。如果兩個命令一起運行,可以把它們放在同一行中,彼此間用分號隔開。

創建shell腳本

在創建shell腳本文件時, 必須在文件的第一行指定要使用的shell,格式爲:

#!/bin/bash

shell除第一行外不會解釋#開頭的行

顯示消息

大多數shell命令都會產生自己的輸出。這些輸出會顯示在腳本所運行的控制檯顯示器上。你可能想要添加自己的文本消息來告訴用戶腳本 正在做什麼。可以通過echo命令來實現這一點

echo this is a message

默認情況下,不需要使用引號將要顯示的文本字符串劃定出來。但有時在字符串中出現引號的話就比較麻煩了。你需要使用另一種引號把字符串劃定起來。

如果想把文本字符和命令輸出顯示在同一行中,可以使用echo語句的-n參數。

使用變量

環境變量

在腳本中,你可以在環境變量前加上($)來使用這些系統環境變量。

但你如果想顯示,那麼則需要在前加一個\

用戶變量

除了環境變量,shell腳本還允許在腳本中定義和使用自己的變量。

用戶變量可以是任何由字母,數字,下劃線組成的文本字符串,長度不超過20個。

使用等號將值賦給用戶變量。在變量,等號和值之間不能出現空格。

shel腳本會自動決定變量值的數據類型。在腳本 的整個生命週期裏,shell腳本中定義的變量會一直保持着它們的值,但在shell腳本結束時會被刪除掉。

與系統變量類似,用戶變量可通過美元符號引用。

命令替換

shell腳本中最有用的特性之一就是可以從命令輸出中提取信息,並將其賦值給變量。把輸出賦給變量後,就可以隨意在腳本中使用了。這個特性在處理腳本數據時尤爲方便。

有兩種方法可以將命令輸出賦值給變量:

  • 反引號字符(`)
  • $()格式

e.g.

testing=date

testing-$(date)

重定向輸入和輸出

輸出重定向

最基本的重定向將命令的輸出發送到一個文件中。bash shell 用大於號(>)來完成這項功能。

command > outputfile

輸入重定向

輸入重定向將誶折內容重定向到命令,而非將命令的輸出重定向到文件。使用(<)符號:

command < inputfile

e.g.

$ wc < testfile
	2	11	60

wc命令可以對數據文本進行計數。默認它會給出3個值:

  • 文本的行數
  • 文本的詞數
  • 文本的字節數
內聯輸入重定向

這種方法無需使用文件進行重定向,只需要在命令行中指定用於輸入 重定向的數據就可以了。

內聯輸入重定向符號是遠於小號(<<)。除了這個符號,你必須指定一個文本標記來劃分輸入數據的開始和結尾。任何字符串都可以作爲文本標記,但在數據的開始和結尾文本必須一致。

e.g.

$ wc << EOF
>  test one 
>  test two
>  test three
>  EOF

管道

有時需要將一個命令的輸出作爲另一個命令的輸入。可以使用重定向來實現,只是有些笨拙。可以使用管道操作符(|)

command1 | command2

管道操作符兩邊的命令會同時運行。在系統內部將它們連接起來。在第一個命令產生輸出的同時,輸出會被立即送給第二個命令。數據傳輸不會用到任何中間文件或緩衝。

執行數學運算

在shell中執行數據運算比較麻煩,可以使用兩種途徑來進行

expr命令

e.g.

$ expr 1 + 5

6

expr命令的操作符

操作符 描述
ARG1 | ARG2 如果ARG1媽不是null也不是零值,返回ARG1,否則返回ARG2
ARG1 & ARG2 如果沒有參數是null或零值,返回ARG1, 否則返回0
ARG1 < ARG2 如果ARG1小於ARG2,返回1,否則 返回0
ARG1 <= ARG2 如果 ARG1小於或等於ARG2返回1,否則返回0
ARG1 = ARG2 如果ARG1等於ARG2 返回1,否則返回0
ARG1 != ARG2 如果ARG1不等於ARG2返回1,否則返回0
ARG1 >= ARG2 如果ARG1大於等於ARG2返回1,否則返回0
ARG1 > ARG2 如果ARG1大於ARG2返回1,否則返回0
ARG1 + ARG2 返回ARG1和ARG2的合
ARG1 - ARG2 返回ARG1各ARG2的算術運算差
ARG1 * ARG2 返回ARG1和ARG2的算術乘積
ARG1 /ARG2 返回ARG1和ARG2的算術商
ARG1 % ARG2 返回ARG1被ARG2除的算術餘數
ARG1 : ARG2 如果REGEXP匹配到了STRING中的某個模式,返回該 模式匹配
match STRING REGEXP 如果REGEXP匹配到了STRING中的某個模式,返回該模式匹配
substr STRING POS LENGTH 返回起始位置爲POS(從1開始計數),長度爲THLENGH個字符的子字符串
index STRING CHARS 返回在STRING中找到CHARS字符串的位置;否則返回0
length STRING 返回字符串STRING的數值長度
+ TOKEN 將TOKEN解釋成字符串,即使是個關鍵字
(EXPRESSION) 返回EXPRESSION的值

儘管標準操作符在expr命令中工作得很好,但在腳本 或命令行上使用它們時仍有問題出現。許多expr命令的操作符在shell中另有含義(比如星號)。當它們出現在expr命令中時,會得到一些詭異的結果。

要解決這樣的問題,需要對那些容易被shell錯誤解釋的字符,在它們傳入expr命令之前進行轉義。

但是在shell中使用expr命令也同樣複雜。

使用方括號

在bash中,在將一個數學運算結果賦給某個變量時,可以用美元符和方括號($[ operation ])將數學表達式圍起來。

浮點解決方案

有幾種解決方案能夠克服bash中數學運算的整數限制。最常見的方案是用內建的bash計算器, 叫做bc.

bc的基本用法

bash計算器能夠識別:

  • 數字(整數和浮點數)
  • 變量(簡單變量和數組)
  • 註釋(以#或c語言中的/* */開始的行)
  • 表達式
  • 編程語句(例如 if -then語句)
  • 函數
在腳本中使用bc

variable=$(echo “options; expression” | bc)

e.g.

#!/bin/bash
var1=$(echo "scale=4; 3.44 / 5" | bc)
echo The answer is $var1

退出腳本

shell中運行的每個命令都使用退出狀態碼(exit status)告訴shell它已經運行完畢。退出狀態碼是一個0~255的整數值,在命令結束運行時由命令傳給shell。可以捕獲這個值 並在腳本中使用

查看退出狀態碼

Linux提供了一個專門的變量$?來保存上個已執行命令的退出狀態碼。

按照慣例,一個成功結束的命令的退出狀態碼是0.如果一個命令結束時有錯誤,退出狀態碼就是一個正數值。有一些參考:

狀態碼 描述
0 命令成功結束
1 一般性未知錯誤
2 不適合的shell命令
126 命令不可執行
127 沒找到命令
128 無效的退出參數
128+x 與Linux信號x相關的嚴重錯誤
130 通過Ctrl + C終止的命令
255 正常範圍之個的退出狀態碼

exit命令

默認情況下,shell腳本會以腳本中最後一個命令的退出狀態碼退出。

你可以改變這種默認行爲,返回自己的退出狀態碼。exit命令允許你在腳本結束時指定一個退出狀態碼

e.g.

$ exit 5

使用結構化命令

使用if-then語句

if command 
then 
	commands
fi

if後面的那個命令執行成功,位於then部分的命令就會被執行。如果該命令的退出狀態碼是苊值。then部分的命令就不會被執行。

if-then-else語句

if command 
then
	commands
else 
	commands
fi

嵌套if

if command1
then
	commands
elif command2
then
	more commands
fi

test命令

test condition

數值比較

test命令的數值比較功能

比較 描述
n1 -eq n2 檢查n1是否與n2相等
n1 -ge n2 檢查n1是否大於或等於n2
n1 -gt n2 檢查n1是否大於n2
n1 -le n2 檢查n1是否小於或等於n2
n1 -lt n2 檢查n1是否小於n2
n1 -ne n2 檢查n1是否不等於n2

e.g.

value = 6
if [ $value -gt 5 ]
then
	echo "The test value $value is greater than five"
fi

字符串比較

條件測試還允許比較字符串值。比較字符串比較煩瑣,常用測試:

比較 描述
str1 = str2 檢查str1是否和str2相同
str1 != str2 檢查str1是否和str2不同
str1 < str2 檢查str1是否比str2小
str1 > str2 檢查str1是否比str2大
-n str1 檢查str1的長度是否非0
-z str1 檢查str1的長度是否爲0
字符串相等性

在比較字符串的相等性時,比較測試會將所有的標點和大小寫情況都考慮在內。

字符串順序

問題:

  1. 大於號和小於號必須轉義,否則shell會把它們當作重定向符號,把字符串值當作文件名;
  2. 大於和小於順序和sort命令所採用的不同:在比較測試中,大寫字母被認爲是小於小寫字母的。但sort命令卻恰好相反。原因是比較測試中使用的是標準的ASCII順序,根據每個字符的ASCII數值來決定排序結果,sort命令使用的是系統本地化語言設置中定義的排序順序。
字符串大小

-n 和 -z可以檢查一個變量是否含有數據

文件比較

test命令的文件比較功能:

比較 描述
-d file 檢查目標是否存在並是一個目錄
-e file 檢查目標是否存在
-f file 檢查是否存在並是一個文件
-r file 檢查目標是否存在並可讀
-s file 檢查目標是否存在並非空
-w file 檢查目標是否存在並可寫
-x file 檢查目標是否存在並可執行
-O file 檢查目標是否存在 並屬於當前用戶
-G file 檢查目標是否存在並默認組與當前用戶相同
file1 -nt file2 檢查file1是否比file2更新
file1 -ot file2 檢查file1是否比file2舊

複合條件測試

if-then語句允許你使用布爾值邏輯來組合測試。有兩種布爾值值運算符可用:

  • [ condition1 ] && [ condition2 ]

    兩種條件必須完全滿足

  • [ condition1 ] || [ condition2 ]

    兩種條件只需滿足一種

if-then的高級特性

  • 用於數學表達式的雙括號
  • 用於高級字符串處理功能的雙方括號

使用雙括號

雙括號命令允許你在比較過程中使用高級數學表達式。test命令只能大比較中使用簡單的算術操作。雙括號命令提供了更多 多的數學符號,這些符號對於用過其他編程語言的程序員而言並不陌生,格式如下:

(( expression ))

雙括號命令符號:

符號 描述
val++ 後增
val– 後減
++val 先增
–val 先減
! 邏輯求反
~ 位求反
** 冪運算
<< 左位移
>> 右位移
& 位布爾和
| 位布爾或
&& 邏輯和
|| 邏輯或

使用雙方括號

雙方括號提供了針對字符串比較的高級特性,格式如下:

[[ expression ]]

雙方括號裏的expression使用了test命令中採用的標準字符串比較。但它提供了test命令未提供的另一個特性——模式匹配(pattern matching).

在模式匹配中,可以定義一個正則表達式來匹配字符串的值

e.g.

#!/bin/bash
if [[ $USER == R* ]]
then
	echo "Hello $USER"
else
	echo "Sorry, I don't know you"
fi

case命令

有了case命令,就不需要再寫出所有的elif語句來不停地檢查同一個變量的值了。格式如下:

case variable in

pattern1 | pattern2) commands1;;

parrtern3) commands2;;

*) default commands;;

esac

更多結構化命令

for命令

for命令允許你創建一個遍歷一系統值 的循環。

基本格式:

for var in list

do

​ commands

done

讀取列表中的值

e.g.

for test in Alabama Alaska Arizona Arkansas
do
	echo "The next state is $test"
done

讀取列表中的複雜值

e.g.

for test in I don't know if this'll work
do
	echo "word:$test"
done
---
word:I
word:dont know if thisll
word:work

shell看到了列表值中的單引號並嘗試使用它們來定義一個單獨的數據值。

有兩種辦法解決這個問題:

  • 使用轉義字符來將單引號轉義
  • 使用雙引號來定義用到單引號的值

從變量讀取列表

從命令讀取值

e.g.

#!/bin/bash
file = "states"
for state in $(cat $file)
do
	echo "Visit beautiful $state"
done

更改字段分隔符

造成這個問題的原因是特殊的環境變量IFS, 叫作內部字段分隔符(internal field separator).IFS環境變量定義了bash shell用作字符分隔符的一系列字符。默認情況下,bash shell會將下列字符當作字段分隔符。

  • 空格
  • 製表符
  • 換行符

如果bash shell在數據中看到了這些字符中的任意一個,它就會假定這表明列表 中一個新數據字段的開始。在處理可能含有空格的數據(比如文件名)時,這空運 非常麻煩。

要解決這個問題,可以在shell腳本中臨時更改IFS環境變量的值來限制被bash shell當作字段分隔符的字符。

IFS=$"\n"

將這個語句加入到腳本中,告訴bash shell在數據值中忽略空格和製表符。

用通配符讀取目錄

最後,可以用for命令來自動遍歷目錄中的文件。進行操作時,必須在文件名或路徑名中使用通配符。它會強制shell使用文件擴展配置。文件擴展匹配是生成匹配指定通配符的文件名或路徑名的過程。

e.g.

#!/bin/bash
# iterate through all the files in a directory

for file in /home/*
do
	fi [ -d "$file"]
	then 
		echo "$file is a directory"
	elif [ -f "$file"]
	then
		echo "$file is a file"
	fi
done

C語言風格的for命令

for (( variable assignment ; condition ; iteration process))

e.g.

for (( a = 1; a < 10; a++))

注意:

  • 變量賦值可以有空格;
  • 條件中的變量不以美元符開頭
  • 迭代過程的算式未用expr命令格式

使用多個變量

C語言風格的for命令也允許爲迭代使用多個變量。循環會單獨處理每個變量,你可以爲每個變量定義不同的迭代過程。儘管可以使用多個變量,但你只能在for循環中定義一種條件。

for (( a = 1, b = 10; a <-10; a++, b--))

while命令

while命令某種單方上是if-then語句和for循環的混雜體。格式如下:

while test command 
do
	other commands
done

while命令定義了每次迭代時檢查的測試條件成立性。

使用多個測試命令

while命令允許你在while語句行定義多個測試命令。只有最後一個測試命令的退出狀態 碼會被用來決定什麼時候結束循環。

util命令

util命令和while命令工作的方式完全相反。util命令要求你指定一個通常返回非零退出狀態碼的測試命令。只有測試命令的退出狀態碼不爲0,bash shell纔會執行循環中列出的命令。一量測試命令返回了退出狀態碼0,循環就結束了。

until test commands
do
	other commands
done

和while類似,你可以在util命令語句中放入多個測試命令。只有最後一個命令的退出狀態碼決定了bash shell是否執行已定義的other comands。

嵌套循環

循環語句可以在循環內使用任意類型的命令,包括其他循環命令。這種循環叫做嵌套循環。

循環處理文件數據

通常必須遍歷存儲在文件中的數據。這要求結合已經進過的兩種技術:

  • 使用嵌套循環
  • 修改IFS環境變量

典型的例子就是處理/etc/passwd文件中的數據。這要求你逐行遍歷/etc/passwd文件。並將IFS變量的值改成冒號,這樣就能分隔開每行中的各個字段值了。

#!/bin/bash
# change this IFS Value
IFS.OLD = $IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
	echo "Values in $entry -"
	IFS=:
	for value in $entry
	do
		echo "	$value"
	done
done

控制循環

如果不能控制循環,那麼一旦啓動了循環,就必須等待循環完成所有迭代纔會停止。

有兩個命令能幫助我們控制循環內部的情況:

  • break
  • continue

break命令

break命令是退出循環的一個簡單方法。可以使用break命令來退出任意類型的循環。

  • 單層循環

  • 內部循環

  • 外部循環

    語法:

    break n  #其中n指定了要跳出的循環層級。默認情況下n爲1,表明跳出的是當前的循環。如果你將n設爲2,break命令會停止下一級的外部循環。
    

continue

continue命令可以提前中止某次循環中的命令,但並不會完全終止整個循環。

處理循環的輸出

在shell腳本中你可以對循環的輸出使用管道或進行重定向。這可以通過在done命令之後添加一個處理命令來實現

for file in /home/rich/*
do
	if [ -d "$file"]
	then
		echo "$file is a directory"
	elif
		echo "$file is a file"
	fi
done > output.txt

處理用戶輸入

命令行參數

向shell腳本傳遞數據的最基本方法是使用命令行參數。命令行參數允許在運行腳本時向命令行添加數據。

e.g.

$ ./addem 10 30

讀取參數

bash shell會將一些稱爲位置參數的特殊變量分配 給輸入到命令行中的所有參數。這也包括shell所執行的腳本名稱。公交車參數變量是標準的數字:

  • $0: 程序名

  • $1: 第一個參數

  • $2: 第二個參數

    直到第九個參數$9

如果腳本需要的命令行參數不止9個,你仍然可以處理,但是需要稍微修改一下變量名。在第9個變量之後,你必須在變量數字周圍加上花括號,比如${10}。

讀取腳本名

使用$0參數獲取shell在命令行啓動的腳本名。

當傳給$0變量的實際字符串不僅僅是腳本名,而是完整的腳本路徑時,變量$0變會使用整個路徑。

e.g.

$ bash /home/Christine/test.sh
The zero paramter is set to : /home/Christine/test.sh

測試參數

當腳本認爲參數變量中會有數據而實際上並沒有時,腳本很有可能會產生錯誤消息。這種寫腳本的方法並不可取。在使用參數前一定要檢查其中是否存在數據。

e.g.

#!/bin/bash

if [ -n "$1" ]
then
	echo Hello $1.
else
	echo "Sorry, you did not identify yourself"
fi

我們可以使用-n測試來檢測命令行參數$1中是否有數據。

特殊參數變量

參數統計

特殊變量$#含有腳本運行時攜帶的命令行參數的個數。可以在腳本中任何地方使用這個特殊變量。

抓取所有的數據

*和@變量可以用來輕鬆訪問所有參數。

KaTeX parse error: Expected 'EOF', got '\*' at position 1: \̲*̲變量會將命令行上提供的所有參數…*變量會將這些參數視爲一個整體,而不是多個個體。

而$@變量會將命令行上提供的所有參數當作同一字符串中的多個獨立的單詞。這樣就能夠遍歷所有的參數值,得到每個參數了。

移動變量

bash shell工具箱中另一件工具是shift命令。它能夠用來操作命令行參數。shift命令會根據它們的相對位置來移動命令行參數。

在默認情況下,它會將每個參數變量向左移動一個位置。所以變量$3的值會移到$2, 變量$2的值會移到$1, 而變量$1的值則會被刪除。而$0的值則不會變。

處理選項

查找選項

命令行選項(是跟在單破折線後面的單個字母,它能改變命令的行爲),可以像處理命令行參數一樣處理命令行選項。

  1. 處理簡單選項

    你可以使用處理腳本 程序攜帶的命令行參數一樣處理命令行選項。

    如在提取每個單獨參數時,使用case語句來判斷某個參數是否爲選項。

  2. 分離參數和選項

    shell中會有同時使用選項和參數的情況。Linux中處理這個問題的標準方式是用特殊字符來將二者分開。如–

  3. 處理帶值的選項

使用getopt命令

getopt命令是一個在處理命令行選項和參數時非常方便的工具。它能夠識別命令行參數。

  1. 命令的格式

    getopt命令可以接受一系列任意形式的命令行選項和參數,並自動將它們轉換成適當 的格式。命令格式如下:

    getopt optstring parameters

  2. 在腳本中使用getopt

    set – (getoptqab:cd&quot;(getopt -q ab:cd &quot;@")

getopt命令並不擅長處理帶空格和引號的參數值。它會將空格當用參數分隔符,而不是根據雙引號將二者當作一個參數。

使用更高級的getopts

getopts內建於bash shell。 它跟近親getopt看起來很像,但多了一些擴展功能。

與getopt不同,前者將命令行上選項和參數處理後只生成一個輸出,而getopts命令能夠和已有的shell參數變量配合默契。

每次調用 它時,它一次只處理命令行上檢測到的一個參數。處理完所有的參數後,它會退出並個大於0的退出狀態碼。這讓它非常適合解析命令行所有的參數的循環中。

getopts後面的字符串就是可以使用的選項列表,每個字母代表一個選項,後面帶:意味着選項除了定義本身之外,還會帶上一個參數作爲選項的值,getopts字符串中沒有跟隨:的是開關型選項,不需要再指定值,相當於true/false,只要事字這個參數就是true。如果命令行中包含了沒有在getopts列表中的選項,會有警告信息,如果在整個getopts字符串加上一個:,就能消除警告信息了。

格式如下:

gettopts [optstring[:]][descrition] variable

  • optstring: 表示爲某個腳本可以使用的選項
  • “:”: 如果某個選項(optstring)後面出現了冒號,則表示這個選項後面可以接參數(即一段描述信息description)
  • variable: 表示將某個選項保存在變量variable中
    getopts會用到兩個環境變量。如果需要跟一個參數值,OPTARG環境變量就會保存這個值。OPTIND環境變量保存了參數列表中getopts正在處理的參數位置。這樣你就能在處理完選項這後繼續處理其他命令行參數了。
  • OPTARG: 就是將選項後面的參數或者描述信息保存在這個變量中
  • OPTIND:這個表示命令行的下一個選項或參數的索引(文件名不算選項或參數)。
    e.g.
#!/bin/bash
echo $*
while getopts ":a:bc:" opt
do
    case $opt in
        a)
        echo $OPTARG $OPTIND;;
        b)
        echo "b $OPTIND";;
        c)
        echo "c $OPTIND";;
        ?)
        echo "error"
        exiit 1;;
    esac
done
echo $OPTIND
shift $(( $OPTIND -))
echo $0
echo $*

執行結果如下:

sh getopts.sh -a 11 -b -c 6

-a 11 -b -c 6
11 3
b 4
c 6
6
getopts.sh

解釋:

  • while getopts “🅰️bc:" opt # 第一個冒號表示忽略錯誤;字符後面的冒號表示該 選項必須有自己的參數。
  • $OPTARG 存儲相應選項的參數,如上例中的11, 6
  • OPTIND總是存儲原始$*中下一個要處理的選項(不是參數,而是選項,此處指的是a,b,c這三個選項,而不是那些數字,當然數字也是會佔有位置的)的位置。
getopts與getopt的區別
  • getopts是shell內建的命令,getopt是一個獨立外部工具
  • getopts的使用語法簡單,而getopt使用語法較爲複雜
  • getopts不支持長參數,getopt支持
  • getopts不會重排所有參數的順序,而getopt會
  • getopts出現的目的是爲了代替getopt較快捷的執行參數分析工作

將選項標準化

在創建shell腳本時,你完全可以決定用哪些字母選項以及它們的用法。但有些字母選項在Linux世界裏已經擁有了某種程度的標準含義。如果你能在shell腳本中支持這些選項,腳本看起來能更友好一些。
下面顯示了Linux中用到的一些命令行選項有常用含義:

選項 描述
-a 顯示所有對象
-c 生成一個計數
-d 指定一個目錄
-e 擴展一個對象
-f 指定讀入數據的文件
-h 顯示命令的幫助信息
-i 忽略文本大小寫
-l 產生輸出的長格式版本
-n 使用非交互模式
-o 將所有輸出重定向到指定的輸出文件
-q 以安靜模式運行
-r 遞歸地處理目錄和文件
-s 以安靜模式運行
-v 生成詳細輸出
-x 排除某個對象
-y 對所有問題回答yes

獲得用戶輸入

比如你想要在腳本 運行時問個問題,等待運行腳本 的人來回答。bash shell爲此提供了read命令。

基本的讀取

read命令從標準輸入(通常是鍵盤)或另一個文件描述符中接受輸入。在收到輸入後,read命令會將數據放進一個變量。
e.g.

#!/bin/bash
#testing the read commannd
echo -n "Enter you name: "
read name
echo "Hello $name,  welcome to my program."

./test.shh
Enter you name: Rich
hello Rich, welcome to my proogram.

注意,生成提示的echo命令使用了-n選項,該 選項不會在字符串末尾輸出換行符。
實際上read命令包含了-p選項,允許你直接在read命令行指定提示符。

read -p "Please enter you age: " age

超時

使用read命令時要當心,腳本很可能會一直等待用戶輸入。如果不管是否有數據輸入,腳本都必須執行,你可以使用-t選項指定一個計時器。-t選項指定了read命令的等待輸入的秒數。當計時器過期後,read命令會返回一個非零的退出狀態碼。

隱藏方式讀取

有時你需要腳本從用戶處得到輸入,但又不在屏幕上顯示輸入信息,比如輸入密碼。你可以使用-s選項。(其實-s選項只是將文本顏色設置成 跟背景色一樣)

從文件中讀取

最後,也可以用read命令來讀取Linux系統上文件裏保存的數據。每次調用read都會從文件中讀取一行文本。當文件中沒有內容時,read命令會退出並返回非零狀態碼。
其中最難的部分是將文件中的數據傳給read命令,最常用的方法是對文件使用cat,將結果通過管理直接傳給含有read命令的while命令。
e.g.

#!/bin/bash
reading data from a file
count=1
cat  test | while read line
do
    echo "Line number: $line"
    count=$[ $count + 1]
done
echo  "Finished processing thhe file"

while循環會持續通過read命令處理文件中的行,直到read命令以非零退出狀態碼退出。

呈現數據

理解輸入和輸出

標準文件描述符

Linux將每個對象當作文件來處理。這包括輸入和輸出進程。Linux用文件描述符來標識每個文件對象。文件描述符是一個非負整數,可以唯一標識會話中打開的文件。每個進程一次最多可以有九個文件描述符。出於特殊目的,bash shell保留了前三個誰的描述符(0, 1, 2)
Linux的標準文件描述符:

文件描述符 縮寫 描述
0 STDIN 標準輸入
1 STDOUT 標準輸出
2 STDERR 標準錯誤
  1. STDIN
    STDIN文件描述符代表shell的標準輸入。對終端來說,標準輸入就是鍵盤。
    在使用輸入重定向符號(<)時,Linux會重定向指定的文件來替換標準輸入文件描述符。它會讀取文件並提取數據,就如同它是鍵盤上的鍵入一樣。
  2. STDOUT
    STDOUT文件描述符代表shell的標準輸出。在終端界面上,標準輸出就是終端顯示器。shell的所有輸出(包括shell中運行的程序腳本)會被定向到標準輸出,也就是顯示器。
    你也可以使用輸出重定向來改變(>)
  3. STDERR
    shell通過特殊的STDERR文件描述符來處理錯誤消息。STDERR文件描述符代表shell的標準錯誤輸出。默認,錯誤消息也會輸出到顯示器輸出中。但STDERR並不會隨着STDOUT的重定向而發生改變。

重定向錯誤

  1. 只重寫向錯誤

ls -all badfile 2> errorMsg

使用2>可以將錯誤重定向到指定文件或其它位置,這樣,錯誤消息就不會出現在屏幕上了。

  1. 重定向錯誤和數據
    如果想重定向錯誤和正常輸出,必須用兩個重定向符號。需要在符號前面放上待重定向數據所對應的文件描述符,然後指向用於保存數據的輸出文件。

ls -all testt test2 badfiile 2> faiiMsg 1> msg

  1. w全部重定向

ls -lah fiile badfile &> alllMsg

在腳本中重定向輸出

有兩種方法在腳本中重定向輸出:

  • 臨時重定向行輸出
  • 永久重定向腳本中的所有命令

臨時重定向

如果有意思在腳本中生成錯誤消息,可以將單獨的一行輸出重定向到STDERR。你所需要做的是使用輸出重定向符來將輸出信息重定向到STDERR文件描述符。在重定向到文件描述符時,你必須在文件描述符數字之前加一個&

echo "This is an error messagge " >&2

如果像平時一樣運行這個腳本,不會發生任何改變,因爲默認情況下,Linux會將STDERR導向STDOUT。但是,如果你在運行腳本時重定向了STDERR,腳本中所有導向STDERR的文本都會被重定向。

永久重定向

可以使用exec命令告訴shell在腳本執行期間重定向某個特定文件描述符。

exec 1> msg

exec命令會啓動一個新shell並將STDOUT文件描述符重定向到文件。腳本中發給STDOUT的所有輸出都會被重定向到文件msg

在腳本中重定向輸入

exec命令允許你將STDIN重定向到Linux系統的文件中:

exec 0< testfile

這個命令會告訴shell它應該從文件testfile中獲得輸入,而不是STDIN。這個重定向只要在腳本需要輸入時就會作用。

創建自己的重定向

創建輸出文件描述符

可以使用exec命令來給輸出分配文件描述符。和標準的文件描述符一樣,一旦將另一個文件描述分配給一個文件,這個重定向就會有一直有效,直到你重新分配。
e.g.

#!/bin/bashh
#usiing an alternative fiile descriptor

exec 3> test3out
echo "This should diispplay on  the monitor"
echo "and thhis shhould be shtoored in  the file" >&3
echo  "Then thhiis should  be  bac on thhe montoor"

$ ./test
This shhould display on thhe montor
Thhis thhiis shhould be back on thhe montoor

cat test3out
and this should be stored in the file

這個腳本用exec命令將文件描述符3重定向到另一個文件。

重定向文件描述符

你可以分配另外一個文件描述符給標準文件描述符,反之亦然。這意味着你可以將STDOUT的原來位置重定向到另一個文件描述符,然後再利用該文件描述符重定向回STDOUT。
e.g.

#!/bin/bash
#sttoring STDOUT, thhen  cooming back to  it

exec 3>&1
exec 1>test4out

echo  "This should store  in the output file"
eccho  "allong with thhe line"

exec 1>&3

echo "Now thiings should be  back to  normall"

.test
Now thhings should be back too normal
cat test4out
This should store in thhe output fiile
along with thhiie line

創建輸入文件描述符

可以用和重定向輸出文件描述符同樣的辦法重定向輸入文件描述符。在重定向到文件之前,先將STDIN文件描述符保存到另外一個文件描述符,然後在讀取完文件之後再將STDIN恢復到它原來的位置。
e.g.

#!/bin/bash
#redirecting input file descriiptors

exec 6<&0
exec 0<testfile

count=1
while read line
do
    echo "Line #$count: $line"
    count=$[ $count + 1]
done

exec 0<&6
read -p "Are you done now?" answer
case $annswer in  
    Y|y) echo "Goodbye";;
    N|n) echo "Sorry, thhis is  the end.";;
esac```

創建讀寫文件描述符

exec 3<> testfile

關閉文件描述符

shell會在腳本退出時自動關閉你創建的新輸入或輸出文件描述符。然而在有些情況下,你需要在腳本結束前手動關閉文件描述符。需要將它重定向特殊符號&-.

exec 3>&-

列出打開的文件描述符

lsof命令會列出整個Linux系統打開的所有文件描述符。
常用參數

  • -p :允許指定PID
  • -d: 允許指定要顯示的文件描述符編號

要想知道進程當前的PID,可以用特殊變量$$(shell會將它設爲當前PID)。-a選項來對其他兩個選項的結果執行布爾And運算,e.g.

/usr/sbin/lsof -a -p $$ -d 0,1,2

lsof默認有7列信息,如下:

描述
COMMAND 正在運行的命令名的前9個字符
PID 進程的PID
USER 進程屬主的登錄名
FD 文件描述符號以及訪問類型(r代表讀,w代表寫,u代表讀寫)
TYPE 文件的類型(CHR代表字符型, BLK代表塊型,DIR代表目錄,REG代表常規文件
DEVICE 設備的設備號(主設備和從設備號)
SIZE 如果有的話,表示文件的大小
NODE 本地文件的節點號
NAME 文件名

與STDIN, STDOUT,TDERR關聯的文件類型是字符型。因爲STDIN, STDOUT和STDERR文件描述符都指向終端,所以輸出的名稱就是終端的設備名。

阻止命令輸出

如果運行在後臺的腳本出現錯誤消息,shell會通過電子郵件將它們發給進程的屬主。這會很麻煩,尤其是當運行會生成很多煩瑣的小錯誤的腳本時。要解決這個問題,可以將STDERR重定向到一個叫作null文件的特殊文件。相當於全部被丟掉了。

ls -la > /dev/null

創建臨時文件

Linux系統有特殊的目錄,專供臨時文件使用。Linux使用/tmp目錄來存放不需要永久保留的文件。大多數Linux發行版配置了系統在啓動時自動刪除/tmp目錄的所有文件。

創建本地臨時文件

默認情況下,mktemp會在本地目錄中創建一個文件。要用mktemp命令在本地目錄中創建一個臨時文件,你只要指定一個文件名模板就行了。模板可以包含任意文本文件,在文件名末尾加上6個X就可以了。
mktemp命令會用6個字符碼替換這6個X,從而保證文件在目錄中的唯一性。
mktemp命令的輸出正是它所創建的文件的名字。在腳本中使用mktemp命令時,可能要將文件名保存到變量中,這樣就能在後面的腳本中引用了。

tempfilename = $(mktemp testfile.XXXXXX)

在/tmp目錄創建臨時文件

-t選項會強制mktemp命令在臨時目錄來創建該文件。在用這個特性時,mktemp命令會返回用來創建臨時文件的全路徑,而不只是文件名。

創建臨時目錄

-d選項會告訴mktemp命令來創建一個臨時目錄而不是臨時文件。

記錄消息

將輸出同時發送到顯示器和日誌文件,這種做法有時候能夠派上用場。你不用將輸出重定向兩次,只要用特殊的tee命令就行。
tee命令相當於管理的一個T型接口。它將從STDIN過來的數據同時發往兩處。一處理是STDOUT,另一處是tee命令行所指定的文件名。

date | tee testfile

默認情況下,tee命令會在每次使用時覆蓋輸出文件內容。如果你想將數據追加到文件中,必須用-a選項。
e.g. 例子是讀取csv文件,然後創建Insert語句將數據插入MySQL數據庫。

#!/bin/bash
#read file and create Insert statement for MySQL

outfile='members.sql'
IFS=','
while read lname fname address city state zip
do
    cat >> $outfile << EOF
    INSERT INTO MEMBERS(lname,fname, address, city, state, zip) values('$lname', '$fname', '$address', '$city', '$state', '$zip');
EOF
done < ${1}

運行腳本:

test23 < members.csv

控制腳本

處理信號

Linux利用信號與運行在系統中的進程進行通信。

重溫Linux信號

Linux系統和應用程序可以生成超過30信號。如下列出了常用的。

信號 描述
1 SIGHUP 掛起進程
2 SIGINT 終止進程
3 SIGQUIT 停止進程
9 SIGKILL 無條件終止進程
15 SIGTERM 儘可能終止進程
17 SIGSTOP 無條件停止進程,但不是終止進程
18 SIGTSTP 停止或暫停進程,但不終止進程
19 SIGCONT 繼續運行停止的進程

默認情況下,bash shell會忽略收到的任何SIGQUIT(3)和SIGTERM(5)信號(正因爲這樣,交互式shell纔不會被意外終止)。但是bash shell會處理收到的SIGHUP(1)和SIGINT(2)信號 。

生成信號

bash shell允許用鍵盤上的組合鍵生成兩種基本的Linux信號。

  1. 中斷進程
    Ctrl+C組合鍵會生成SIGINT信號,並將其發送給當前在shell中運行的所有進程。
    Ctrl+C組合鍵會發送SIGINT信號,停止shell中當前運行的進程。
  2. 暫停進程
    你可以在進程運行期間暫停進程,而無需終止它。
    Ctrl+Z組合鍵會生成一個SIGTSTP信號,停止shell中運行的任何進程。停止進程跟終止進程不同:停止進程會讓程序繼續保留在內存中,並能從上次停止的位置繼續運行。
    可以使用ps命令來查看已停止的作業。

捕獲信號

也可以不忽略信號,在信號出現時捕獲它們並執行其他命令。trap命令允許你來指定shell腳本要監看並從shell中攔截的Linux信號。如果腳本收到了trap命令中列出的信號,該信號不再由shell處理,而是交由本地處理。命令格式:

trap commands signals

在trap命令行上,你只要列出想要shell執行的命令,以及一組用空格分開的待捕獲的信號。你可以用數值或Linux信號名來指定信號。
e.g. 使用trap命令來忽略SIGINT信號,並控制腳本的行爲

#!/bin/bash
#Testing signal trapping
trap "echo 'sorry! I have trapped Ctrl-C'" SIGINT
echo This is a test script
count=1
while [ $count -le 10]
do
    echho "Loop #$count"
    sleep 1
    count=$[ $count + 1]
done
echo "This is thhe end of the test script"```

本例中用到的trap命令會在每次檢測到SIGINT信號時顯示一行簡單的文本消息。捕獲這些信號會阻止用戶用bash shell組合鍵Ctrl+C來停止程序。
每次使用Ctrl+C組合鍵,腳本都會執行trap命令中指定的echo語句,而不是處理該信號並允許shell停止該腳本。

捕獲腳本退出

除了在shell腳本中捕獲信號,你也可以在shell腳本退出時進行捕獲。這是在shell完成任務時執行命令的一種簡便方法。
要捕獲shell腳本的退出,只要在trap命令後加上EXIT信號 就行。

修改或移除捕獲

想要在腳本 中的不同位置進行不同的捕獲處理,只需要重新使用帶有新選項的trap命令。修改了信號捕獲之後,腳本處理信號的方式就會發生變化。但如果一個信號是在捕獲被修改前接收到的,那麼腳本仍然會根據最初的trap命令進行處理。
也可以刪除已設置好的捕獲。只需要在trap命令與希望恢復默認行爲的信號列表之間加上破折號(一個或兩個都可以)就行了。

以後臺模式運行腳本

後臺運行腳本

以後臺模式運行shell腳本只需要在命令後加個&符就行了。
當&符放到命令後時,它會將命令和bash shell分離開來,將命令作爲系統中的一個獨立的後臺進程運行。
不過需要注意,當後臺進程運行時,它仍然會使用終端顯示器來顯示STDOUT和STDERR消息。這樣腳本的輸出就會與shell提示符混雜在一起了。所以最好是將後臺運行的腳本 的STDOUT和STDERR重定向。

運行多個後臺作業

在非控制檯下運行腳本

有時你會想在終端會想在終端會話中啓動shell腳本,然後讓腳本一直在後臺模式運行到結束,即使你退出了終端會話。這可以使用nohup命令來實現。
nohup命令運行了另外一個命令來阻斷所有發送給該進程的SIGHUP信號。這會在退出終端會話時阻止進程退出。格式如下:

nohup testshell.sh &

由於nohup命令會解除終端與進程的關聯,進程也就不再同STDOUT和STDERR聯繫在一起。爲了保存該命令產生的輸出,nohup命令會自動 將STDOUT和STDERR的消息重定向到一個名爲nohup.out的文件中。

作業控制

啓動,停止,終止以及恢復作業的這些功能統稱爲作業控制。

查看作業

作業控制中的關鍵命令是jobs命令。jobs命令允許查看shell當前正在處理的作業。
腳本中使用$$變量來顯示Linux系統分配給該腳本的PID。
jobs命令的常用參數:

參數 描述
-l 列出進程的PID以及作業號
-n 只列出上次shell發出的通知後改變了狀態的作業
-p 只列出作業的pid
-r 只列出運行中的作業
-s 只列出已停止的作業

作業列表中帶加號的作業會被當作默認作業。在使用作業控制命令時,如果示在命令行指定任何作業號,該 作業會被當成作業控制命令的操作對象。

重啓停止的作業

要以後臺模式重啓一個作業,可用bg命令加上作業號。
要以前臺模式重啓作業,可用帶有作業號的fg命令。

調整謙讓度

在Linux系統中,由shell啓動的所有進程的調試優先級默認都是相同的。
調試優先級是個整數值,從-20(最高優先級)到+19(最低優先級)。默認情況下,bash shell以優先級0來啓動所有進程。
可以使用nice命令改變優先級

nice命令

在啓動命令時只要用nice命令指定優先級別,就可以降低命令的優先級。

nice -n 10 ./testshell.sh > out.out &

renice命令

如需要改變已運行命令的優先級。renice可以允許你指定運行進程的PID來改變它的優先級。

renice -n num -p pid

不過有一些限制:

  • 只能對屬於你的進程執行renice
  • 只能通過renice降低優先級
  • root用戶可以通過renice來任意調整進程的優先級。

定時運行作業

Linux系統提供了多個在預選時間運行腳本的方法: at命令和cron表。

用at命令來計劃執行作業

at命令允許指定Linux系統何時運行腳本。at命令會將作業提交到隊列中,指定shell何時運行該作業。at的守護進程atd會雙後臺模式運行,檢查作業隊列來運行作業。大多數Linux發行版會在啓動時運行此守護進程。
atd守護進程會檢查系統上的一個特殊目錄(var/spool/at)來獲取用at命令提交的作業。默認情況下atd守護進程會每60秒檢查一下這個目錄。有作業時,atd守護進程會檢查作業設置的運行時間。如果時間跟當前時間匹配,atd守護進程就會運行此作業。

  1. at命令的格式

at [ -f filename] time

如果你指定的時間已經錯過,at命令會在第二天的那個時間運行指定的作業。
at命令能識別多種不同的時間格式

  • 標準的小時和分鐘格式,比如10:15
  • AM/PM指示符,比如10:15 PM
  • 特定可命名時間,比如now, noon, midnight或者teatime(4 PM)。

除了指定運行作業的時間,也可以通過不同的日期格式指定特定的日期。

  • 標準日期格式,比如MMDDYY,MM/DD/YY或DD.MM.YY
  • 文本日期,比如Jul 4或Dec 25,加不加年份均可。
  • 你也可以指定時間增量
    • 當前時間+25 min
    • 明天10:15 PM
    • 10:15 + 7天

在你使用at命令時,該 作業會被提交到作業隊列。作業隊列會保存通過at命令提交的待處理作業。針對不同優先級,存在 26種不同的作業隊列。作業隊列通常用小寫字母a-z和大寫字母A-Z來指代。作業隊列的字母排序越高,作業運行的優先級主小老虎 低(更衰敗的nice值)。默認情況下,at的作業會被提交到a作業隊列。如果想以更高優先級運行作業,可以用-q參數指定不同的隊列字母。

  1. 獲取作業的輸出
    當作業在Linux系統上運行時,顯示器並不會關聯到該作業。取而代之的是,Linux系統會將提交該作業的用戶的電子郵件地址作爲STDOUT和STDERR
  2. 列出等待的作業
    atq命令可以查看系統中有哪些作業在等待。
  3. 刪除作業
    atrm命令可以刪除等待的作業

安排需要定期執行的腳本

  1. cron時間表
    cron時間表採用一種特別的格式來指定作業何時運行。其格式如下:

min hour dayofmnthh month dayofweekk command

  1. 構建cron時間表
    列出已的有時間表:

crontab -l

添加時間表:

crontab -e

  1. 瀏覽目錄
    如果你創建的腳本對精確的執行時間要求不高,用預配置的cron腳本目錄會更方便。有4個基本目錄:hourly, daily, monthly和weekly 在/etc/下。
  2. anacron程序
    cron程序 的唯一問題是它假定系統是7*24小時運行的。
    如果某個作業在cron時間表中安排運行的時間已到,但這個時間Linux系統系統處理於關機狀態,那麼這個作業就不會被執行。當系統開機時,cron程序不會再去運行那些錯過的作業。要解決這個問題,許多Linux發行版還包含了anacron程序。
    如果anacron程序知道某個作業錯過了執行時間,它會盡快運行該作業。這意味着Linux關機了幾天,當它再次開機時,原定在關機期間運行的作業會自動 運行。
    anacron程序使用自己的時間表(通常位於/etc/anacrontab)來檢查作業目錄。
    anacron時間表的基本格式和cron時間表略有不同:

period delay identifier command

  • period條目定義了作業多久運行一次,以天爲單位。
  • delay條目會指定系統啓動後anacron程序需要等待多少分鐘再開始運行錯過的腳本。
  • command條目包含了run-parts程序和一個cron腳本目錄名。run-parts程序負責運行目錄中傳給它的任何腳本。
  • identifier條目是一種特別的非空字符串,如cron-weekly。它用於唯一標識日誌消息和錯誤郵件中的作業。

高級Shell腳本編程

創建函數

基本的腳本函數

在開始編寫較複雜的shell腳本時,你會發現自己毛毛蟲使用了部分能夠執行特定任務的代碼。這些代碼有時簡單,比如顯示一條文本消息,或者從腳本用戶那裏獲得一個答案,有時則會比較複雜,需要作爲大型處理過程中的一部分被多次使用。
函數是一個腳本代碼塊,你可以爲其命名並在代碼中任意位置重用。要在腳本中使用該 代碼,只要使用所起的函數名就行了(這個過程稱爲函數調用)。

創建函數

有兩種格式可以用來在bash shell腳本 中創建函數。第一種格式採用function關鍵字,後跟分配該代碼塊的函數名。

function funcname {
commands
}

funcname屬性定義了賦予函數的唯一名稱。腳本中定義的每個函數都必須有一個唯一的名稱。
commands是構成函數的一條或多條bash shell命令。
第二種格式更接近於其他編程語言中定義函數的方式。

funcname() {
commands
}

函數名後的空括號表明正在定義的是一個函數。這種格式的命名規則和之前定義shell腳本 函數的格式一樣。

使用函數

要在腳本中使用函數,只需要像其他shell命令一樣,在行中指定函數名就行了。

返回值

bash shell會把函數當作一個小型腳本,運行結束時會返回一個退出狀態碼,有3種不同的方法來爲函數生成退出碼。

默認退出狀態碼

默認情況下,函數的退出狀態碼是函數中最後一條命令退出狀態碼。在函數執行結束後,可以用標準變量$?來確定函數的退出狀態碼。

使用return命令

bash shell使用return命令來退出函數並返回特定的退出狀態碼。return命令允許指定一個整數值來定義函數的退出狀態碼,從而提供了一種簡單的途徑來編程設定函數退出狀態碼。
不過需要注意:

  • 函數一結束就取返回值
  • 退出狀態碼必須是0-255

如果在用$?變量提取函數返回值 之前執行了其他命令,函數的返回值就會丟失。

使用函數輸出

正如可以將命令的輸出保存到shell變量中一樣,你也可以對函數同樣的處理辦法。可以用這種技術來獲得任何類型的函數輸出,並將其保存到變量中。

result=$(func)

在函數中使用變量

在函數中使用變量時,你需要注意它們的定義方式以及處理方式。

向函數傳遞參數

bash shell會將函數當作小型腳本來對待。這意味着你可以像普通腳本那樣向函數傳遞參數。
函數可以使用參數環境變量來表示命令行上傳給函數的參數。也可以用特殊變量$#來判斷傳給函數的參數數目。

在函數中處理變量

給shell腳本程序員帶來麻煩的原因之一就是變量的作用域。作用域是變量可見的區域。函數中定義的變量與普通變量的作用域不同。也就是說,對腳本 的其他部分而言,它們是隱藏的。
函數使用兩種類型的變量:

  • 全局變量
  • 局部變量
全局變量

全局變量是在shell腳本中任何地方都有效的變量。如果你在腳本的記事本部分定義了一個全局變量。那麼可以在函數內讀取它的值。類似你在函數內定義了一個全局變量,可以在腳本的主體部分讀取它的值。
默認情況下,你在腳本中定義的任何變量都是全局變量。在函數外定義的變量可在函數內正常訪問。
如果變量在函數內被賦予了新值,那麼在腳本中引用該變量時,新值也依然有效。

局部變量

函數內部使用的任何變量都可以被聲明成局部變量。要實現這一點只要在變量聲明前面加上local關鍵字就可以了

local variable_name

你也可以在變量賦值語句中使用local關鍵字

local variable_name=$[ $value + 5]

local關鍵字保證了變量只侷限在該函數中。如果腳本中在該函數之外有同樣名字的變量,那麼shell將會保持這兩個變量的值是分離的。現在你就能很輕鬆地將函數變量和腳本變量隔離開了,只共享需要共享的變量。

數組變量和函數

向函數傳數組參數

向腳本函數傳遞數組變量的方法會有點不好理解 。將數組變量當作單個參數傳遞的話,它不會起作用。
如果你試圖將數組變量作爲函數參數,函數只會取數組變量的第一個值。要解決這個問題,你必須將該數組的值分解成單個的值,然後將這些值作爲函數參數使用。

從函數返回數組

從函數裏向shell腳本傳回數組變量用類似的方法。函數用echo語句來按正確順序輸出單個數組值,然後腳本再將它們重新放進一個新的數組變量中。

函數遞歸

局部函數變量的一個特性是自成體系。除了從腳本 命令行處獲得的變量,自成體系的函數不需要使用任何外部資源。
這個特性使得函數可以遞歸地調用,也就是說,函數可以調用 自己來得到結果。

創建庫

使用函數可以在腳本 中省去一些輸入工作,但若需要在多個腳本 中使用同一段代碼。我們就需要創建函數庫文件。bash shell允許創建函數庫文件,然後在多個腳本 中引用該庫文件。
格式:

. 庫文件

在命令行上使用函數

在命令行上創建函數

因爲shell會解釋用戶輸入 的命令,所有可以在命令行上直接定義一個函數。有兩種方法
一種方法是採用行方式定義函數。
當在命令行上定義函數時, 你必須記得在每個命令後面加個分號,這樣shell就能知道 在哪裏是命令的起止了。
另一種方法是採用多行方式來定義函數。在定義時,bash會使用次提示符來提示輸入更多命令。用這種方法, 你不用在每條命令的末尾放一個分號,只要按下回車鍵就行。
在函數的尾部使用花括號,shell就會知道你已經完成了函數的定義。

在.bashrc文件中定義函數

  1. 直接定義函數
  2. 讀取函數文件

圖形化桌面環境中的編程腳本

創建文本菜單

shell腳本 菜單的核心是case命令。case命令會根據用戶在菜單 上的選擇來執行特定命令。

創建菜單佈局

  1. 使用clear清屏
  2. 使用echo打印菜單項
  3. 使用read命令讀取用戶輸入。

創建菜單函數

shell腳本 菜單 選項作爲一組獨立 的函數實現起來更爲容易。要做到這一點,你要爲每個菜單 選項創建獨立的shell函數。
創建shell菜單 腳本 的第一步是決定你希望腳本執行哪些功能,然後將這些功能以函數的形式放在代碼中。
通常我們會爲還沒有實現的函數先創建一個樁函數(stud function)。樁函數是一個空函數或者只有一個echo語句,說明最終這裏需要什麼內容。這允許你的菜單在你實現某個函數時仍然能正常操作。

添加菜單邏輯

整合shell腳本菜單

e.g…

#!/usr/bash
#simple script menu

functiion  diskspace {
    clear
    df -k
}

function whoseon {
    clear
    whho
}

functiion memusage {
    clear
    cat /proc/meminfo
}

function menu {
    clear
    echo
    echo -e "\t\t\tSys Admin Menu\n"
    echo -e "\t1. Display disk space"
    echo -e "\t2. Display logged on users"
    echo -e "\t3. Display memory usage"
    echo -e "\t0. Exit program\n\n"
    echo -en "\t\tEnter option: "
    read -n 1 option
}

while [ 1 ]
do
    menu
    case $option in 
    0)
        break ;;
    1)
        diskspace ;;
    2)
        whoseon ;;
    3)
        memusage ;;
    *)
        clear
        echo "Sorry, wroong selectiion";;
    esac
    echo -enn "\n\n\t\t\tHit any key to coontinue"
    read -n 1 line
done
clear

使用select命令

select命令只需要一條命令就可以創建出菜單,然後獲取輸入的答案並自動處理。select命令的格式如下:

select variable in list
do
commands
done

list參數是由空格分隔的文本選項列表,這些列表構成了整個菜單。select命令會將每個列表項顯示成一個帶編號的選項,然後爲選項顯示一個由PS3環境變量定義的特殊提示符。

#!/bin/bash
#using select in the menu

function diskspace {
    clear
    df -h
}

function whoseon {
    clear
    who
}

function memusage {
    clear
    cat /proc/meminfo
}

PS3="Enter option:"
select option in "Display disk space" "Display logged on users" "Display memory usage" "Exit program"
do
    case $option in
	"Exit program")
	    break ;;
	"Display disk space")
	    diskspace ;;
	"Display logged on users")
	    whoseon ;;
	"Display memory usage")
	    memsage ;;
	*)
	    clear
	    echo "Sorry, wrong selection";;
    esac
done
clear

製作窗口

dialog包

dialog包

dialog命令使用命令行參數來決定生成哪種容器部件。部件是dialog包中容器元素類型術語。dialog包現在運行如下部件類型:

部件 描述
calendar 提供選擇日期的日曆
checklist 顯示多個選項(其中每個選項都能打開或關閉)
form 構建一個帶有標籤以及文本字段(可以趕寫內容)的表彰
fselect 提供一個文件選擇容器來瀏覽選擇文件
gauge 顯示完成的百分比進度條
infobox 顯示一條消息,但不用等待迴應
inputbox 提供一個輸入文本用的文本表單
inputmenu 提供一個可編輯的菜單
menu 顯示可選擇的一系列選項
msgbox 顯示一條消息,並要求用戶選擇OK按鈕
pause 顯示一個進度條來顯示暫定期間的狀態
passwordbox 顯示一個文本框,但會隱藏輸入的文本
passwordform 顯示一個帶標籤和隱藏文本字段的表彰
radiolist 提供一組菜單 選項,但只能選擇其中一個
tailbox 用tail命令在滾動容器中顯示文件的內容
tailboxbg 跟tailbox一樣,介是在中運行
textbox 在滾動容器中顯示文件的內容
timebox 提供一個選擇小時,分鐘和秒數的容器
yesno 提供一條帶有Yes和No按鈕的簡單消息

要在命令行上指定某個特定的部件,需要使用雙破折線格式。

dialog --wiidgett parameters

其中widget是表中的部件名,parameters定義了部件容器的大小以及部件需要的文本
每個dialog部件都提供了兩種形式的輸出:

  • 使用STDERR
  • 使用退出狀態碼

可以通過dialog命令的退出狀態碼來確定用戶選擇的按鈕。如果選擇了Yes或OK按鈕,dialog命令會返回退出狀態碼0.如果選擇了Cancel或No按鈕,dialog命令會返回退出狀態碼1.可以用標準$?變量來確定dialog部件中具體選擇了哪個按鈕。
如果部件返回了數據,比如菜單選擇,那麼dialog命令會將數據發送到STDERR。可以用標準的bash shell方法來將STDERR輸出重定向到另一個文件或文件描述符中。
e.g.

$ dialog --inputbox "Enter you age: " 10 20 2>age.txt

常用的dialog部件

  1. msgbox部件
    它會在窗口中顯示一條簡單的消息,直到用戶單擊OK按鈕才消失

$dialog -msgboox text height width

text參數是你想在容器中顯示的字符串。如果你想在容器頂部放一個標題,也可以用–title參數,後接作爲標題的文本。

$ dialog --title titleName --msgbox “This is a msg” 10 20

  1. yesno部件
    yesno部件進一步擴展了msgbox部件的功能,允許用戶對容器中顯示的問題選擇yes或no。

$ dialog --title “Please answer” --yesno “Is this thhing on?” 10 20
echo $?

  1. inputbox部件
    inputbox部件爲用戶提供了一個簡單的文本框區域來輸入文本字符串。dialog命令會將文本字符串的值發給STDERR。你必須重定向STDERR來獲取用戶輸入。
  2. textbox部件
    textbox部件是在容器中顯示大量信息的極佳辦法。它會生成一個滾動容器來顯示由參數所指定的文件中的文本。

$ dialog --textbox /etc/passwd 15 45

  1. menu部件
    menu部件允許你來創建我們之前所缺件的文本菜單的窗口版本。只要爲每個選項提供一個選擇標號和文本就行了。

$ dialog --menu “Sys Admin mennu” 20 300 10 1 “Display diskk space” 2 “Display users” 3 “Display memory usage” 4 “Exit” 2>test.txt

6… fselect部件

dialog選項

除了標準部件,還要以在dialog命令中定製很多不同的選項。

選項 描述
–add-widget 繼續下個對話框,直到按下Esc或Cancel按鈕
–aspect ratio 指定容器寬度和高度的寬高比
–backtitle title 指定顯示在屏幕頂部背景上的標題
–begin x y 指定容器左上角的起始位置
–cancel-label label 指定Cancel按鈕的替代標籤
–clear 用默認的對話背景來清空屏幕內容
–colors 在對話文本中嵌入ANSI色菜編碼
–cr-wrap 在對話文本中允許使用換行符並強制換行
–create-rc file 將示例配置文件的內容複製到指定的file文件中
–defaultno 將yes/no對話框的默認答案設爲No
–default-item string 設定複選列表,表單或菜單 對話中的默認項
–exit-label label 指定Exit按鈕的替代標籤
–extra-buton 在OK按鈕和Cancel按鈕之間顯示一個額外按鈕
–extra-label label 指定 額外按鈕的替代標籤
–help 顯示dialog命令的幫助信息
–help-button 在OK按鈕 和Cancel按鈕後顯示一個Help按鈕
–help-label label 指定Help按鈕的替代標籤
–help-status 當選定Help按鈕後,在幫助信息後寫入多選列表,單選列表或表彰信息
–ignore 忽略dialog不能識別的選項
–input-fd fd 指定 STDIN之外的另一個文件描述符
–insecure 在password部件 中鍵入內容時顯示星號
–item-help 爲多選列表,單選列表或菜單中的每個標號在屏幕的底部添加一個幫助欄
–keep-window 不要清除屏幕上顯示過的部件
–max-input size 指定輸入的最大字符串長度。默認爲2048
–nocancel 隱藏Cancel按鈕
–no-collapse 不要將對話文本中的製表符轉換成空格
–no-kill 將tailboxbg對話放到後臺,並禁止該進程的SIGHUP信號
–no-label label 爲No按鈕指定替代標籤
–no-shadow 不要顯示對話容器的陰影效果
–ok-label label 指定OK按鈕的替代標籤
–output-fd fd 指定除STDERR之外的另一個輸出文件描述符
–print-maxsize 將對話容器的最大尺寸打印到輸出中
–print-size 將每個對話容器的大小打印到輸出中
–separate-output 一次一行地輸出checklist部件 的結果,不使用引號
–separator string 指定 用於分隔部件輸出的字符串
–separate-widget string 指定用於分隔部件輸出的字符串
–shadow 在每個容器的右下角繪製陰影
–single-quoted 需要時對多選列表的輸出採用單引號
–sleep sec 在處理完對話容器之後延遲指定的秒數
–stderr 將輸出發送到STDERR
–stdout 將輸出發送到STDOUT
–tab-correct 將製表符轉換成空格
–tab-len n 指定一個製表符佔用的空格數(默認爲8)
–timeout sec 指定無用戶輸入 時,sec秒後退出並返回錯誤代碼
–title title 指定對話窗口的標題
–trim 從對話文本中刪除前導空格和換行符
–visit-items 修改對話窗口中製表符停留位置,使其包括選項列表
–yes-label label 爲Yes按鈕指定替代標籤

在腳本中使用dialog命令

在腳本中使用dialog需要注意:

  • 如果有cancel或No按鈕,檢查dialog命令的退出狀態碼
  • 重定向STDERR來獲得輸出值

使用圖形

KDE環境

KDE圖形化環境默認包含kdialog包

GNOME環境

GNOME圖形化環境支持兩種流行的可生成標準容器的包:

  • gdialog
  • zenity

初識sed和gawk

文本處理

sed編輯器

sed編輯器被稱作流編輯器(stream editor),和普通的交互式文本編輯器恰好相反。
sed編輯器可以根據命令來處理數據流中的數據,這些命令要麼從命令行中輸入,要麼存儲在一個文本文件中。sed編輯器會執行下列操作。

  • 一次從輸入中讀取一行數據。
  • 根據所提供的編輯器命令匹配數據
  • 按照命令修改流中的數據。
  • 將新的數據輸出到STDOUT
    在流編輯器將所有命令與一行數據匹配完畢後,它會讀取下一行數據並重復這個過程。在流編輯器處理完流中的所有數據行後,它就會終止。
    由於命令是按順序逐行給出的,sed編輯器只需要對數據流進行一遍處理就可以完成編輯操作。
    sed命令的格式如下

sed options script file

選項允許你修改sed命令的行爲,可以使用的:

選項 描述
-e script 在處理輸入時,將script中指定的命令添加到已有的命令中
-f file 在處理輸入時,將file中指定的命令添加到已有的命令中
-n 不產生命令輸出,使用print命令來完成輸出

script參數指定了應用於流數據上的單個命令。如果需要用多個命令,要麼使用-e選項在命令行中指定,要麼使用-f選項在單獨的文件中指定。

  1. 在命令行定義編輯器命令
    默認情況下,sed編輯器會將指定的命令應用到STDIN輸入流上。這樣你可以直接將數據通過管道輸入sed編輯器處理。
    e.g.

echo “This is a test” | sed ‘s/test/big test/’
This is a big test

重要的是,要記住,sed編輯器並不會修改文本文件的數據。它只會將修改後的數據發送到STDOUT。

  1. 在命令行使用多個編輯器命令
    要在sed命令行上執行多個命令時,只要用-e選項就可以了。
    e.g.

sed -e ‘s/brown/green/; s/dog/cat/’ data1.txt

兩個命令都作用到文件中的每行數據上。命令之間必須用分號隔開,並且在命令末尾和分號之間不能有空格。
如果不想用分號,也可以用bash shell中的次提示符來分隔命令。只要輸入 第一個單引號標示出sed程序腳本的起始(sed編輯器命令列表),bash會繼續提示你輸入更多的命令,直到輸入了標示結束的單引號。
e.g.

sed -e ’
s/brown/green/
s/fox/elephant/
s/dog/cat/’ data.txt

必須記住,要在封尾單引號所在行結束命令。bash shell一旦發現了封尾的單引號,就會執行命令。開始後,sed命令就會將你指定的每笨命令應用到文本誰的中的每一行上。

  1. 從文件中讀取編輯器命令
    最後,如果有大量要處理的sed命令,那麼將它們放進一個單獨的文件中通常會更方便一些。可以在sed命令中用-f選項來指定文件。
    e.g.

sed -f script.sed data.txt

在sed文件中,不用在每條命令後面放一個分號,sed編輯器知道每行都是一條單獨的命令。跟在命令行輸入命令一樣。

gawk程序

gawk能提供一個類編程環境來修改和重新組織文件中的數據。
gawk程序是Unix中的原始awk程序 的GNU版本。在gawk編程語言中,你可以做正面的事情:

  • 定義變量來保存數據
  • 使用算術和字符串操作符來處理數據
  • 使用結構化編程概念(比如if-then語句和循環)來爲數據處理增加處理邏輯
  • 通過提取數據文件中的數據元素,將其重新排列或格式化,生成格式化報告。

gawk程序的報告生成能力通常用來從大文本文件中提取數據元素,並將它們格式化成可讀的報告。其中最完美的例子就是格式化日誌文件。

  1. gawk命令格式

gawkk options program file

可用選項:

選項 描述
-F fs 指定行中劃分數據字段的字段分隔符
-v var=value 定義gawk程序中的一個變量及其默認值
-mf N 指定要處理的數據文件中的最大字段值
-mr N 指定數據文件中的最大數據行數
-W keyword 指定gawk的兼容模式或警告等級

命令行選項提供了一個簡單的途徑來定製gawk程序的功能。

  1. 從命令行讀取程序腳本
    gawk程序腳本用一對花括號來定義。你必須將腳本命令放到兩個花括號({})中。
    由於gawk命令行假定腳本是單個文本字符串,你還必須將腳本放到單引號中。
    e.g.

gawk ‘{print “Hello World!”}’

要終止這個gawk程序,你必須表明數據流已經結束了。bash shell提供了一個組合鍵來生成EOF(End-of-File)字符。Ctrl+D組合鍵會在bash中產生一個EOF字符。這個組合鍵能夠終止gawk程序並返回到命令行界面提示符下。

  1. 使用數據字段變量
    gawk的主要特性之一是其處理文本文件中數據的能力。它會自動給一行中的每個數據元素分配一個變量。
    -$0: 代表整個文本行
  • $1:代表文本行中的第1個數據字段。


在文本行中,每個數據字段字段都是通過字段分隔符劃分的。gawk在讀取一行文本時,會用預定義的字段分隔符劃分每個數據字段。gawk中默認的字段分隔符是任意的空白字符(例如空格或製表符)。

  1. 在程序腳本 中使用多個命令
    gawk編程語言允許你將多條命令組合成一個正常的程序。要在命令行上有程序腳本中使用多條命令,只要在命令之間放個分號即可。
    e.g.

echo “My name is Rich” | gawk ‘{$4=“Christine”; print $0}’
My name is Christine

第一條命令會給字段變量$4賦值。第二條命令會打印整個數據字段。

  1. 從文件中讀取程序
    跟sed編輯器一樣,gawk編程器允許將程序存儲到文件中,然後再在命令行中引用。
    e.g.

cat script.gawk
{print $1 "'s homedirectory is " $6}
gawk -F: -f scrippt.gawk /etc/passwd

  1. 在處理數據前運行腳本
    gawk還允許指定程序腳本何時運行。默認情況下,gawk會從輸入中讀取一行文本,然後針對該行的數據執行程序腳本 。有時可能需要在處理數據前運行腳本,比如爲報告創建標題。BEGIN關鍵字就是用來做這個的。它會強制gawk在讀取數據前執行BEGIN關鍵字後指定的程序腳本 。
    e.g.

gawkk ‘BEGIN {print “Hello World!”}’

  1. 在處理數據後運行腳本
    與BEGIN關鍵字類似,END關鍵字允許你指定一個程序腳本,gawk會在讀完數據後執行它。
    e.g.

gawk ‘BEGIN {print "The data3 File Contents: "}
{print $0}
END {print “End of File”}’ data3.txt

在腳本中除了使用-F還可以使用叫作FS的特殊變量指定分隔符。

sed編程基礎

成功使用sed編輯器的關鍵在於掌握其各式各樣的命令和格式。

更多的替換選項

s命令(substitute):替換

  1. 替換標記
    替換命令在替換多行中的文本時能正常工作,但默認情況下它只替換每行中出現的第一處,要讓替換命令替換一行中不同地方出現的文本必須使用替換標記。替換標記會在替換命令字符串之後設置。

s/pattern/replaccement/flags

有4種可用的替換標記:

  • 數字: 表明新文本將替換第幾處模式匹配的地方
  • g: 表明新文本將會替換所有匹配的文本
    -p: 表明原先行的內容要打印出來
    -w file:將替換的結果寫到文件中

sed ‘s/test/trial/w test.txt’ data.txt # w替換標記會產生輸出到test.txt文件

  1. 替換字符
    有時你會在文本字符串中遇到一些不太方便在替換模式中使用的字符。如:正斜線。要解決這個問題,sed編輯器允許選項其他字符來作爲替換命令中的字符串分隔符。
    e.g. 使用感嘆號做爲分隔符

sed ‘s!/bin/bash!/bin/zsh!’ /etc/passwd

使用地址

默認情況下,在sed編輯器中使用的命令會作用於文本數據的所有行。如果只想將命令作用於特定行或某些行,則必須用行尋址。在sed編輯器中有兩種形式的行尋址:

  • 以數字形式表示行區間
  • 用文本模式來過濾出行

兩種形式都使用相同的格式來指定地址:

[address] command

也可以將特定地址的多個分組:

address {
command1
command2
command3
}

  1. 數字方式 的行尋址
    e.g.

sed ‘2s/dog/cat/’ data1.txt #只替換第二行
sed ‘2,3s/dog/cat/’ data1.txt #替換2到3行
sed ‘2, $s/dog/cat/’ data1.txt #替換2到最後一行

  1. 使用文本模式過濾器
    sed允許指定文本模式來過濾出命令要作用的行,命令格式如下:

/pattern/command

必須用正斜線將要指定的pattern封起來。sed編輯器會將該 命令作用到包含指定文本模式的行上。
e.g.

sed ‘/root/s/bash/zsh/’ /etc/passwd #替換root用戶的默認shell

sed編輯器在文本模式中採用了一種稱爲正則表達式的特性來幫助創建匹配模式。

  1. 命令組合
    如果需要在單選上執行多條命令,可以用花括號將多條命令組合在一起。sed編輯器會處理地址行處列出的每條命令。
    e.g.

sed ‘2, ${
s/foox/elephant/
s/dog/cat/
}’ data.txt

刪除行

刪除命令d,會刪除匹配指定尋址模式的所有行。如果忘記加入尋址模式的話,流中的所有文本行都會被刪除。

  • 通過區間指定

sed ‘2, 5d’ data.txt

  • 通過模式匹配刪除

sed ‘/number 1/d’ data.txt

記住sed編輯器不會修改原始文件,你刪除的行只是從sed編輯器的輸出中消失了。原始文件仍然包含那些“刪除掉的”行

插入了附加文本

sed編輯器允許向數據流 插入附加 文本行。

  • 插入(insert)命令(i)會在指定行前增加一個新行;
  • 附加(append)命令(a)會在指定行後增加一個新行。

它們不能在單個命令行上使用。你必須指定是要將行插入還是附加 到另一行。格式如下:

sed ‘[address]command
new line’

new line中的文本將會出現在sed編輯器輸出中你指定的位置。
e.g.

echo “Test Line 2” | sed ‘i\Test Line 1’
sed ‘3i
This is an inserted line.’ data.txt #數據會插入到數據流的第三行

修改行

修改(change)命令(c)允許你修改數據流中事先 文本的內容。
同樣可以使用行號模式和文本模式也尋址
e.g.

sed ‘3c
This is a changed line of text.’ data.txt
sed ‘/number 4/c
This is a change line of txt .’ data.txt

轉換命令

轉換(transform)命令(y)是唯一可以處理單個字符的sed編輯器命令。格式如下:

[address]y/inchars/outchars/

轉換命令會對inchars和outchars值 進行一對一的映射。如果inchars和outchars的長度不同,則sed編輯器會產生一條錯誤消息。e.g.

sed ‘y/123/789/’ datta.txt

轉換命令是個全局命令,也就是說,它會在文本行中找到的所有指定字符自動 進行轉換,而不會考慮它們出現的位置。

回顧打印

有3個命令可以用來打印數據流中的信息:

  • p命令
  • 等號(=)命令用來打印行號
  • 小寫的L命令用來列出行
  1. 打印行

echo “thhis is a test” | sed ‘p’
sed -n ‘/number 3/p’ data.txt

在命令行上用-n選項,你可以禁止輸出其他行只打印包含匹配文本模式的行。

sed -n ‘2,3p’ data.txtt

如果需要在修改之前查看行,也可以使用打印命令,比強替換或修改命令一起使用。
e.g.

sed -n ‘/3/{
p
s/line/test/p
}’ data.txt #sed命令會查找包含數字3的行,然後執行兩條命令。

  1. 打印行號
    等號命令會打印行在數據流中的當前行號。

sed ‘=’ data.txtt

  1. 列出行
    列出(list)命令(l)可以打印數據流中的文本和不可打印的ASCII字符。
    e.g.

sed -n ‘l’ data.txt

使用sed處理文件

1.寫入文件
w命令用來向文件寫入行。格式如下:

[adddress]w filename

filename可以使用相對路徑 或絕對 路徑,但不管是哪種,運行sed編輯器的用戶都必須有文件的寫權限。
e.g.

sed ‘1,2w test.txt’ data.txtt #將data.txt中的前兩行寫入test.txt

  1. 從文件讀取數據
    讀取(read)命令(r)允許你將一個獨立 文件中的數據插入到數據流中。格式如下:

[address]r filename

filename參數指定了數據文件的絕對路徑 或相對路徑 。你在讀取命令中使用地址區間,只能指定單獨一個行號或文本模式地址。sed編輯器會將文件中的文本插入到指定 地址後。
e.g.

sed ‘3r data1.txt’ data2.txt #會將data1.txt中的數據插入data2的第三行後。

正則表達式

在腳本 中成功運用sed編輯器和gawk程序的着急在於熟練使用正則表達式。

什麼是正則表達式

定義

正則表達式的類型

正則表達式是通過正則表達式引擎(regular expression engine)實現的。正則表達式引擎是一套底層軟件,負責解釋正則表達式模式並使用這些模式進行文本匹配
在Linux中,有兩種流行的正則表達式引擎:

  • POSIX基礎正則表達式(basic regular expression.BRE)引擎
  • POSIZ擴展正則表達式(extended regular expression, ERE)引擎

定義BRE模式

純文本

特殊字符

正則表達式識別的特殊字符包括:

.*[]^${}+?|()

如果需要某個特殊字符作爲文本字符,就必須轉義。在轉義特殊字符時,你需要在它前面加一個特殊字符來告訴正則表達式引擎應該將接下來的字符當作普通的文本字符。這個特殊字符就是反斜線(\)。

錨字符

  1. 鎖定在行首
    脫 字符(^)定義從流中文本行的行首開始的模式。如果模式出現在行首之外的位置,正則表達式模式則無法匹配。
  2. 鎖定在行尾
    特殊字符$定義了行尾錨點。
  3. 組合錨點

點號字符

特殊字符點號用來匹配除換行符之外的任意單個字符。

字符組

使用方括號來定義一個字符組。方括號裏包含所有你希望出現在該 字符組中的字符。

排除型字符組

在字符組的開頭加一個脫字符,就可以反轉字符組的作用。尋找組中沒有的字符。

區間

可以使用單破折線符號在字符組中表示字符區間。

特殊的字符組

BRE特殊字符組

描述
[[:alpha:]] 匹配任意字母字符,不管是大寫還是小寫
[[:allnum:]] 匹配任意字母數字字符0-9, a-z或A-Z
[[:blank:]] 匹配空格或製表符
[[:diigit:]] 匹配0-9之間的數字
[[:lower:]] 匹配小寫字母字符
[[:print:]] 匹配伴音可打印字符
[[:punct:]] 匹配標點符號
[[:space:]] 匹配任意空白字符:空格,製表符,ML, FF, VT和CR
[[:upper:]] 匹配任意大寫字母字符

可以在正則表達式模式中將特殊字符組像普通字符組一樣使用。

星號

在字符後面放置昨號表明該 字符那也得在匹配模式的文本中出現0次或多次

擴展正則表達式

POSIX ERE模式包括了一些可供Linux應用和工具使用的額外符號 。gawk程序能夠識別ERE模式,但sed編輯器不能。

問號

問題類似於星號,表明前面的字符可以出現0次或1次。

加號

表明前面的字符可以出現1次或多次。

使用花括號

花括號允許你爲可重複的正則表達式指定一個上限。這通常稱爲間隔。可以用兩種格式來指定區間

  • m: 正則表達式準確出現m次
  • m,n:正則表達式至少出現m次,至多出現n次。

管道符號

管道符號允許你在檢查數據流時,用邏輯OR方式指定正則表達式引擎要用的兩個或多個模式。如果任何一個模式匹配了數據流文本,文本就通過測試。

表達式分組

正則表達式也可以用圓括號分組。當你將正則表達式模式分組時,該分組會被視爲一個標準字符。可以像對普通字符一樣給該組使用特殊字符。

sed進階

多行命令

sed編輯器包含了三個可用來處理多行文本的特殊命令。

  • N: 將數據流中的下一行加進來創建一個多行組來處理
  • D: 刪除多行組中的一行
  • P: 打印多行組中的一行。

next命令

  1. 單行的next命令
    e.g.

sed ‘/header/{n; d}’ data.txt # 刪除含有header的行的下一行。

  1. 合併文本行
    多行版本的next命令(用大寫的N)會將下一文本行添加到模式空間中已有的文本後。這樣的作用是將數據流中的兩個文本行合併到同一個模式空間中 。文本用換行符分隔。
    e.g.

sed ‘/first/{N ; s/\n/ /}’ data.txt #查詢含有單詞first的那行文本。找到該行後,它會用N命令將下一行合併到那行,然後用替換命令s將揀選符替換成空格。

多行刪除命令

e.g.

sed ‘N ; /Systemm\nAdministrator/d’ datta.txt #會刪除合併後的兩行內容
sed ‘N ; /System\nAdministrator/D’ datta.txt # 會刪除模式空間中的第一行。

多行打印命令

多行打印命令(P)沒用了同樣的方法。它只打印多行模式空間中的第一行。

保持空間

模式空間(pattern space)是一塊活躍的緩衝區,在sed編輯器執行命令時它會保存待檢查的文本。但它並不是sed編輯器保存文本的唯一空間。
sed編輯器有另一塊稱作保持空間(hold space)的緩衝區域。有5條命令可用來操作保持空間:

命令 描述
h 將模式空間複製到保持空間
H 將模式空間附加到保持空間
g 將保持空間複製到模式空間
G 將保持空間附加到模式空間
x 交換模式空間和保持 空間的內容

排除命令

感嘆號命令(!)用來排除(negate)命令,也就是說原本會起作用的起作用。相當於取反的作。

改變流

分支

分支(branch)命令b的格式如下:

[address]b [label]

adddress參數決定了哪些行的數據會觸發分支命令。label參數定義了要跳轉到的位置。如果沒有加label參數,跳轉命令會跳轉到腳本 的結尾。

sed ‘{/first/b jump1 ; s/This is the /No jump on/
:jump1
s/This is the /Jump here on/}’ data.txt

e.g.

echo “This, is , a test, to, remove, commands.” | sed -n ‘{
:atart
s/,//1p
/,/b tart
}’

分支命令會在行中有逗號的情況下跳轉。在最後一個逗號被刪除後,分支命令不會再執行,腳本也就能正常停止了。

測試

格式:

[address]t [label]

e.g.

sed ‘{
s/firstmatched/
t
s/This is the /No match on/
}’ data.txt

第一替換命令會查找模式文本firstt。如果匹配了行中的模式,它就會替換文本,而且測試命令會路過後面的替換命令。如果第一個替換命令未能匹配模式,第二個替換命令就會被執行。

模式替代

&符號

&符號可以用來代表替換命令中的匹配的模式。不管模式匹配的是什麼樣的文本,你都可以在替代模式中使用&符號來使用這段文本。
e.g.

echo “The cat sleeps in his hat.” | sed ‘s/.at/"&"/g’
The “cat” sleeps in his “hat”.

替代單獨的單詞

sed編輯器用圓括號來定義替換模式中的子模式。你可以在替代模式中使用特殊字符來引用每個子模式。替代字符由反斜線和數字組成。數字表明子模式的位置。sed編輯器會給第一個子模式分配字符\1,給第二個子模式分配字符\2,依此類推。
e.g.

echo “The System Administrator manuall” | sed ’
s/(System) Administrator/\1 User’

這個替換命令用一對圓括號將單詞System括起來,將其標示爲一個子模式。然後它在替代模式中使用\1來提取第一個匹配的子模式。

在腳本中使用sed

創建sed實用工具

加倍行間距

sed ‘$!G’ data.txt

對可能 含有空白行的文件加倍行間距

sed ‘/^$/d ; $!G’ data.txt

給文件中的行編號

sed ‘=’ data.txt | sed ‘N; s/\n/ /’

打印末尾行

sed -n ‘$p’ data.txt

刪除行

刪除數據流中不需要的空白行。

  1. 刪除連續的空白行

sed ‘/./,/^$/!d’ data.txt

  1. 刪除開頭的空白行

sed ‘/./,$!d’

  1. 刪除結尾的空白行

sed ‘{
:start
/^\n*KaTeX parse error: Expected '}', got 'EOF' at end of input: /{d; N; b start }
}’

  1. 刪除HTML標籤

sed ‘s/<.*>//g’ data.txt

gawk進階

使用變量

所有編程語言共有的一個重要特性是使用變量來存取值。gawk編程語言支持兩種不同類型的變量:

  • 內建變量
  • 自定義變量

內建變量

  1. 字段和記錄分隔符變量
    數據字段變量:允許你使用美元符號和字段在該 記錄中的位置修士來引用記錄對應的字段。如第一個:$1。
    數據字段由字段分隔符來劃定的。默認情況下,字段分隔符是一個空白字符,也就是空格符或製表符。我們在命令行下可以使用-F或者gawk程序中使用特殊的內建變量FS來更改字段分隔符。
    gawk數據字段和記錄變量:
變量 描述
FILEDWIDTHS 由空格分隔的一列數字,定義了每個數據字段確切寬度
FS 輸入字段分隔符
RS 輸入記錄分隔符
OFS 輸出字段分隔符
ORS 輸出記錄分隔符
  1. 數據變量
    更多的gawk內建變量:
變量 描述
ARGC 當前命令行參數個數
ARGIND 當前文件在ARGV中的位置
ARGV 包含命令行參數的數組
CONVFMT 數字的轉換格式(參見printf語句),默認值爲%.6g
ENVIRON 當前Shell環境變量及其值組成的關聯數組
ERRNO 當讀取或關閉輸入文件發生錯誤時的系統錯誤號
FILENAME 用作GAWK輸入數據的數據文件的文件名
FNR 當前數據文件中的數據行數
IGNORECASE 設成非零值時,忽略gawk命令中出現的字符串的字符大小寫
NF 數據文件中的字段總數
NR 已處理的輸入記錄數
OFMT 數字的輸出格式,默認值爲%.6g
RLENGTH 由match函數所匹配的子字符串的長度
RSTART 由match函數所匹配的子字符串的起始位置

說明:跟shell變量不同,在腳本 中引用gawk變量時,變量名前不加美元符。

自定義變量

gawk自定義變量名可以是任意數目 的字母,數字和下劃線,但不能以數字開頭。而且區分大小寫。

  1. 在腳本 中給變量賦值
    在gawk程序 中給變量賦值跟在shell腳本 中賦值類似,都用賦值語句。
    e.g.

gawk ’
BEGIN{
testing=“This is a test”
print testing
}’
This is a test

  1. 在命令行上給變量賦值

處理數組

Gawk使用關聯數組提供數組功能 。

定義數組變量

可以用標準賦值語句 來定義 數組變量。格式如下:

var[index] = element

遍歷數組變量

可以使用for語句的一種特殊形式。

for (var in arrayy) {
print "Index: ", test, " - Value: ", var[test]
}

刪除數組變量

delete array[index]

使用模式

正則表達式

在使用正則表達式時,正則表達式必須出現在它要控制的程序腳本 的左花括號前。

gawk ‘BEGIN{FS=","} /11/{print $1}’ data

正則表達式/11/匹配了數據字段中含有字符串11的記錄。

匹配操作符

匹配操作符(matching operator)允許將正則表達式限定在記錄中的特定數據字段。匹配操作符的波浪線(~)可以指定匹配操作符,數字字段變量以及要匹配的正則表達式。
e.g.

gawk ‘BEGIN{FS=","} $2 ~ /^data2/{print $0}’ data

匹配操作符會用正則表達式/^data2/來比較第二個數據字段。

數學 表達式

除了正則表達式,你也可以在匹配模式中用數學表達式。
e.g.

gawkk -F: ‘$4==0{print $1}’ /etc/passwd

結構化命令

if語句

gawk編程語言支持標準的if-then-else格式的if語句。格式:

if (condition) statment

e.g.

gawk ‘{ if ($1 > 20) { x = $1 *2
print x
}
}’ datta

while語句

格式:

while (condition) {
statements
}

do-while語句

格式:

do {
stattements
} while (conditiion)

for語句

格式:

for( variable asssignmennt; coondition; iteration process)

格式化打印

gawk中的printf命令跟C語言的用法一致,格式如下:

printf “format string”, var1, var2 …

格式化指定符采用如下格式:

%[modifier]control-letter

其中control-leter是一個單字符代碼,用於指明顯示什麼類型的數據,而modifier則定義了可選的格式化特性。
格式化指定字符的控制字母表:

控制字母 描述
c 將一個數作爲ASCII字符顯示
d 顯示一個整數值
i 顯示一個整數值(跟d一樣)
e 用科學計數法顯示一個數
f 顯示一個浮點數
g 用科學計數法或浮點數顯示(選擇較短的格式)
o 顯示一個八進制數
s 顯示一個文本字符串
x 顯示一個十門進制數
X 顯示一個十六進制值,但用大寫字母A-F

除了控制字母外,還有3種修飾符可以用來進一步控制輸出。

  • widthh: 指定輸出字段最小寬度的數字值。如果輸出短於這個值 ,printf會將文本右對齊,並用空格進行填充。如果輸出比指定的寬度還要長,則按照實際長度輸出。
  • prec:這是一個數字值,指定浮點數中小數點後面位數,或者文本字符串顯示的最大字符數。
  • -(減號): 指明在向格式化空間中放入數據時採用左對齊而不是右對齊。

內建函數

gawk提供了不少內置函數,可進行一些常見的數學,字符串以及時間函數運算。

數學函數

函數 描述
atan2(x, y) x/y的反正切, x和y以弧度爲單位
cos(x) x的餘弦,x以弧度爲單位
exp(x) x的指數函數
int(x) x的整數部分,取靠近零一側的值
log(x) x的自然對數
randd() 比0大比1小的隨機浮點數
sin(x) x的正統,x以弧度爲單位
sqrt(x) x的平方根
srand(x) 爲計算隨機數指定 一個種子 值

除了標準數學函數外,gawk還支持一些按位操作數據的函數

函數 描述
and(v1, v2) 執行值v1和v2的按位運算
compl(vall) 執行val的補位運算
lshift(val,count) 將值val左移count位
or(v1, v2) 執行值v1和v2的按位或運算
rshift(val, count) 將值val右移count位
xor(v1, v2) 執行值v1和v2的按位異或運算

字符串函數

函數 描述
asort(s [,d]) 將數組s按數據元素值排序。索引值 會被替換成的排序順序的連續數字。另外,如果指定了d,則排序後的數組會存儲在數組d中
asorti(s [,d]) 將數組s按索引值排序。生成的數組會將作爲數據元素值,用連續數字索引來表明排序順序。另外如果指定了d,排序後的數組會存儲在數組d中
gensub(r,s,h [,t]) 查找變量$0或目標字符串t(如果提供了的話)來匹配正則表達式r。如果h是一個以g或G開頭的字符串,就用s替換掉匹配的文本。如果h是一個數字,它表示替換掉第h處r匹配的地方
gsub(r, s [,t]) 查找變量$0或目標字符串t(如果提供了的話)來匹配正則表達式r。如果找到了,就全部替換成字符串s
index(s,t) 返回字符串t在字符串s中的索引值,如果沒找到的話就返回0
length([s]) 返回字符串s的長度,如果沒有指定的話,返回$0的撒謊
match(s, r [,a]) 返回字符串s中正則表達式r出現位置的索引。如果指定了數組a,它會存儲s中匹配正則表達式的那部分
split(s, a [,r]) 將s用FS字符或正則表達式r(如果指定了的話)分開放到數組a中。返回字段的總數.
sprintf(format, variables) 用提供的format和variables返回一個類似於printf輸出的字符串
sub(r, s [,t]) 在變量$0或目標字符串t中查找正則表達式r的匹配。如果找到了,就用字符串s替換掉第一處理匹配。
substr(s, i [,n]) 返回s中從索引值i開始的n個字符組成的子字符串。如果未提供n,則返回s剩下的部分
toloweer(s) 將s中的所有字符轉換成小寫
tooupper(s) 將s中的所有字符轉換成大寫

時間函數

函數 描述
mktiime(datesppec) 將一個按YYYY MM DD HH MM SS [DST]格式指定的日期轉換成時間戳值
strftime(format [,timestamp]) 將當前時間的時間戳或tiimestammp(如果提供了的話)轉化格式化日期(採用shell函數date()的格式)
systime() 返回當前時間的時間戳

自定義函數

要定義自己的函數,必須用function關鍵字。

function name([variables]) {
statements
}

函數名必須能夠唯一標識函數。

使用自定義函數

在定義函數時,它必須出現在所有代碼塊之前(包括BEGIN代碼塊)。它有助於將函數代碼與gawk程序的其他部分分開。

創建函數庫

gawk提供了一種途徑來將多個函數放到一個庫文件中,這樣你就能在所有的gawk程序中使用了。
首先,你需要創建一個存儲所有gawk函數的文件
使用時間需要使用-f命令行參數來使用它們。

使用其它Shell

dash shell

zsh shell

創建實用的腳本

編寫簡單的腳本實用工具

創建與數據庫、Web及電子郵件相關的腳本

一些小有意思的腳本

附錄

A1. bash命令快速指南

命令 描述
: 擴展參數列表,執行重定向操作
. 讀取並執行指定文件中的命令(在當前shell環境中)
alias 爲指定命令定義一個別名
bg 將作業以後臺模式運行
bind 將鍵盤序列綁定到一個readline函數或宏
break 退出for,while,selecct或until循環
builtin 執行指定的shell內建命令
caller 返回活動子函數調用 的上下亠
cd 將當前目錄切換爲指定的目錄
command 執行指定的命令,無需進行通常的shell查找
compgenn 爲指定單詞生成可能的補全匹配
complete 顯示指定的單詞是如何補全的
compopt 修改指定單詞的補全選項
continue 繼續執行for, while,select或until循環的下一次迭代
declare 聲明一個變量或變量類型
dirs 顯示當前存儲目錄的列表
disown 從進程作業表中刪除指定的作業
echo 將指定字符串輸出到STDOUT
enable 啓用或禁用指定的內建shell命令
eval 將指定的參數拼接成一個命令,然後再執行該命令
exec 用指定命令替換shell進程
exit 強制shell以指定的退出狀態碼退出
export 設置子shell進程可用的變量
fc 從歷史記錄中選擇命令列表
fg 將作業以前臺模式運行
getopts 分析指定的位置參數
hash 查找並記住指定命令的全路徑名
help 顯示幫助文件
history 顯示命令歷史記錄
jobs 列出活動作業
kill 向指定的進程ID發送一個系統信號
let 計算一個數學表達式中的每個參數
local 在函數中創建一個作用域受限的變量
logout 退出登錄shell
mapfile 從STDIN讀取數據行,並將其加入索引數組
popd 從目錄棧中刪除記錄
printf 使用格式化字符串顯示文本
pushd 向目錄棧添加一個目錄
pwd 顯示當前工作目錄的路徑名
read 從STDIN讀取一行數據並將其賦給一個變量
readarray 從STDIN讀取數據行並將其放入索引數組
readonly 從STDIN讀取一行數據並將其賦給一個不可修改的變量
return 強制函數以某個值退出,這個值可以被調用腳本提取
set 設計並顯示環境變量的值和shell屬性
shift 將位置參數依次向下降一個位置
shopt 打開/關閉控制shell可選 行爲的變量值
source 讀取並執行指定文件中的命令
suspend 暫停shell的執行,直到收到一個SIGCONT信號
test 基於指定條件返回退出狀態碼0或1
times 顯示累計的用戶和系統時間
trap 如果收到了指定的系統信號,執行指定的命令
type 顯示指定的單詞如果作爲命令將會如何被解釋
typeset 聲明一個變量或變量類型
ulimit 爲系統用戶設置指定的資源的上限
umask 爲新建的文件和目錄設置默認權限
unalias 刪除指定的別名
unset 刪除指定的環境變量或shell屬性
wait 等待指定的進程完成,並返回退出狀態碼

A2. 常見的bash命令

命令 描述
bzip2 採用Burrows-Wheeler塊排序文本壓縮算法和霍夫曼編碼進行壓縮
cat 列出指定文件的內容
chage 修改指定系統用戶賬戶的密碼過期日期
chfn 修改指定用戶賬戶的備註信息
chgrp 修改指定文件或目錄的默認屬組
chmod 爲指定文件或目錄修改系統安全權限
chown 修改指定文件或目錄的默認發證
chpasswd 讀取一個包含登錄名/密碼的文件並更新密碼
chsh 修改指定用戶賬戶的默認shell
clear 從終端仿真器或虛擬控制檯終端刪除文本
compress 最初的Unix文件壓縮工具
coproc 在後臺模式中生成子shell,並執行指定的命令
cp 將指定文件複製到另一個位置
crontab 初始化用戶的crontable對應的編輯器(如果允許的話)
cut 刪除文件行中指定的位置
date 以各種格式顯示日期
df 顯示所有掛載設備的當前磁盤空間使用情況
du 顯示指定文件路徑的磁盤使用情況
emacs 調用emacs文本編輯器
file 查看指定文件的文件類型
find 對文件進行遞歸查找
free 查看 系統上可用的和已用的內存
gawk 使用編程語言命令的流編輯器
grep 在文件中查找指定的文本字符串
gedit 調用 GNOME桌面編輯器
getopt 解析命令選項(包括長格式選項)
groups 顯示指定用戶的組成員關係
groupadd 創建新的系統組
groupmod 修改已有的系統級
gzip 採用Lempel-Ziv編碼的GNU項目壓縮工具
head 顯示指定文件內容的開頭部分
help 顯示bash內建命令的幫助頁面
killall 根據進程名向運行中的進程發送一個系統信號
kwrite 調用 KWrite文本編輯器
less 查看文件內容的高級方法
link 用別名創建一個指向文件的鏈接
ln 創建針對指定文件的符號鏈接或硬鏈接
ls 列出目錄內容
makewhatis 創建能夠使用手冊頁關鍵字進行搜索的whatis數據庫
man 顯示指定命令或話題的手冊頁
mkdir 在當前目錄下創建指定目錄
more 列出指定文件的內容,在每屏數據後暫停下來
mount 顯示虛擬文件系統上掛載的設備或將磁盤設備掛載到虛擬文件系統上
mv 重命令名或移動文件,文件夾
nano 調用nano文本編輯器
nice 在系統上使用不同優先級來運行命令
passwd 修改某個系統用戶的賬戶的密碼
ps 顯示系統上運行中進程的信息
pwd 顯示當前目錄
renice 修改系統上運行的優先級
rm 刪除文件
rmdir 刪除指定目錄
sed 使用編輯的文本流編輯器
sleep 在的一段時間內暫停bash shell操作
sort 基於指定的順序組織數據文件中的數據
stat 顯示指定文件的文件統計數據
sudo 以root用戶賬戶身價運行應用
tail 顯示指定文件內容的末尾內容
tar 將數據和目錄歸檔到 單個文件中
top 顯示活動進程以及其他重要的系統統計數據
touch 新建一個空文件,或更新一個已有文件的時間戳
umount 從虛擬文件系統上刪除一個已掛載的磁盤設備
uptime 顯示系統已運行了多久
useradd 新建一個系統用戶賬戶
uaserdel 刪除已有的一個系統賬戶
usermod 修改已有系統用戶賬戶
vi 調用vim文本編輯器
vmstat 生成一個詳盡的系統內存和CPU使用情況報告
whereis 顯示指定命令的相關文件,包括二進制文件,源代碼文件以及手冊頁
which 查找可執行文件的位置
who 顯示當前系統中的登錄用戶
whoami 顯示當前用戶的用戶名
xargs 從STDIN中獲取數據項,構建並執行命令
zip Windows下的PKZIP程序的Unix版本

A.3 環境變量

變量 描述
* 含有所有命令行參數(以單個文本值的形式)
@ 含有所有命令行參數(以多個文本值的形式)
# 命令行參數數目
最近使用的前臺退出狀態碼
- 當前命令行選項標記
$ 當前shell的進程ID
! 最近執行後臺PID
0 命令行中使用的命令名稱
_ shell的絕對路徑名
BASH 用戶調用shell的完整文件名
BASHOPTS 允許冒號分隔列表形式的shell選項
BASHPID 當前bash shell的進程ID
BASH_ALIASED 含有當前所用別名的數組
BASH_ARGC 當前子函數中的參數數量
BASH_ARGV 含有所有指定命令行參數的數組
BASH_CMDS 含有命令的內部的數組
BASH_COMMAND 當前正在被執行的命令名
BASH_ENV 如果設置了的話,每個bash腳本都會嘗試在運行前執行由該 變量定義的起始文件
BASH_EXECUTION_STRING 在-c命令行選項中用到的命令
BASH_LINENO 含有腳本 中每個命令的行號的數組
BASH_REMATCH 含有與指定的正則表達式匹配的文本元素的數組
BASH_SOURCE 含有shell中已聲明函數所在源文件名的數組
BASH_SUBSHELL 當前shell生成的子shell數目
BASH_VERSINFO 含有當前bash shell實例的主版本號和次版本號的數組
BASH_VERSION 當前bash shell實例的版本號
BASH_STRACFED 當設置一個有效的文件描述銜整數時,跟蹤輸出生成,並與診斷和錯誤信息分離開文件描述 符必須設置-x啓動
COLUMNS 含有當前bash shell實例使用的終端的寬度
COMP_CWORD 含有變量COMP_WORDS的索引值,COMP_WORD包含當前光標所在的位置
COMP_KEY 調用補全功能的按鍵
COMP_LINE 當前命令行
COMP_POINT 當前光標位置相對於當前命令起始位置的索引
COMP_TYPE 實例類型所對應的整數值
COMP_WORDBREAKS 在進行單詞補全時用作單詞分隔符的一組字符
COMP_WORDS 含有當前命令行上所有單詞的數組
COMPREPLY 含有由shell函數生成的可能補全碼的數組
COPROC 含有用於匿名協程I/O的文件描述符的數組
DIRSTACK 含有目錄棧當前內容的數組
EMACS 如果設置了該環境變量,則shell認爲其使用的是emacs shell緩衝區,同時禁止行編輯功能
ENV 當shell以POSIX模式調用時,每個bash腳本在運行之前都會執行由該環境變量所定義的起始文件
EUID 當前用戶的有效用戶ID
FCEDIT fc命令使用的默認編輯器
FIGNORE 以冒號分隔的後綴名列表,在文件名補全時會被忽略
FUNCNAME 當前執行的shell函數的名稱
FUNCNEST 嵌套函數的最高層級
GLOBIGNORE 以早號分隔的模式列表,定義了文件名展開時要忽略的文件名集合
GROUPS 含有當前用戶屬組的數組
histchars 控制歷史記錄展開的字符(最多可有3個)
HISTCMD 當前命令在歷史記錄中的編號
HISTCONTROL 控制哪些命令留在歷史記錄列表中
HISTFILE 保存shell歷史記錄列表的文件名(默認是.bash_history)
HISTFILESIZE 保存在歷史文件中的最大行數
HISTIGNORE 以冒號分隔的模式列表,用來決定哪些命令不存進歷史文件
HISTSIZE 最多在歷史文件中保存多少條命令
HISTIMEFORMAT 設置後,決定歷史文件條目的時間戳的格式字符串
HOSTFILE 含有shell在補全主機名時讀取的文件的名稱
HOSTNAME 當前主機的名稱
HOSTTYPE 當前運行bash shell的機器
IGNOREEOF shell在退出前必須收到連續的EOF字符的數量。如果這個值不存在,默認是1
INPUTRC readline初始化文件名(默認是.inputrc)
LANG shell的語言環境分類
LC_ALL 定義一個語言環境分類,它會覆蓋LANG變量
LC_COLLATE 設置對字符串值排定義了終端上可見的行數
名擴展和模式匹配時,如何解釋其中的字符
LC_MESSAGES 決定解釋前置美元符($)的雙引號字符串的語言環境設置
LC_NUMERIC 決定格式化數字時的所使用的語言環境設置
LINENO 腳本中當前執行代碼的行號
LINES 定義了終端上可見的行數
MACHTYPE 用“cpu公司系統”格式定義的系統類型
MAILCHECK shell多久查看一次新郵件(以秒爲單位,默認值是60)
MAPFILE 含有mapfile命令所讀入文本的數組,當沒有給出變量名的時候,使用該環境變量
OLDPWD shell之前的工作目錄
OPTERR 設置爲1時,bash shell會顯示getopts命令產生的錯誤
OSTYPE 定義了shell運行的操作系統
PIPESTATUS 含有前臺進程退出狀態碼的數組
POSIXLY_CORRECT 如果設置了該環境變量,bash會以POSIX模式啓動
PPID bash shell父進程的PID
PROMPT_COMMAND 如果設置該環境變量,在顯示命令行主提示符之前會執行這條命令
PS1 主命令行提示符字符串
PS2 次命令行提示符字符串
PS3 select命令的提示符
PS4 如果使用了bash的-x選項,在命令行顯示之前顯示的提示符
PWD 當前工作目錄
RANDOM 返回一個0~32 767的隨機數,對其賦值可作爲隨機數生成器的種子
READLINE_LINE 保存了readline行緩衝區中的內容
READLINE_POINT 當前readline行緩衝區的插入點位置
REPLY read命令的默認變量
SECONDS 自shell啓動到現在的秒數,對其賦值將會重置計時器
SHELL shell的全路徑名
SHELLOPTS 已啓用bash shell選項列表,由冒號分隔
SHLVL 表明shell層級,每次啓動一個新的bash shell時計數加1
TIMEFORMAT 指定了shell顯示的時間值的格式
TMOUT select和read命令在沒輸入的情況下等待多久(以秒爲單位)。默認值爲零,表示無限長
TMPDIR 如果設置成目錄名,shell會將其作爲臨時文件目錄
UID 當前用戶的真實用戶ID(數字形式)

可以用set內建命令來顯示這些環境變量。對於不同的Linux發行版,開機時設置的默認shell變量經常會不一樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章