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中國
捐贈 Let's Encrypt,共建安全的互聯網
隨著 Mozilla、蘋果和谷歌對沃通和 StartCom 這兩家 CA 公司處罰落定,很多使用這兩家 CA 所簽發證書的網站紛紛尋求新的證書籤發商。有一個非盈利組織可以為大家提供了免費、可靠和安全的 SSL 證書服務,這就是 Let's Encrypt 項目。現在,它需要您的幫助
Let's Encrypt 正式發布,已經保護 380 萬個域名
由於 Let's Encrypt 讓安裝 X.509 TLS 證書變得非常簡單,所以這個數量增長迅猛。
關於Linux防火牆iptables的面試問答
Nishita Agarwal是Tecmint的用戶,她將分享關於她剛剛經歷的一家公司(印度的一家私人公司Pune)的面試經驗。在面試中她被問及許多不同的問題,但她是iptables方面的專家,因此她想分享這些關於iptables的問題和相應的答案給那些以後可能會進行相關面試的人。 所有的問題和相應的答案都基於Nishita Agarwal的記憶並經過了重寫。 嗨,朋友!我叫Nishita Agarwal。我已經取得了理學學士學位,我的專業集中在UNIX和它的變種(BSD,Linux)。它們一直深深的吸引著我。我在存儲方面有1年多的經驗。我正在尋求職業上的變化,並將供職於印度的P
Lets Encrypt 已被所有主流瀏覽器所信任
旨在讓每個網站都能使用 HTTPS 加密的非贏利組織 Lets Encrypt 已經得了 IdenTrust的交叉簽名,這意味著其證書現在已經可以被所有主流的瀏覽器所信任。從這個裡程碑事件開始,訪問者訪問使用了Lets Encrypt 證書的網站不再需要特別配置就可以得到 HTTPS 安全保護了。 Lets Encrypt 的兩個中級證書 ...

















