Linux中國
命令行藝術
流暢地使用命令行是一個常被忽略的技能,或被認為是神秘的奧義。但是,它會以明顯而微妙的方式改善你作為工程師的靈活度和生產力。這是我在 Linux 上工作時發現的有用的命令行使用小竅門和筆記的精粹。有些小竅門是很基礎的,而有些是相當地特別、複雜、或者晦澀難懂。這篇文章不長,但是如果你可以使用並記得這裡的所有內容,那麼你就懂得很多了。
其中大部分最初出現在Quora上,但是考慮到興趣所在,似乎更應該放到 Github 上,這裡的人比我更能提出改進建議。如果你看到一個錯誤,或者更好的某種東西,請提交問題或 PR!(當然,提交前請看看必讀小節和已有的 PR/Issue。)
必讀
範圍:
- 本文是針對初學者和專業人員的,選題目標是覆蓋面廣(全都很重要)、有針對性(大多數情況下都給出具體實例)而簡潔(避免不必要內容以及你能在其它地方輕鬆找到的離題的內容)。每個小竅門在某種情形下都很必需的,或者能比替代品大大節省時間。
- 這是為 Linux 寫的。絕大部分條目都可以同樣應用到 MacOS(或者甚至 Cygwin)。
- 主要針對互動式 Bash,儘管大多數小竅門也可以應用到其它 shell,以及常規 Bash 腳本。
- 包括了「標準的」UNIX 命令以及那些需要安裝的軟體包(它們很重要,值得安裝)。
注意:
- 為了能在一篇文章內展示盡量多的東西,一些具體的信息會被放到引用頁里。你可以使用 Google 來獲得進一步的內容。(如果需要的話,)你可以使用
apt-get
/yum
/dnf
/pacman
/pip
/brew
來安裝這些新的程序。 - 使用 Explainshell 來獲取命令、參數、管道等內容的解釋。
基礎
- 學習基本 Bash 技能。實際上,鍵入
man bash
,然後至少瀏覽一遍所有內容;它很容易理解,沒那麼長。其它 shell 也不錯,但是 Bash 很強大,而且到處都可以找到(如果在你自己的筆記本上只學習 zsh、fish 之類,會在很多情形下受到限制,比如使用現存的伺服器時)。 - 至少學好一種基於文本的編輯器。理想的一個是 Vim(
vi
),因為在終端中編輯時隨時都能找到它(即使大多數時候你在使用 Emacs、一個大型的 IDE、或一個現代的時髦編輯器)。 - 學習怎樣使用
man
來閱讀文檔(好奇的話,用man man
來列出分區號,比如 1 是常規命令,5 是文件描述,8 用於管理員)。用apropos
找到幫助頁。了解哪些命令不是可執行程序,而是 Bash 內置的,你可以用help
和help -d
得到幫助。 - 學習使用
>
和<
來進行輸出和輸入重定向,以及使用|
來管道重定向,學習關於 stdout 和 stderr 的東西。 - 學習
*
(也許還有?
和{
...}
)文件通配擴展和應用,以及雙引號"
和單引號'
之間的區別。(更多內容請參看下面關於變數擴展部分)。 - 熟悉 Bash 作業管理:
&
, ctrl-z, ctrl-c,jobs
,fg
,bg
,kill
等等。 - 掌握
ssh
,以及通過ssh-agent
,ssh-add
等進行無密碼驗證的基礎技能。 - 基本的文件管理:
ls
和ls -l
(特別是,知道ls -l
各個列的意義),less
,head
,tail
和tail -f
(或者更好的less +F
),ln
和ln -s
(知道硬鏈接和軟鏈接的區別,以及硬鏈接相對於軟鏈接的優勢),chown
,chmod
,du
(用於查看磁碟使用率的快速摘要:du -sk *
)。文件系統管理:df
,mount
,fdisk
,mkfs
,lsblk
。 - 基本的網路管理:
ip
或ifconfig
,dig
。 - 熟知正則表達式,以及各種使用
grep
/egrep
的選項。-i
,-o
,-A
和-B
選項值得掌握。 - 學會使用
apt-get
,yum
,dnf
或pacman
(這取決於你的發行版)來查找並安裝軟體包。確保你可以用pip
來安裝基於 Python 的命令行工具(下面的一些東西可以很容易地通過pip
安裝)。
日常使用
- 在Bash中,使用 tab 補完參數,使用 ctrl-r 來搜索命令歷史。
- 在Bash中,使用 ctrl-w 來刪除最後的單詞,使用 ctrl-u 來刪除整行,返回行首。使用 alt-b 和 alt-f 來逐詞移動,使用 ctrl-k 來清除到行尾的內容,以及使用 ctrl-l 清屏。參見
man readline
來查看 Bash 中所有默認的鍵盤綁定,有很多。例如,alt-. 可以循環顯示先前的參數,而alt- 擴展通配。(LCTT 譯註:關於 Bash 下的快捷鍵,可以參閱: </article-5660-1.html> ) - 另外,如果你喜歡 vi 風格的鍵盤綁定,可以使用
set -o vi
。 - 要查看最近用過的命令,請使用
history
。 有許多縮寫形式,比如!$
(上次的參數)和!!
(上次的命令),雖然使用ctrl-r
和alt-.
更容易些。(LCTT 譯註:關於歷史擴展功能,可以參閱: </article-5658-1.html> ) - 返回先前的工作目錄:
cd -
- 如果你命令輸入到一半,但是改變主意了,可以敲 alt-# 來添加一個
#
到開頭,然後將該命令作為注釋輸入(或者使用快捷鍵 ctrl-a, #,enter 輸入)。然後,你可以在後面通過命令歷史來回到該命令。 - 使用
xargs
(或parallel
),它很強大。注意,你可以控制每行(-L
)執行多少個項目,以及並行執行(-P
)。如果你不確定它是否會做正確的事情,可以首先使用xargs echo
。同時,使用-I{}
也很方便。樣例:
find . -name '*.py' | xargs grep some_function
cat hosts | xargs -I{} ssh root@{} hostname
pstree -p
對於顯示進程樹很有幫助。- 使用
pgrep
和pkill
來按名稱查找進程或給指定名稱的進程發送信號(-f
很有幫助)。 - 掌握各種可以發送給進程的信號。例如,要掛起進程,可以使用
kill -STOP [pid]
。完整的列表可以查閱man 7 signal
。 - 如果你想要一個後台進程一直保持運行,使用
nohup
或disown
。 - 通過
netstat -lntp
或ss -plat
檢查哪些進程在監聽(用於 TCP,對 UDP 使用-u
替代-t
)。 lsof
來查看打開的套接字和文件。- 在 Bash 腳本中,使用
set -x
調試腳本輸出。儘可能使用嚴格模式。使用set -e
在遇到錯誤時退出。也可以使用set -o pipefail
,對錯誤進行嚴格處理(雖然該話題有點微妙)。對於更複雜的腳本,也可以使用trap
。 - 在 Bash 腳本中,子 shell(寫在括弧中的)是組合命令的便利的方式。一個常見的例子是臨時移動到一個不同的工作目錄,如:
# 在當前目錄做些事
(cd /some/other/dir; other-command)
# 繼續回到原目錄
- 注意,在 Bash 中有大量的各種各樣的變數擴展。檢查一個變數是否存在:
${name:?error message}
。例如,如果一個Bash腳本要求一個單一參數,只需寫input_file=${1:?usage: $0 input_file}
。算術擴展:i=$(( (i + 1) % 5 ))
。序列:{1..10}
。修剪字元串:${var%suffix}
和${var#prefix}
。例如,ifvar=foo.pdf
,那麼echo ${var%.pdf}.txt
會輸出foo.txt
。 - 命令的輸出可以通過
<(some command)
作為一個文件來處理。例如,將本地的/etc/hosts
和遠程的比較:
diff /etc/hosts <(ssh somehost cat /etc/hosts)
- 了解 Bash 中的「嵌入文檔」,就像在
cat <<EOF ...
中。 - 在 Bash 中,通過:
some-command >logfile 2>&1
同時重定向標準輸出和標準錯誤。通常,要確保某個命令不再為標準輸入打開文件句柄,而是將它捆綁到你所在的終端,添加</dev/null
是個不錯的做法。 man ascii
可以得到一個不錯的ASCII表,帶有十六進位和十進位值兩種格式。對於常規編碼信息,man unicode
,man utf-8
和man latin1
將很有幫助。- 使用
screen
或tmux
來複用屏幕,這對於遠程 ssh 會話尤為有用,使用它們來分離並重連到會話。另一個只用於保持會話的最小可選方案是dtach
。 - 在 ssh 中,知道如何使用
-L
或-D
(偶爾也用-R
)來打開埠通道是很有用的,如從一台遠程伺服器訪問網站時。 - 為你的 ssh 配置進行優化很有用;例如,這個
~/.ssh/config
包含了可以避免在特定網路環境中連接被斷掉的情況的設置、使用壓縮(這對於通過低帶寬連接使用 scp 很有用),以及使用一個本地控制文件來開啟到同一台伺服器的多通道:
TCPKeepAlive=yes
ServerAliveInterval=15
ServerAliveCountMax=6
Compression=yes
ControlMaster auto
ControlPath /tmp/%r@%h:%p
ControlPersist yes
- 其它一些與 ssh 相關的選項對會影響到安全,請小心開啟,如各個子網或主機,或者在信任的網路中:
StrictHostKeyChecking=no
,ForwardAgent=yes
- 要獲得八進位格式的文件的許可權,這對於系統配置很有用而用
ls
又沒法查看,而且也很容易搞得一團糟,可以使用像這樣的東西:
stat -c '%A %a %n' /etc/timezone
- 對於從另一個命令的輸出結果中交互選擇值,可以使用
percol
。 - 對於基於另一個命令(如
git
)輸出的文件交互,可以使用fpp
(路徑選擇器)。 - 要為當前目錄(及子目錄)中的所有文件構建一個簡單的 Web 伺服器,讓網路中的任何人都可以獲取,可以使用:
python -m SimpleHTTPServer 7777
(使用埠 7777 和 Python 2)。
處理文件和數據
- 要在當前目錄中按名稱定位文件,
find . -iname '*something*'
(或者相類似的)。要按名稱查找任何地方的文件,使用locate something
(但請記住,updatedb
可能還沒有索引最近創建的文件)。 - 對於源代碼或數據文件進行的常規搜索(要比
grep -r
更高級),使用ag
。 - 要將 HTML 轉成文本:
lynx -dump -stdin
。 - 對於 Markdown、HTML,以及各種類型的文檔轉換,可以試試
pandoc
。 - 如果你必須處理 XML,
xmlstarlet
雖然有點老舊,但是很好用。 - 對於 JSON,使用
jq
。 - 對於 Excel 或 CSV 文件,csvkit 提供了
in2csv
,csvcut
,csvjoin
,csvgrep
等工具。 - 對於亞馬遜 S3 ,
s3cmd
會很方便,而s4cmd
則更快速。亞馬遜的aws
則是其它 AWS 相關任務的必備。 - 掌握
sort
和uniq
,包括 uniq 的-u
和-d
選項——參見下面的單行程序。 - 掌握
cut
,paste
和join
,它們用於處理文本文件。很多人會使用cut
,但常常忘了join
。 - 了解
tee
,它會將 stdin 同時複製到一個文件和 stdout,如ls -al | tee file.txt
。 - 知道 locale 會以微妙的方式對命令行工具產生大量的影響,包括排序的順序(整理)以及性能。大多數安裝好的 Linux 會設置
LANG
或其它 locale 環境變數為本地設置,比如像 US English。但是,你要明白,如果改變了本地環境,那麼排序也將改變。而且 i18n 過程會讓排序或其它命令的運行慢好多倍。在某些情形中(如像下面那樣的設置操作或唯一性操作),你可以安全地整個忽略緩慢的 i18n 過程,然後使用傳統的基於位元組的排序順序export LC_ALL=C
。 - 了解基本的改動數據的
awk
和sed
技能。例如,計算某個文本文件第三列所有數字的和:awk '{ x += $3 } END { print x }'
。這可能比 Python 的同等操作要快3倍,而且要短3倍。 - 在一個或多個文件中,替換所有出現在特定地方的某個字元串:
perl -pi.bak -e 's/old-string/new-string/g' my-files-*.txt
- 要立即根據某個模式對大量文件重命名,使用
rename
。對於複雜的重命名,repren
可以幫助你達成。
# 恢復備份文件 foo.bak -> foo:
rename 's/.bak$//' *.bak
# 完整的文件名、目錄名 foo -> bar:
repren --full --preserve-case --from foo --to bar .
- 使用
shuf
來從某個文件中打亂或隨機選擇行。 - 了解
sort
的選項。知道這些鍵是怎麼工作的(-t
和-k
)。特別是,注意你需要寫-k1,1
來只通過第一個欄位排序;-k1
意味著根據整行排序。 - 穩定排序(
sort -s
)會很有用。例如,要首先按欄位2排序,然後再按欄位1排序,你可以使用sort -k1,1 | sort -s -k2,2
- 如果你曾經需要在 Bash 命令行中寫一個水平製表符(如,用於 -t 參數的排序),按ctrl-v [Tab],或者寫
$'t'
(後面的更好,因為你可以複製/粘貼)。 - 對源代碼進行補丁的標準工具是
diff
和patch
。 用diffstat
來統計 diff 情況。注意diff -r
可以用於整個目錄,所以可以用diff -r tree1 tree2 | diffstat
來統計(兩個目錄的)差異。 - 對於二進位文件,使用
hd
進行簡單十六進位轉儲,以及bvi
用於二進位編輯。 - 還是用於二進位文件,
strings
(加上grep
等)可以讓你找出一點文本。 - 對於二進位文件的差異(delta 壓縮),可以使用
xdelta3
。 - 要轉換文本編碼,試試
iconv
吧,或者對於更高級的用途使用uconv
;它支持一些高級的 Unicode 的東西。例如,這個命令可以轉換為小寫並移除所有重音符號(通過擴展和丟棄):
uconv -f utf-8 -t utf-8 -x '::Any-Lower; ::Any-NFD; [:Nonspacing Mark:] >; ::Any-NFC; ' < input.txt > output.txt
- 要將文件分割成幾個部分,來看看
split
(按大小分割)和csplit
(按格式分割)吧。 - 使用
zless
,zmore
,zcat
和zgrep
來操作壓縮文件。
系統調試
- 對於 Web 調試,
curl
和curl -I
很方便靈活,或者也可以使用它們的同行wget
,或者更現代的httpie
。 - 要了解磁碟、CPU、網路的狀態,使用
iostat
,netstat
,top
(或更好的htop
)和(特別是)dstat
。它們對於快速獲知系統中發生的狀況很好用。 - 對於更深層次的系統總覽,可以使用
glances
。它會在一個終端窗口中為你呈現幾個系統層次的統計數據,對於快速檢查各個子系統很有幫助。 - 要了解內存狀態,可以運行
free
和vmstat
,看懂它們的輸出結果吧。特別是,要知道「cached」值是Linux內核為文件緩存所佔有的內存,因此,要有效地統計「free」值。 - Java 系統調試是一件截然不同的事,但是對於 Oracle 系統以及其它一些 JVM 而言,不過是一個簡單的小把戲,你可以運行
kill -3 <pid>
,然後一個完整的堆棧追蹤和內存堆的摘要(包括常規的垃圾收集細節,這很有用)將被轉儲到stderr/logs。 - 使用
mtr
作路由追蹤更好,可以識別網路問題。 - 對於查看磁碟滿載的原因,
ncdu
會比常規命令如du -sh *
更節省時間。 - 要查找佔用帶寬的套接字和進程,試試
iftop
或nethogs
吧。 - (Apache附帶的)
ab
工具對於臨時應急檢查網路伺服器性能很有幫助。對於更複雜的負載測試,可以試試siege
。 - 對於更仔細的網路調試,可以用
wireshark
,tshark
或ngrep
。 - 掌握
strace
和ltrace
。如果某個程序失敗、掛起或崩潰,而你又不知道原因,或者如果你想要獲得性能的大概信息,這些工具會很有幫助。注意,分析選項(-c
)和使用-p
關聯運行進程。 - 掌握
ldd
來查看共享庫等。 - 知道如何使用
gdb
來連接到一個運行著的進程並獲取其堆棧追蹤信息。 - 使用
/proc
。當調試當前的問題時,它有時候出奇地有幫助。樣例:/proc/cpuinfo
,/proc/xxx/cwd
,/proc/xxx/exe
,/proc/xxx/fd/
,/proc/xxx/smaps
。 - 當調試過去某個東西為何出錯時,
sar
會非常有幫助。它顯示了 CPU、內存、網路等的歷史統計數據。 - 對於更深層的系統和性能分析,看看
stap
(SystemTap),perf
和sysdig
吧。 - 確認是正在使用的 Linux 發行版版本(支持大多數發行版):
lsb_release -a
。 - 每當某個東西的行為異常時(可能是硬體或者驅動器問題),使用
dmesg
。
單行程序
這是將命令連成一行的一些樣例:
- 有時候通過
sort
/uniq
對文本文件做交集、並集和差集運算時,這個例子會相當有幫助。假定a
和b
是已經進行了唯一性處理的文本文件。這會很快,而且可以處理任意大小的文件,總計可達數千兆位元組。(Sort不受內存限制,不過如果/tmp
放在一個很小的根分區的話,你可能需要使用-T
選項。)也可參見上面關於LC_ALL
的註解和-u
選項(參見下面例子更清晰)。
sh cat a b | sort | uniq > c # c 是 a 和 b 的並集
cat a b | sort | uniq -d > c # c 是 a 和 b 的交集
cat a b b | sort | uniq -u > c # c 是 a 減去 b 的差集
- 使用
grep . *
來可視化查看一個目錄中的所有文件的所有內容,例如,對於放滿配置文件的目錄:/sys
,/proc
,/etc
。 - 對某個文本文件的第三列中所有數據進行求和(該例子可能比同等功能的Python要快3倍,而且代碼也少於其3倍):
awk '{ x += $3 } END { print x }' myfile
- 如果想要查看某個文件樹的大小/日期,該例子就像一個遞歸
ls -l
,但是比ls -lR
要更容易讀懂:
find . -type f -ls
- 只要可以,請使用
xargs
或parallel
。注意,你可以控制每行(-L
)執行多少個項目,以及並行執行(-P
)。如果你不確定它是否會做正確的事情,可以首先使用xargs echo
。同時,使用-I{}
也很方便。樣例:
find . -name '*.py' | xargs grep some_function
cat hosts | xargs -I{} ssh root@{} hostname
- 比如說,你有一個文本文件,如 Web 伺服器的日誌,在某些行中出現了某個特定的值,如 URL 中出現的
acct_id
參數。如果你想要統計有多少個acct_id
的請求:
cat access.log | egrep -o 'acct_id=[0-9]+' | cut -d= -f2 | sort | uniq -c | sort -rn
- 運行該函數來獲得來自本文的隨機提示(解析Markdown並從中提取某個項目):
function taocl() {
curl -s https://raw.githubusercontent.com/jlevy/the-art-of-command-line/master/README.md |
pandoc -f markdown -t html |
xmlstarlet fo --html --dropdtd |
xmlstarlet sel -t -v "(html/body/ul/li[count(p)>0])[$RANDOM mod last()+1]" |
xmlstarlet unesc | fmt -80
}
晦澀難懂,但卻有用
expr
:實施算術或布林操作,或者求正則表達式的值m4
:簡單的宏處理器yes
:大量列印一個字元串cal
:漂亮的日曆env
:(以特定的環境變數設置)運行一個命令(腳本中很有用)look
:查找以某個字元串開頭的英文單詞(或文件中的行)cut
和paste
以及join
:數據處理fmt
:格式化文本段落pr
:格式化文本為頁/列fold
:文本折行column
:格式化文本為列或表expand
和unexpand
:在製表符和空格間轉換nl
:添加行號seq
:列印數字bc
:計算器factor
:分解質因子gpg
:加密並為文件簽名toe
:terminfo 條目表nc
:網路調試和數據傳輸socat
:套接字中繼和 tcp 埠轉發(類似netcat
)slurm
:網路流量可視化dd
:在文件或設備間移動數據file
:識別文件類型tree
:以樹形顯示目錄及子目錄;類似ls
,但是是遞歸的。stat
:文件信息tac
:逆序列印文件shuf
:從文件中隨機選擇行comm
:逐行對比分類排序的文件hd
和bvi
:轉儲或編輯二進位文件strings
:從二進位文件提取文本tr
:字元轉譯或處理iconv
或uconv
:文本編碼轉換split
和csplit
:分割文件units
:單位轉換和計算;將每雙周(fortnigh)一浪(浪,furlong,長度單位,約201米)轉換為每瞬(blink)一緹(緹,twip,一種和屏幕無關的長度單位)(參見: /usr/share/units/definitions.units)(LCTT 譯註:這都是神馬單位啊!)7z
:高比率文件壓縮ldd
:動態庫信息nm
:目標文件的符號ab
:Web 伺服器基準測試strace
:系統調用調試mtr
:用於網路調試的更好的路由追蹤軟體cssh
:可視化並發 shellrsync
:通過 SSH 同步文件和文件夾wireshark
和tshark
:抓包和網路調試ngrep
:從網路層摘取信息host
和dig
:DNS查詢lsof
:處理文件描述符和套接字信息dstat
:有用的系統統計數據glances
:高級,多個子系統概覽iostat
:CPU和磁碟使用率統計htop
:top的改進版last
:登錄歷史w
:誰登錄進來了id
:用戶/組身份信息sar
:歷史系統統計數據iftop
或nethogs
:按套介面或進程的網路使用率ss
:套介面統計數據dmesg
:啟動和系統錯誤信息hdparm
:SATA/ATA 磁碟操作/改善性能lsb_release
:Linux 發行版信息lsblk
:列出塊設備,以樹形展示你的磁碟和分區lshw
:硬體信息fortune
,ddate
和sl
:嗯,好吧,它取決於你是否認為蒸汽機車和 Zippy 引用「有用」
更多資源
免責聲明
除了非常小的任務外,其它都寫出了代碼供大家閱讀。伴隨力量而來的是責任。事實是,你能在Bash中做的,並不意味著是你所應該做的!;)
via: https://github.com/jlevy/the-art-of-command-line
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive
對這篇文章感覺如何?
太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
More in:Linux中國
如何通過 VLC 使用字幕
使用 VLC 媒體播放器播放和管理字幕的新手指南。
Unix 桌面:在 Linux 問世之前
僅僅開源還不足以實現開放,還需開放標準和建立共識。
Valve 對於 Ubuntu 的 Snap 版本的 Steam 並不滿意:原因何在
你可能會發現,Snap 版本的 Steam 並不如你期待的那樣好,你怎麼看?
Wine 9.0 發布,實驗性地加入了 Wayland 驅動
Wine 的這個新版本正在為未來做好準備!