Shell是Linux/Unix的一個外殼,你理解成衣服也行。它負責外界與Linux內核的交互,接收用戶或其他應用程序的命令,然后把這些命令轉化成內核能理解的語言,傳給內核,內核是真正干活的,干完之后再把結果返回用戶或應用程序。
Linux/Unix提供了很多種Shell,為毛要這么多Shell?難道用來炒着吃么?那我問你,你同類型的衣服怎么有那么多件?花色,質地還不一樣。寫程序比買衣服復雜多了,而且程序員往往負責把復雜的事情搞簡單,簡單的事情搞復雜。牛程序員看到不爽的Shell,就會自己重新寫一套,慢慢形成了一些標准,常用的Shell有這么幾種,sh、bash、csh等,想知道你的系統有幾種shell,可以通過以下命令查看:
cat /etc/shells
顯示如下:
/bin/bash /bin/csh /bin/ksh /bin/sh /bin/tcsh /bin/zsh
在 Linux 里執行這個命令和 Mac 略有不同,你會發現 Mac 多了一個 zsh,也就是說 OS X 系統預裝了個 zsh,這是個神馬 Shell 呢?
目前常用的 Linux 系統和 OS X 系統的默認 Shell 都是 bash,但是真正強大的 Shell 是深藏不露的 zsh, 這貨絕對是馬車中的跑車,跑車中的飛行車,史稱『終極 Shell』,但是由於配置過於復雜,所以初期無人問津,很多人跑過來看看 zsh 的配置指南,什么都不說轉身就走了。直到有一天,國外有個窮極無聊的程序員開發出了一個能夠讓你快速上手的zsh項目,叫做「oh my zsh」,Github 網址是:https://github.com/robbyrussell/oh-my-zsh。這玩意就像「X天叫你學會 C++」系列,可以讓你神功速成,而且是真的。
好,下面我們看看如何安裝、配置和使用 zsh。
安裝zsh如果你用 Mac,就可以直接看下一節
如果你用 Redhat Linux,執行:sudo yum install zsh
如果你用 Ubuntu Linux,執行:sudo apt-get install zsh
如果你用 Windows……去洗洗睡吧。
安裝完成后設置當前用戶使用 zsh:chsh -s /bin/zsh,根據提示輸入當前用戶的密碼就可以了。
安裝oh my zsh首先安裝 Git,安裝方式同上,把 zsh 換成 git 即可。
安裝「oh my zsh」可以自動安裝也可以手動安裝。
自動安裝:
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
手動安裝:
git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
都不復雜,安裝完成之后退出當前會話重新打開一個終端窗口,你就可以見到這個彩色的提示了:
配置
zsh 的配置主要集中在用戶當前目錄的.zshrc里,用 vim 或你喜歡的其他編輯器打開.zshrc,在最下面會發現這么一行字:
# Customize to your needs…
可以在此處定義自己的環境變量和別名,當然,oh my zsh 在安裝時已經自動讀取當前的環境變量並進行了設置,你可以繼續追加其他環境變量。
接下來進行別名的設置,我自己的部分配置如下:
- alias cls='clear'
- alias ll='ls -l'
- alias la='ls -a'
- alias vi='vim'
- alias javac="javac -J-Dfile.encoding=utf8"
- alias grep="grep --color=auto"
- alias -s html=mate # 在命令行直接輸入后綴為 html 的文件名,會在 TextMate 中打開
- alias -s rb=mate # 在命令行直接輸入 ruby 文件,會在 TextMate 中打開
- alias -s py=vi # 在命令行直接輸入 python 文件,會用 vim 中打開,以下類似
- alias -s js=vi
- alias -s c=vi
- alias -s java=vi
- alias -s txt=vi
- alias -s gz='tar -xzvf'
- alias -s tgz='tar -xzvf'
- alias -s zip='unzip'
- alias -s bz2='tar -xjvf'
- #color{{{
- autoload colors
- colors
- for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do
- eval _$color='%{$terminfo[bold]$fg[${(L)color}]%}'
- eval $color='%{$fg[${(L)color}]%}'
- (( count = $count + 1 ))
- done
- FINISH="%{$terminfo[sgr0]%}"
- #}}}
- #命令提示符
- RPROMPT=$(echo "$RED%D %T$FINISH")
- PROMPT=$(echo "$CYAN%n@$YELLOW%M:$GREEN%/$_YELLOW>$FINISH ")
- #PROMPT=$(echo "$BLUE%M$GREEN%/
- #$CYAN%n@$BLUE%M:$GREEN%/$_YELLOW>>>$FINISH ")
- #標題欄、任務欄樣式{{{
- case $TERM in (*xterm*|*rxvt*|(dt|k|E)term)
- precmd () { print -Pn "\e]0;%n@%M//%/\a" }
- preexec () { print -Pn "\e]0;%n@%M//%/\ $1\a" }
- ;;
- esac
- #}}}
- #編輯器
- export EDITOR=vim
- #輸入法
- export XMODIFIERS="@im=ibus"
- export QT_MODULE=ibus
- export GTK_MODULE=ibus
- #關於歷史紀錄的配置 {{{
- #歷史紀錄條目數量
- export HISTSIZE=10000
- #注銷后保存的歷史紀錄條目數量
- export SAVEHIST=10000
- #歷史紀錄文件
- export HISTFILE=~/.zhistory
- #以附加的方式寫入歷史紀錄
- setopt INC_APPEND_HISTORY
- #如果連續輸入的命令相同,歷史紀錄中只保留一個
- setopt HIST_IGNORE_DUPS
- #為歷史紀錄中的命令添加時間戳
- setopt EXTENDED_HISTORY
- #啟用 cd 命令的歷史紀錄,cd -[TAB]進入歷史路徑
- setopt AUTO_PUSHD
- #相同的歷史路徑只保留一個
- setopt PUSHD_IGNORE_DUPS
- #在命令前添加空格,不將此命令添加到紀錄文件中
- #setopt HIST_IGNORE_SPACE
- #}}}
- #每個目錄使用獨立的歷史紀錄{{{
- cd() {
- builtin cd "$@" # do actual cd
- fc -W # write current history file
- local HISTDIR="$HOME/.zsh_history$PWD" # use nested folders for history
- if [ ! -d "$HISTDIR" ] ; then # create folder if needed
- mkdir -p "$HISTDIR"
- fi
- export HISTFILE="$HISTDIR/zhistory" # set new history file
- touch $HISTFILE
- local ohistsize=$HISTSIZE
- HISTSIZE=0 # Discard previous dir's history
- HISTSIZE=$ohistsize # Prepare for new dir's history
- fc -R #read from current histfile
- }
- mkdir -p $HOME/.zsh_history$PWD
- export HISTFILE="$HOME/.zsh_history$PWD/zhistory"
- function allhistory { cat $(find $HOME/.zsh_history -name zhistory) }
- function convhistory {
- sort $1 | uniq |
- sed 's/^:
[0−9]∗ :[0-9]*;.∗ /\1::::::\2/' | - awk -F"::::::" '{ $1=strftime("%Y-%m-%d %T",$1) "|"; print }'
- }
- #使用 histall 命令查看全部歷史紀錄
- function histall { convhistory =(allhistory) |
- sed '/^.\{20\} *cd/i\\' }
- #使用 hist 查看當前目錄歷史紀錄
- function hist { convhistory $HISTFILE }
- #全部歷史紀錄 top50
- function top50 { allhistory | awk -F':[ 0-9]*:[0-9]*;' '{ $1="" ; print }' | sed 's/ /\n/g' | sed '/^$/d' | sort | uniq -c | sort -nr | head -n 50 }
- #}}}
- #雜項 {{{
- #允許在交互模式中使用注釋 例如:
- #cmd #這是注釋
- setopt INTERACTIVE_COMMENTS
- #啟用自動 cd,輸入目錄名回車進入目錄
- #稍微有點混亂,不如 cd 補全實用
- setopt AUTO_CD
- #擴展路徑
- #/v/c/p/p => /var/cache/pacman/pkg
- setopt complete_in_word
- #禁用 core dumps
- limit coredumpsize 0
- #Emacs風格 鍵綁定
- bindkey -e
- #bindkey -v
- #設置 [DEL]鍵 為向后刪除
- #bindkey "\e[3~" delete-char
- #以下字符視為單詞的一部分
- WORDCHARS='*?_-[]~=&;!#$%^(){}<>'
- #}}}
- #自動補全功能 {{{
- setopt AUTO_LIST
- setopt AUTO_MENU
- #開啟此選項,補全時會直接選中菜單項
- #setopt MENU_COMPLETE
- autoload -U compinit
- compinit
- #自動補全緩存
- #zstyle ':completion::complete:*' use-cache on
- #zstyle ':completion::complete:*' cache-path .zcache
- #zstyle ':completion:*:cd:*' ignore-parents parent pwd
- #自動補全選項
- zstyle ':completion:*' verbose yes
- zstyle ':completion:*' menu select
- zstyle ':completion:*:*:default' force-list always
- zstyle ':completion:*' select-prompt '%SSelect: lines: %L matches: %M [%p]'
- zstyle ':completion:*:match:*' original only
- zstyle ':completion::prefix-1:*' completer _complete
- zstyle ':completion:predict:*' completer _complete
- zstyle ':completion:incremental:*' completer _complete _correct
- zstyle ':completion:*' completer _complete _prefix _correct _prefix _match _approximate
- #路徑補全
- zstyle ':completion:*' expand 'yes'
- zstyle ':completion:*' squeeze-shlashes 'yes'
- zstyle ':completion::complete:*' '\\'
- #彩色補全菜單
- eval $(dircolors -b)
- export ZLSCOLORS="${LS_COLORS}"
- zmodload zsh/complist
- zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
- zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
- #修正大小寫
- zstyle ':completion:*' matcher-list '' 'm:{a-zA-Z}={A-Za-z}'
- #錯誤校正
- zstyle ':completion:*' completer _complete _match _approximate
- zstyle ':completion:*:match:*' original only
- zstyle ':completion:*:approximate:*' max-errors 1 numeric
- #kill 命令補全
- compdef pkill=kill
- compdef pkill=killall
- zstyle ':completion:*:*:kill:*' menu yes select
- zstyle ':completion:*:*:*:*:processes' force-list always
- zstyle ':completion:*:processes' command 'ps -au$USER'
- #補全類型提示分組
- zstyle ':completion:*:matches' group 'yes'
- zstyle ':completion:*' group-name ''
- zstyle ':completion:*:options' description 'yes'
- zstyle ':completion:*:options' auto-description '%d'
- zstyle ':completion:*:descriptions' format $'\e[01;33m -- %d --\e[0m'
- zstyle ':completion:*:messages' format $'\e[01;35m -- %d --\e[0m'
- zstyle ':completion:*:warnings' format $'\e[01;31m -- No Matches Found --\e[0m'
- zstyle ':completion:*:corrections' format $'\e[01;32m -- %d (errors: %e) --\e[0m'
- # cd ~ 補全順序
- zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
- #}}}
- ##行編輯高亮模式 {{{
- # Ctrl+@ 設置標記,標記和光標點之間為 region
- zle_highlight=(region:bg=magenta #選中區域
- special:bold #特殊字符
- isearch:underline)#搜索時使用的關鍵字
- #}}}
- ##空行(光標在行首)補全 "cd " {{{
- user-complete(){
- case $BUFFER in
- "" ) # 空行填入 "cd "
- BUFFER="cd "
- zle end-of-line
- zle expand-or-complete
- ;;
- "cd --" ) # "cd --" 替換為 "cd +"
- BUFFER="cd +"
- zle end-of-line
- zle expand-or-complete
- ;;
- "cd +-" ) # "cd +-" 替換為 "cd -"
- BUFFER="cd -"
- zle end-of-line
- zle expand-or-complete
- ;;
- * )
- zle expand-or-complete
- ;;
- esac
- }
- zle -N user-complete
- bindkey "\t" user-complete
- #}}}
- ##在命令前插入 sudo {{{
- #定義功能
- sudo-command-line() {
- [[ -z $BUFFER ]] && zle up-history
- [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
- zle end-of-line #光標移動到行末
- }
- zle -N sudo-command-line
- #定義快捷鍵為: [Esc] [Esc]
- bindkey "\e\e" sudo-command-line
- #}}}
- #命令別名 {{{
- alias cp='cp -i'
- alias mv='mv -i'
- alias rm='rm -i'
- alias ls='ls -F --color=auto'
- alias ll='ls -al'
- alias grep='grep --color=auto'
- alias la='ls -a'
- alias pacman='sudo pacman-color'
- alias p='sudo pacman-color'
- alias y='yaourt'
- alias h='htop'
- alias vim='sudo vim'
- #[Esc][h] man 當前命令時,顯示簡短說明
- alias run-help >&/dev/null && unalias run-help
- autoload run-help
- #歷史命令 top10
- alias top10='print -l ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
- #}}}
- #路徑別名 {{{
- #進入相應的路徑時只要 cd ~xxx
- hash -d A="/media/ayu/dearest"
- hash -d H="/media/data/backup/ayu"
- hash -d E="/etc/"
- hash -d D="/home/ayumi/Documents"
- #}}}
- ##for Emacs {{{
- #在 Emacs終端 中使用 Zsh 的一些設置 不推薦在 Emacs 中使用它
- #if [[ "$TERM" == "dumb" ]]; then
- #setopt No_zle
- #PROMPT='%n@%M %/
- #>>'
- #alias ls='ls -F'
- #fi
- #}}}
- #{{{自定義補全
- #補全 ping
- zstyle ':completion:*:ping:*' hosts 192.168.1.{1,50,51,100,101} www.google.com
- #補全 ssh scp sftp 等
- #zstyle -e ':completion::*:*:*:hosts' hosts 'reply=(${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) /dev/null)"}%%[# ]*}//,/ })'
- #}}}
- #{{{ F1 計算器
- arith-eval-echo() {
- LBUFFER="${LBUFFER}echo \$(( "
- RBUFFER=" ))$RBUFFER"
- }
- zle -N arith-eval-echo
- bindkey "^[[11~" arith-eval-echo
- #}}}
- ####{{{
- function timeconv { date -d @$1 +"%Y-%m-%d %T" }
- # }}}
- zmodload zsh/mathfunc
- autoload -U zsh-mime-setup
- zsh-mime-setup
- setopt EXTENDED_GLOB
- #autoload -U promptinit
- #promptinit
- #prompt redhat
- setopt correctall
- autoload compinstall
- #漂亮又實用的命令高亮界面
- setopt extended_glob
- TOKENS_FOLLOWED_BY_COMMANDS=('|' '||' ';' '&' '&&' 'sudo' 'do' 'time' 'strace')
- recolor-cmd() {
- region_highlight=()
- colorize=true
- start_pos=0
- for arg in ${(z)BUFFER}; do
- ((start_pos+=${#BUFFER[$start_pos+1,-1]}-${#${BUFFER[$start_pos+1,-1]## #}}))
- ((end_pos=$start_pos+${#arg}))
- if $colorize; then
- colorize=false
- res=$(LC_ALL=C builtin type $arg 2>/dev/null)
- case $res in
- *'reserved word'*) style="fg=magenta,bold";;
- *'alias for'*) style="fg=cyan,bold";;
- *'shell builtin'*) style="fg=yellow,bold";;
- *'shell function'*) style='fg=green,bold';;
- *"$arg is"*)
- [[ $arg = 'sudo' ]] && style="fg=red,bold" || style="fg=blue,bold";;
- *) style='none,bold';;
- esac
- region_highlight+=("$start_pos $end_pos $style")
- fi
- [[ ${${TOKENS_FOLLOWED_BY_COMMANDS[(r)${arg//|/\|}]}:+yes} = 'yes' ]] && colorize=true
- start_pos=$end_pos
- done
- }
- check-cmd-self-insert() { zle .self-insert && recolor-cmd }
- check-cmd-backward-delete-char() { zle .backward-delete-char && recolor-cmd }
- zle -N self-insert check-cmd-self-insert
- zle -N backward-delete-char check-cmd-backward-delete-char
- # man page highlight
- export LESS_TERMCAP_mb=$'\E[01;31m' # begin blinking
- export LESS_TERMCAP_md=$'\E[01;38;5;74m' # begin bold
- export LESS_TERMCAP_me=$'\E[0m' # end mode
- export LESS_TERMCAP_se=$'\E[0m' # end standout-mode
- export LESS_TERMCAP_so=$'\E[38;5;246m' # begin standout-mode - info box
- export LESS_TERMCAP_ue=$'\E[0m' # end underline
- export LESS_TERMCAP_us=$'\E[04;38;5;146m' # begin underline
zsh 的牛糞之處在於不僅可以設置通用別名,還能針對文件類型設置對應的打開程序,比如:
alias -s html=mate,意思就是你在命令行輸入 hello.html,zsh會為你自動打開 TextMat 並讀取 hello.html; alias -s gz='tar -xzvf',表示自動解壓后綴為 gz 的壓縮包。
總之,只有想不到,木有做不到。
設置完環境變量和別名之后,基本上就可以用了,如果你是個主題控,還可以玩玩 zsh 的主題。在 .zshrc 里找到ZSH_THEME,就可以設置主題了,默認主題是:
ZSH_THEME=”robbyrussell”
oh my zsh 提供了數十種主題,相關文件在~/.oh-my-zsh/themes目錄下,你可以隨意選擇,也可以編輯主題滿足自己的變態需求,我采用了默認主題robbyrussell,不過做了一點小小的改動:
PROMPT='%{$fg_bold[red]%}➜ %{$fg_bold[green]%}%p%{$fg[cyan]%}%d %{$fg_bold[blue]%}$(git_prompt_info)%{$fg_bold[blue]%}% %{$reset_color%}>' #PROMPT='%{$fg_bold[red]%}➜ %{$fg_bold[green]%}%p %{$fg[cyan]%}%c %{$fg_bold[blue]%}$(git_prompt_info)%{$fg_bold[blue]%} % %{$reset_color%}'
對照原來的版本,我把 c 改為 d,c 表示當前目錄,d 表示絕對路徑,另外在末尾增加了一個「 > 」,改完之后的效果是這樣的:
大家可以嘗試進行改造,也算個趣事。
最后我們來說說插件。
插件oh my zsh 項目提供了完善的插件體系,相關的文件在~/.oh-my-zsh/plugins目錄下,默認提供了100多種,大家可以根據自己的實際學習和工作環境采用,想了解每個插件的功能,只要打開相關目錄下的 zsh 文件看一下就知道了。插件也是在.zshrc里配置,找到plugins關鍵字,你就可以加載自己的插件了,系統默認加載 git ,你可以在后面追加內容,如下:
plugins=(git textmate ruby autojump osx mvn gradle)
下面簡單介紹幾個:
1、git:當你處於一個 git 受控的目錄下時,Shell 會明確顯示 「git」和 branch,如上圖所示,另外對 git 很多命令進行了簡化,例如 gco=’git checkout’、gd=’git diff’、gst=’git status’、g=’git’等等,熟練使用可以大大減少 git 的命令長度,命令內容可以參考~/.oh-my-zsh/plugins/git/git.plugin.zsh
2、textmate:mr可以創建 ruby 的框架項目,tm finename 可以用 textmate 打開指定文件。
3、osx:tab 增強,quick-look filename 可以直接預覽文件,man-preview grep 可以生成 grep手冊 的pdf 版本等。
4、autojump:zsh 和 autojump 的組合形成了 zsh 下最強悍的插件,今天我們主要說說這貨。
首先安裝autojump,如果你用 Mac,可以使用 brew 安裝:
brew install autojump
如果是 Linux,去下載 autojump 的最新版本,比如:
wget https://github.com/downloads/joelthelion/autojump/autojump_v21.1.2.tar.gz
解壓縮后進入目錄,執行
./install.sh
最后把以下代碼加入.zshrc:
[[ -s ~/.autojump/etc/profile.d/autojump.sh ]] && . ~/.autojump/etc/profile.d/autojump.sh
至此,安裝、配置、插件三位一體,終極 Shell 全面登場。退出終端會話重新登錄,開始感受 zsh 的訓疾如風!
使用 zsh1、兼容 bash,原來使用 bash 的兄弟切換過來毫無壓力,該咋用咋用。
2、強大的歷史紀錄功能,輸入 grep 然后用上下箭頭可以翻閱你執行的所有 grep 命令。
3、智能拼寫糾正,輸入gtep mactalk * -R,系統會提示:zsh: correct ‘gtep’ to ‘grep’ [nyae]? 比妹紙貼心吧,她們向來都是讓你猜的……
4、各種補全:路徑補全、命令補全,命令參數補全,插件內容補全等等。觸發補全只需要按一下或兩下 tab 鍵,補全項可以使用 ctrl+n/p/f/b上下左右切換。比如你想殺掉 Java 的進程,只需要輸入 kill java + tab鍵,如果只有一個 java 進程,zsh 會自動替換為進程的 pid,如果有多個則會出現選擇項供你選擇。ssh + 空格 + 兩個tab鍵,zsh會列出所有訪問過的主機和用戶名進行補全
5、智能跳轉,安裝了autojump之后,zsh 會自動記錄你訪問過的目錄,通過 j + 目錄名 可以直接進行目錄跳轉,而且目錄名支持模糊匹配和自動補全,例如你訪問過Hadoop-1.0.0目錄,輸入j hado 即可正確跳轉。j –stat 可以看你的歷史路徑庫。
6、目錄瀏覽和跳轉:輸入 d,即可列出你在這個會話里訪問的目錄列表,輸入列表前的序號,即可直接跳轉。
7、在當前目錄下輸入 .. 或 … ,或直接輸入當前目錄名都可以跳轉,你甚至不再需要輸入 cd 命令了。
8、通配符搜索:ls -l **/*.sh,可以遞歸顯示當前目錄下的 shell 文件,文件少時可以代替 find,文件太多就歇菜了。
9、更強的別名:請參考配置一節。
10、插件支持:請參考插件一節。
