打造高效的工作环境 – SHELL 篇
注:本文由雷俊(Javaer/Emacser)和我一起編輯,所以文章版權歸雷俊與我共同所有,轉載者必需注明出處和我們兩位作者。原文最早發于酷殼微信公眾號,后來我又做了一些修改,再發到博客這邊。
程序員是一個很懶的群體,總想著能夠讓代碼為自己干活,他們不斷地把工作生活中的一些事情用代碼自動化了,從而讓整個社會的效率運作地越來越高。所以,程序員在準備去優化這個世界的時候,都會先要優化自己的工作環境,是所謂“工欲善其事,必先利其器”。
我們每個程序員都應該打造一套讓自己更為高效的工作環境。那怕就是讓你少輸入一次命令,少按一次鍵,少在鼠標和鍵盤間切換一次,都會讓程序員的工作變得更為的高效。所以,程序員一般需要一臺性能比較好,不會因為開了太多的網頁或程序就卡得不行的電腦,還要配備多個顯示器,一個顯示器寫代碼,一個查文檔,一個測試運行結果,而不必在各種窗口來來回回的切換……在大量的窗口間切換經常會迷路,而且也容易出錯(分不清線上或測試環境)……
除了硬件上的裝備,軟件上也是能夠提升程序員生產力的地方,在軟件層面提升程序員生產力的東西有一個很重要的事就是命令行和腳本,使用鼠標和圖形界面則會大大降低程序員的生產力。酷殼以前也寫過一些,如《你可能不知道的Shell》和《?應該知道的Linux技巧》,但是Unix/Linux Shell就是一個大寶庫,怎么寫也寫不完,不然,怎么會有“Where is the Shell, there is a way”。
?
命令行
在不同的操作系統下,都有著很不錯的命令行工具,比如 Mac 下的?Iterm2,Linux 下的原生命令行,如果你是在 Windows 下工作,問題也不大,因為 Windows 下現在有了?WSL。WSL 提供了一個由微軟開發的Linux兼容的內核接口(不包含Linux內核代碼),然后可以在其上運行GNU用戶空間,例如 Ubuntu,openSUSE,SUSE Linux Enterprise Server,Debian和Kali Linux。這樣的用戶空間可能包含 Bash shell 和命令語言,使用本機 GNU/Linux 命令行工具(sed,awk 等),編程語言解釋器(Ruby,Python 等),甚至是圖形應用程序(使用主機端的X窗口系統)。
使用命令行可以完成所有日常的操作,新建文件夾(mkdir)、新建文件(touch)、移動(mv)、復制(cp)、刪除(rm)等等。而且使用 Linux/Unix 命令行最好的方式是可以用?awk、sed、grep、xargs、find、sort?等等這樣的命令,然后用管道把其串起來,就可以完成一個你想要的功能,尤其是一些簡單的數據統計功能。這是Linux命令行不可比擬的優勢。比如:
- 查看連接你服務器 top10 用戶端的 IP 地址:
netstat -nat | awk '{print $5}' | awk -F ':' '{print $1}' | sort | uniq -c | sort -rn | head -n 10
- 查看一下你最常用的10個命令:
cat .bash_history | sort | uniq -c | sort -rn | head -n 10 (or cat .zhistory | sort | uniq -c | sort -rn | head -n 10
(注:awk?和?sed?是兩大神器,所以,我以前的也有兩篇文章來介紹它們——《awk簡明教程》和《sed簡明教程》,你可以前往一讀)
在命令行中使用?alias?可以將使用頻率很高命令或者比較復雜的命令合并成一個命令,或者修改原生的命令。
下面這幾個命令,可能是你天天都在敲的。所以,你應該設置成 alias 來提高效率
alias nis="npm install --save " alias svim='sudo vim' alias mkcd='foo(){ mkdir -p "$1"; cd "$1" }; foo ' alias install='sudo apt get install' alias update='sudo apt-get update; sudo apt-get upgrade' alias ..="cd .." alias ...="cd ..; cd .." alias www='python -m SimpleHTTPServer 8000' alias sock5='ssh -D 8080 -q -C -N -f user@your.server'你還可以參考如下的一些文章,看看別人是怎么用好?alias?的
- 30 Handy Bash Shell Aliases For Linux / Unix / Mac OS X
- What are your favorite bash aliases?
- 23 Handy Bash Shell Aliases For Unix, Linux, and Mac OS X
- A few more of my favorite Bash aliases
命令行中除了原生的命令之外,還有很多可以提升使用體驗的工具。下面羅列一些很不錯的命令,把原生的命令增強地很厲害:
- fasd?增強了?cd?命令 。
- bat?增強了?cat?命令 。如果你想要有語法高亮的?cat,可以試試?ccat?命令。
- exa?增強了?ls?命令,如果你需要在很多目錄上瀏覽各種文件 ,ranger?命令可以比?cd?和?cat?更有效率,甚至可以在你的終端預覽圖片。
- fd?是一個比?find?更簡單更快的命令,他還會自動地忽略掉一些你配置在?.gitignore?中的文件,以及?.git?下的文件。
- fzf?會是一個很好用的文件搜索神器,其主要是搜索當前目錄以下的文件,還可以使用?fzf --preview 'cat {}'邊搜索文件邊瀏覽內容。
- grep?是一個上古神器,然而,ack、ag?和?rg?是更好的grep,和上面的?fd一樣,在遞歸目錄匹配的時候,會使用你配置在?.gitignore?中的規則。
- rm?是一個危險的命令,尤其是各種?rm -rf …,所以,trash?是一個更好的刪除命令。
- man?命令是好讀文檔的命令,但是man的文檔有時候太長了,所以,你可以試試?tldr命令,把文檔上的一些示例整出來給你看。
- 如果你想要一個圖示化的ping,你可以試試?prettyping?。
- 如果你想搜索以前打過的命令,不要再用 Ctrl +R 了,你可以使用加強版的?hstr? 。
- htop? 是 top 的一個加強版。然而,還有很多的各式各樣的top,比如:用于看IO負載的?iotop,網絡負載的?iftop, 以及把這些top都集成在一起的?atop。
- ncdu? 比 du 好用多了用。另一個選擇是?nnn。
- 如果你想把你的命令行操作建錄制成一個 SVG 動圖,那么你可以嘗試使用?asciinema?和?svg-trem?。
- httpie?是一個可以用來替代?curl?和?wget?的 http 客戶端,httpie?支持 json 和語法高亮,可以使用簡單的語法進行 http 訪問:?http -v github.com。
- tmux?在需要經常登錄遠程服務器工作的時候會很有用,可以保持遠程登錄的會話,還可以在一個窗口中查看多個 shell 的狀態。
- Taskbook?是可以完全在命令行中使用的任務管理器 ,支持 ToDo 管理,還可以為每個任務加上優先級。
- sshrc?是個神器,在你登錄遠程服務器的時候也能使用本機的 shell 的 rc 文件中的配置。
- goaccess??這個是一個輕量級的分析統計日志文件的工具,主要是分析各種各樣的 access log。
關于這些增加命令,主要是參考自下面的這些文章
Shell 和腳本
shell 是可以與計算機進行高效交互的文本接口。shell 提供了一套交互式的編程語言(腳本),shell的種類很多,比如?sh、bash、zsh?等。
shell 的生命力很強,在各種高級編程語言大行其道的今天,很多的任務依然離不開 shell。比如可以使用 shell 來執行一些編譯任務,或者做一些批處理任務,初始化數據、打包程序等等。
現在比較流行的是?zsh?+?oh-my-zsh?+?zsh-autosuggestions?的組合,你也可以試試看。其中 zsh 和 oh-my-zsh 算是常規操作了,但是 zsh-autosuggestions 特別有用,可以超級快速的幫你補全你輸入過的命令,讓命令行的操作更加高效。
另外,fish?也是另外一個牛逼的shell,比如:命令行自動完成(根據歷史記錄),命令行命令高亮,當你要輸入命令行參數的時候,自動提示有哪些參數…… fish在很多地方也是用起來很爽的。和上面的 oh-my-zsh 有點不分伯仲了。
你也許會說,用 Python 腳本或 PHP 來寫腳本會比 Shell 更好更沒有 bug,但我要申辯一下:
- 其一,如果你有一天要維護線上機器的時候,或是到了銀行用戶的系統(與外網完全隔離,而且服務器上沒有安裝 Python/PHP 或是他們的的高級庫,那么,你只有 Shell 可以用了)。
- 其二,而且,如果要跟命令行交互很多的話,Shell 是不二之選,試想一下,如果你要去 100 臺遠程的機器上查access.log 日志中有沒有某個錯誤,完成這個工作你是用 PHP/Python 寫腳本快還是用 Shell 寫腳本快呢?
所以,我們還要學會只使用傳統的grep/awk/sed等等這些POSIX的原生的系統默認安裝的命令。
當然,要寫好一個腳本并不容易,下面有一些小模板供你參考:
處理命令行參數的一個樣例
while [ "$1" != "" ]; docase $1 in-s ) shift SERVER=$1 ;; -d ) shiftDATE=$1 ;;--paramter|p ) shiftPARAMETER=$1;;-h|help ) usage # function callexit ;;* ) usage # All other parametersexit 1esacshift done命令行菜單的一個樣例
#!/bin/bash # Bash Menu Script ExamplePS3='Please enter your choice: ' options=("Option 1" "Option 2" "Option 3" "Quit") select opt in "${options[@]}" docase $opt in"Option 1")echo "you chose choice 1";;"Option 2")echo "you chose choice 2";;"Option 3")echo "you chose choice $REPLY which is $opt";;"Quit")break;;*) echo "invalid option $REPLY";;esac done顏色定義,你可以使用?echo -e "${Blu}blue ${Red}red ${RCol}etc...."?進行有顏色文本的輸出
RCol='\e[0m' # Text Reset# Regular Bold Underline High Intensity BoldHigh Intens Background High Intensity Backgrounds Bla='\e[0;30m'; BBla='\e[1;30m'; UBla='\e[4;30m'; IBla='\e[0;90m'; BIBla='\e[1;90m'; On_Bla='\e[40m'; On_IBla='\e[0;100m'; Red='\e[0;31m'; BRed='\e[1;31m'; URed='\e[4;31m'; IRed='\e[0;91m'; BIRed='\e[1;91m'; On_Red='\e[41m'; On_IRed='\e[0;101m'; Gre='\e[0;32m'; BGre='\e[1;32m'; UGre='\e[4;32m'; IGre='\e[0;92m'; BIGre='\e[1;92m'; On_Gre='\e[42m'; On_IGre='\e[0;102m'; Yel='\e[0;33m'; BYel='\e[1;33m'; UYel='\e[4;33m'; IYel='\e[0;93m'; BIYel='\e[1;93m'; On_Yel='\e[43m'; On_IYel='\e[0;103m'; Blu='\e[0;34m'; BBlu='\e[1;34m'; UBlu='\e[4;34m'; IBlu='\e[0;94m'; BIBlu='\e[1;94m'; On_Blu='\e[44m'; On_IBlu='\e[0;104m'; Pur='\e[0;35m'; BPur='\e[1;35m'; UPur='\e[4;35m'; IPur='\e[0;95m'; BIPur='\e[1;95m'; On_Pur='\e[45m'; On_IPur='\e[0;105m'; Cya='\e[0;36m'; BCya='\e[1;36m'; UCya='\e[4;36m'; ICya='\e[0;96m'; BICya='\e[1;96m'; On_Cya='\e[46m'; On_ICya='\e[0;106m'; Whi='\e[0;37m'; BWhi='\e[1;37m'; UWhi='\e[4;37m'; IWhi='\e[0;97m'; BIWhi='\e[1;97m'; On_Whi='\e[47m'; On_IWhi='\e[0;107m';取當前運行腳本絕對路徑的示例:(注:Linux下可以用?dirname $(readlink -f $0)?)
FILE="$0" while [[ -h ${FILE} ]]; doFILE="`readlink "${FILE}"`" done pushd "`dirname "${FILE}"`" > /dev/null DIR=`pwd -P` popd > /dev/null如何在遠程服務器運行一個本地腳本
#無參數 ssh user@server 'bash -s' < local.script.sh#有參數 ssh user@server ARG1="arg1" ARG2="arg2" 'bash -s' < local_script.sh如何檢查一個命令是否存在,用?which?嗎?最好不要用,因為很多操作系統的?which?命令沒有設置退出狀態碼,這樣你不知道是否是有那個命令。所以,你應該使用下面的方式。
# POSIX 兼容: command -v [the_command]# bash 環境: hash [the_command] type [the_command]# 示例: gnudate() {if hash gdate 2> /dev/null; thengdate "$@"elsedate "$@"fi }然后,如果要寫出健壯性更好的腳本,下面是一些相關的技巧:
- 使用?-e?參數,如:set -e?或是?#!/bin/sh -e,這樣設置會讓你的腳本出錯就會停止運行,這樣一來可以防止你的腳本在出錯的情況下還在拼拿地干活停不下來。
- 使用?-u?參數,如:?set -eu,這意味著,如果你代碼中有變量沒有定義,就會退出。
- 對一些變理,你可以使用默認值。如:${FOO:-'default'}
- 處理你代碼的退出碼。這樣方便你的腳本跟別的命令行或腳本集成。
- 盡量不要使用?;?來執行多個命令,而是使用?&&,這樣會在出錯的時候停止運行后續的命令。
- 對于一些字符串變量,使用引號括起,避免其中有空格或是別的什么詭異字符。
- 如果你的腳有參數,你需要檢查腳本運行是否帶了你想要的參數,或是,你的腳本可以在沒有參數的情況下安全的運行。
- 為你的腳本設置?-h?和?--help?來顯示幫助信息。千萬不要把這兩個參數用做為的功能。
- 使用?$()?而不是 “ 來獲得命令行的輸出,主要原因是易讀。
- 小心不同的平臺,尤其是 MacOS 和 Linux 的跨平臺。
- 對于?rm -rf?這樣的高危操作,需要檢查后面的變量名是否為空,比如:rm -rf $MYDIDR/*?如果?$MYDIR為空,結果是災難性的。
- 考慮使用 “find/while” 而不是 “for/find”。如:for F in $(find . -type f) ; do echo $F; done?寫成?find . -type f | while read F ; do echo $F ; done?不但可以容忍空格,而且還更快。
- 防御式編程,在正式執行命令前,把相關的東西都檢查好,比如,文件目錄有沒有存在。
你還可以使用ShellCheck 來幫助你檢查你的腳本。
- https://www.shellcheck.net/
最后推薦一些 Shell 和腳本的參考資料。
各種有意思的命令拼裝,一行命令走天涯:
- http://www.bashoneliners.com/
- http://www.shell-fu.org/
- http://www.commandlinefu.com/
下面是一些腳本集中營,你可以在里面淘到各種牛X的腳本:
- http://www.shelldorado.com/scripts/
- https://snippets.siftie.com/public/tag/bash/
- https://bash.cyberciti.biz/
- https://github.com/alexanderepstein/Bash-Snippets
- https://github.com/miguelgfierro/scripts
- https://github.com/epety/100-shell-script-examples
- https://github.com/ruanyf/simple-bash-scripts
甚至寫腳本都可以使用框架:
- 寫bash腳本的框架?https://github.com/Bash-it/bash-it
Google的Shell腳本的代碼規范:
- https://google.github.io/styleguide/shell.xml
最后,別忘了幾個和shell有關的索引資源:
- https://github.com/alebcay/awesome-shell
- https://github.com/awesome-lists/awesome-bash
- https://terminalsare.sexy/
from:?https://coolshell.cn/articles/19219.html?
總結
以上是生活随笔為你收集整理的打造高效的工作环境 – SHELL 篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 卷积神经网络CNN总结
- 下一篇: 程序员练级攻略