這裏顯示兩個版本的差異處。
| Both sides previous revision 前次修改 下次修改 | 前次修改 | ||
|
linux:shell [2007/03/13 22:33] wenpei |
linux:shell [2011/08/09 09:43] (目前版本) wenpei |
||
|---|---|---|---|
| 行 25: | 行 25: | ||
| | \e |跳脫字元| | | \e |跳脫字元| | ||
| | \H |主機名稱(較長格式)| | | \H |主機名稱(較長格式)| | ||
| - | | \h || | + | | \h |主機名稱(較短格式)| |
| | \n |換行| | | \n |換行| | ||
| | \s |Shell Name| | | \s |Shell Name| | ||
| | \T |以 12 小時制顯示時間| | | \T |以 12 小時制顯示時間| | ||
| - | | \t || | + | | \t |以 24 小時制顯示時間| |
| - | | \@ || | + | | \@ | | |
| | \u |使用者名稱| | | \u |使用者名稱| | ||
| | \W |完整工作目錄| | | \W |完整工作目錄| | ||
| | \w |目前目錄| | | \w |目前目錄| | ||
| | \$ |root 會顯示「#」,一般使用者則為「$」| | | \$ |root 會顯示「#」,一般使用者則為「$」| | ||
| - | | \\ |印出反斜線| | + | | \ \ |印出反斜線| |
| + | |||
| + | ===== bash 記憶指令 ===== | ||
| + | 在 ~/.bashrc 加上 | ||
| + | bind '"\x1b\x5b\x41":history-search-backward' | ||
| + | bind '"\x1b\x5b\x42":history-search-forward' | ||
| + | |||
| + | 參考 zxvc.bbs@ptt.cc 寫的 | ||
| + | <code> | ||
| + | 如果想知道bash有多少好用的hotkey, | ||
| + | 只要man bash,然後搜尋『history-search-backward』, | ||
| + | 就可以在history-search-backward附近找到一堆hotkey。 | ||
| + | 或者在bash中輸入 | ||
| + | $ bind -p | ||
| + | 也可以看到很多hotkey,只不過沒有詳細說明。 | ||
| + | |||
| + | 另外『\M-』這個prefix在一般PC鍵盤上代表的是ESC key, | ||
| + | 這man bash也是可以查得到。 | ||
| + | |||
| + | 如果想知道某個按鍵的keymap(例如Up鍵),可以在『純終端機』 | ||
| + | (我不清楚為什麼虛擬終端機會不能用showkey)輸入 | ||
| + | $ showkey -m | ||
| + | 查到,但是這是10進位的值,要把它轉成16進位再加上『\x』 | ||
| + | 才可以跟某個function bind在一起。 | ||
| + | 例如:Up鍵與history-search-backward bind在一起: | ||
| + | $ bind ‘”\x1b\x5b\x41″:history-search-backward’ | ||
| + | </code> | ||
| + | |||
| + | [[http://www.thegeekstuff.com/2011/08/bash-history-expansion/|15 Linux Bash History Expansion Examples You Should Know]] | ||
| ====== Shell Script ====== | ====== Shell Script ====== | ||
| 行 204: | 行 232: | ||
| ==== break , continue ==== | ==== break , continue ==== | ||
| 可在後面接數字,代表要跳出哪個迴圈,如:break2 指要中斷第二個迴圈。 | 可在後面接數字,代表要跳出哪個迴圈,如:break2 指要中斷第二個迴圈。 | ||
| + | |||
| + | ===== function ===== | ||
| + | 函數宣告必須在呼叫之前完成,因為 Shell script 是直譯程式,且需注意:1. 全域和區域變數的範圍;2. 傳參數的用法。 | ||
| + | Function name | ||
| + | { | ||
| + | ...... | ||
| + | } | ||
| + | 或 | ||
| + | function_name() | ||
| + | { | ||
| + | ...... | ||
| + | } | ||
| + | |||
| + | ==== 變數的生命週期 ==== | ||
| + | 有三種不同性質的變數。 | ||
| + | |||
| + | === 環境變數 === | ||
| + | 由系統產生,必定是全域變數。 | ||
| + | |||
| + | === 位置變數 === | ||
| + | 由函式被呼叫時所附加的參數而定,因此必為區域變數,在不同的函式用同樣的方法使用,但數值不同。 | ||
| + | $1, $2, $3, ... | ||
| + | |||
| + | === 自訂變數 === | ||
| + | 除非特別指定成 local,不然皆為全域變數。 | ||
| + | local var1="string" | ||
| + | |||
| + | <code> | ||
| + | #!/bin/bash | ||
| + | funct () { | ||
| + | echo "Inside -- funct: $# args: $1 $2 $3" | ||
| + | } | ||
| + | echo "Outside -- $0: $# args: $1 $2 $3" | ||
| + | funct input1 input2 input3 // 呼叫函式 | ||
| + | </code> | ||
| + | $ ./test.sh in1 in2 in3 | ||
| + | Outside -- ./test.sh: 3 args: in1 in2 in3 | ||
| + | Inside -- funct: 3 args: input1 input2 input3 | ||
| + | |||
| + | ==== 參數傳遞 ==== | ||
| + | * 傳入函式:呼叫時直接寫在函式名稱後面,即可成為函式的位置變數 | ||
| + | * 傳出函式:使用全域變數來儲存跨函式間的資料 | ||
| + | |||
| + | ===== 上一個指令的執行結果 ===== | ||
| + | http://blog.miniasp.com/post/2009/02/Writing-Bash-script-should-care-about-error-handling-issues.aspx | ||
| + | |||
| + | 「$?」代表上個指令的執行結果,若成功執行則回傳「0」。 | ||
| + | |||
| + | 因此可寫成: | ||
| + | <code> | ||
| + | SUCCESS=0 | ||
| + | |||
| + | mv some.log $BAKDIR/some-$TODAY.log | ||
| + | |||
| + | if [ "$?" -ne $SUCCESS ] | ||
| + | then | ||
| + | echo "Can NOT move some.log to $BAKDIR/some-$TODAY.log!!" | ||
| + | exit 1 | ||
| + | fi | ||
| + | </code> | ||
| + | |||
| + | ====== date 指令 ====== | ||
| + | 取得昨天的日期: | ||
| + | date -d 'yesterday' +%Y-%m-%d.log | ||
| + | |||
| + | 取得幾天前的日期: | ||
| + | date -d '6 days ago' +%Y-%m-%d | ||
| + | |||
| + | 下週一、上週三的日期: | ||
| + | date -d 'next Mon' | ||
| + | date -d 'last Wed' | ||
| + | |||
| + | ====== 定期確認 apache 的 error log ====== | ||
| + | 定期分析 apache 的 error log 中,找不到檔案的部份,郵寄給管理者參考。 | ||
| + | <code> | ||
| + | #! /bin/bash | ||
| + | |||
| + | ( for x in `grep "File does not exist:" /var/log/apache2/error.log | awk '{print $13}' | sort | uniq`; | ||
| + | do | ||
| + | grep $x /var/log/apache2/error.log | wc -l | tr -d '\n'; | ||
| + | echo " : $x"; | ||
| + | done | sort -rn | head -20 ) | mail -s "Missing file report" webmaster@domain.name | ||
| + | </code> | ||
| + | |||
| + | 並在 crontab 中加入(需 root 權限) | ||
| + | 0 21 * * 5 /root/apache_file_no_found_error.sh | ||
| + | | ||
| + | ====== zsh ====== | ||
| + | http://friedcpu.wordpress.com/2007/07/24/zsh-the-last-shell-youll-ever-need/ | ||
| + | |||
| + | http://grml.org/zsh/zsh-lovers.html | ||
| + | |||
| + | http://www.acm.uiuc.edu/workshops/zsh/toc.html | ||
| + | |||
| + | http://rayninfo.co.uk/tips/zshtips.html | ||
| + | |||
| + | ===== zshrc by vgod ===== | ||
| + | <code> | ||
| + | export PATH="$PATH:~/bin:/usr/local/bin:/usr/local/texlive/2007/bin/i386-darwin:/opt/flex_sdk_3/bin:/usr/texbin:/opt/local/bin" | ||
| + | export EDITOR=vim | ||
| + | export LANG=en_US.UTF-8 | ||
| + | |||
| + | UNAME=`uname` | ||
| + | if [[ $UNAME == "Darwin" ]] | ||
| + | then | ||
| + | export LSCOLORS="gxfxcxdxbxegedabagacad" | ||
| + | alias ls='ls -Gv' | ||
| + | elif [[ $UNAME == "Linux" ]] | ||
| + | then | ||
| + | alias ls='ls --color=auto' | ||
| + | fi | ||
| + | |||
| + | # path alias, e.g. cd ~XXX | ||
| + | #hash -d WWW="/home/lighttpd/html" | ||
| + | |||
| + | |||
| + | # HISTORY | ||
| + | # number of lines kept in history | ||
| + | export HISTSIZE=10000 | ||
| + | # # number of lines saved in the history after logout | ||
| + | export SAVEHIST=10000 | ||
| + | # # location of history | ||
| + | export HISTFILE=~/.zhistory | ||
| + | # # append command to history file once executed | ||
| + | setopt INC_APPEND_HISTORY | ||
| + | |||
| + | # Disable core dumps | ||
| + | limit coredumpsize 0 | ||
| + | |||
| + | # vi key binding | ||
| + | bindkey -v | ||
| + | bindkey '^R' history-incremental-search-backward | ||
| + | # mapping del | ||
| + | bindkey "\e[3~" delete-char | ||
| + | |||
| + | setopt AUTO_PUSHD | ||
| + | |||
| + | WORDCHARS='*?_-[]~=&;!#$%^(){}<>' | ||
| + | |||
| + | # auto-completion | ||
| + | setopt COMPLETE_ALIASES | ||
| + | setopt AUTO_LIST | ||
| + | setopt AUTO_MENU | ||
| + | #setopt MENU_COMPLETE | ||
| + | setopt MULTIBYTE | ||
| + | |||
| + | autoload -U compinit | ||
| + | compinit | ||
| + | |||
| + | # Completion caching | ||
| + | zstyle ':completion::complete:*' use-cache on | ||
| + | zstyle ':completion::complete:*' cache-path .zcache | ||
| + | #zstyle ':completion:*:cd:*' ignore-parents parent pwd | ||
| + | |||
| + | #Completion Options | ||
| + | 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 | ||
| + | |||
| + | # Path Expansion | ||
| + | zstyle ':completion:*' expand 'yes' | ||
| + | zstyle ':completion:*' squeeze-shlashes 'yes' | ||
| + | zstyle ':completion::complete:*' '\\' | ||
| + | |||
| + | #zstyle ':completion:*:*:*:default' menu yes select #interactive | ||
| + | zstyle ':completion:*:*:default' force-list always | ||
| + | |||
| + | # require /etc/DIR_COLORS to display colors in the completion list | ||
| + | [ -f /etc/DIR_COLORS ] && eval $(dircolors -b /etc/DIR_COLORS) | ||
| + | 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:*' completer _complete _match _approximate | ||
| + | zstyle ':completion:*:match:*' original only | ||
| + | zstyle ':completion:*:approximate:*' max-errors 1 numeric | ||
| + | |||
| + | bindkey -M menuselect '^M' .accept-line | ||
| + | |||
| + | compdef pkill=kill | ||
| + | compdef pkill=killall | ||
| + | zstyle ':completion:*:*:kill:*' menu yes select interactive | ||
| + | zstyle ':completion:*:kill:*' force-list always | ||
| + | zstyle ':completion:*:processes' command 'ps -au$USER' | ||
| + | |||
| + | # Group matches and Describe | ||
| + | zstyle ':completion:*:matches' group 'yes' | ||
| + | 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' | ||
| + | |||
| + | alias ll='ls -l' | ||
| + | alias grep='grep --color=auto' | ||
| + | |||
| + | |||
| + | function precmd { | ||
| + | |||
| + | local TERMWIDTH | ||
| + | (( TERMWIDTH = ${COLUMNS} - 1 )) | ||
| + | |||
| + | ### | ||
| + | # Truncate the path if it's too long. | ||
| + | |||
| + | PR_FILLBAR="" | ||
| + | PR_PWDLEN="" | ||
| + | |||
| + | local promptsize=${#${(%):---(%n@%m)----}} | ||
| + | local pwdsize=${#${(%):-%~}} | ||
| + | |||
| + | if [[ "$promptsize + $pwdsize" -gt $TERMWIDTH ]]; then | ||
| + | ((PR_PWDLEN=$TERMWIDTH - $promptsize)) | ||
| + | else | ||
| + | PR_FILLBAR="\${(l.(($TERMWIDTH - ($promptsize + $pwdsize)))..${PR_HBAR}.)}" | ||
| + | fi | ||
| + | |||
| + | ### | ||
| + | # Get APM info. | ||
| + | |||
| + | #if which ibam > /dev/null; then | ||
| + | #PR_APM_RESULT=`ibam --percentbattery` | ||
| + | #elif which apm > /dev/null; then | ||
| + | #PR_APM_RESULT=`apm` | ||
| + | #fi | ||
| + | } | ||
| + | |||
| + | setopt extended_glob | ||
| + | preexec () { | ||
| + | if [[ "$TERM" == "screen" ]]; then | ||
| + | local CMD=${1[(wr)^(*=*|sudo|-*)]} | ||
| + | echo -n "\ek$CMD\e\\" | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | setprompt () { | ||
| + | ### | ||
| + | # Need this so the prompt will work. | ||
| + | |||
| + | setopt prompt_subst | ||
| + | |||
| + | ### | ||
| + | # See if we can use colors. | ||
| + | |||
| + | autoload colors zsh/terminfo | ||
| + | if [[ "$terminfo[colors]" -ge 8 ]]; then | ||
| + | colors | ||
| + | fi | ||
| + | for color in RED GREEN YELLOW BLUE MAGENTA CYAN WHITE; do | ||
| + | eval PR_$color='%{$terminfo[bold]$fg[${(L)color}]%}' | ||
| + | eval PR_LIGHT_$color='%{$fg[${(L)color}]%}' | ||
| + | (( count = $count + 1 )) | ||
| + | done | ||
| + | PR_NO_COLOUR="%{$terminfo[sgr0]%}" | ||
| + | |||
| + | ### | ||
| + | # See if we can use extended characters to look nicer. | ||
| + | |||
| + | typeset -A altchar | ||
| + | set -A altchar ${(s..)terminfo[acsc]} | ||
| + | PR_SET_CHARSET="%{$terminfo[enacs]%}" | ||
| + | PR_SHIFT_IN="%{$terminfo[smacs]%}" | ||
| + | PR_SHIFT_OUT="%{$terminfo[rmacs]%}" | ||
| + | PR_HBAR=${altchar[q]:--} | ||
| + | #PR_HBAR=" " | ||
| + | PR_ULCORNER=${altchar[l]:--} | ||
| + | PR_LLCORNER=${altchar[m]:--} | ||
| + | PR_LRCORNER=${altchar[j]:--} | ||
| + | PR_URCORNER=${altchar[k]:--} | ||
| + | |||
| + | ### | ||
| + | # Decide if we need to set titlebar text. | ||
| + | |||
| + | case $TERM in | ||
| + | xterm*) | ||
| + | PR_TITLEBAR=$'%{\e]0;%(!.-=*[ROOT]*=- | .)%n@%m:%~ | ${COLUMNS}x${LINES} | %y\a%}' | ||
| + | ;; | ||
| + | screen) | ||
| + | PR_TITLEBAR=$'%{\e_screen \005 (\005t) | %(!.-=[ROOT]=- | .)%n@%m:%~ | ${COLUMNS}x${LINES} | %y\e\\%}' | ||
| + | ;; | ||
| + | *) | ||
| + | PR_TITLEBAR='' | ||
| + | ;; | ||
| + | esac | ||
| + | |||
| + | ### | ||
| + | # Decide whether to set a screen title | ||
| + | if [[ "$TERM" == "screen" ]]; then | ||
| + | PR_STITLE=$'%{\ekzsh\e\\%}' | ||
| + | else | ||
| + | PR_STITLE='' | ||
| + | fi | ||
| + | |||
| + | ### | ||
| + | # APM detection | ||
| + | |||
| + | #if which ibam > /dev/null; then | ||
| + | #PR_APM='$PR_RED${${PR_APM_RESULT[(f)1]}[(w)-2]}%%(${${PR_APM_RESULT[(f)3]}[(w)-1]})$PR_LIGHT_BLUE:' | ||
| + | #elif which apm > /dev/null; then | ||
| + | #PR_APM='$PR_RED${PR_APM_RESULT[(w)5,(w)6]/\% /%%}$PR_LIGHT_BLUE:' | ||
| + | #else | ||
| + | PR_APM='' | ||
| + | #fi | ||
| + | |||
| + | ### | ||
| + | # Finally, the prompt. | ||
| + | |||
| + | PROMPT='$PR_SET_CHARSET$PR_STITLE${(e)PR_TITLEBAR}\ | ||
| + | $PR_CYAN$PR_SHIFT_IN$PR_ULCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT [\ | ||
| + | $PR_GREEN%(!.%SROOT%s.%n)$PR_GREEN@%m\ | ||
| + | $PR_BLUE]$PR_SHIFT_IN $PR_SHIFT_OUT$PR_BLUE\ | ||
| + | $PR_MAGENTA%$PR_PWDLEN<..<%~%<<\ | ||
| + | $PR_BLUE$PR_SHIFT_IN$PR_HBAR${(e)PR_FILLBAR}$PR_CYAN$PR_URCORNER$PR_SHIFT_OUT\ | ||
| + | |||
| + | $PR_CYAN$PR_SHIFT_IN$PR_LLCORNER$PR_BLUE$PR_HBAR$PR_SHIFT_OUT \ | ||
| + | %(?..$PR_LIGHT_RED%?$PR_BLUE:)\ | ||
| + | $PR_LIGHT_BLUE%(!.$PR_RED#.$PR_WHITE\$)$PR_SHIFT_IN$PR_SHIFT_OUT\ | ||
| + | $PR_CYAN$PR_SHIFT_IN$PR_SHIFT_OUT\ | ||
| + | $PR_NO_COLOUR ' | ||
| + | |||
| + | RPROMPT=' $PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_BLUE$PR_HBAR$PR_SHIFT_OUT\ | ||
| + | ($PR_YELLOW%D{%H:%M}$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_CYAN$PR_LRCORNER$PR_SHIFT_OUT$PR_NO_COLOUR' | ||
| + | |||
| + | PS2='$PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\ | ||
| + | $PR_BLUE$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT(\ | ||
| + | $PR_LIGHT_GREEN%_$PR_BLUE)$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT\ | ||
| + | $PR_CYAN$PR_SHIFT_IN$PR_HBAR$PR_SHIFT_OUT$PR_NO_COLOUR ' | ||
| + | } | ||
| + | |||
| + | setprompt | ||
| + | </code> | ||
| + | |||
| + | |||