一,Shell中特殊且重要的變量bash
$0結合dirname和basename分別取出腳本名稱和腳本路徑ssh
[root@192-168-3-163 scripts]# cat test.sh #!/bin/bash dirname $0 basename $0 [root@192-168-3-163 scripts]# sh /mnt/scripts/test.sh /mnt/scripts test.sh
也可參考系統rpcbind腳本函數
echo $"Usage: $0 {start stop | status | restart | reload }"
$n測試測試
[root@192-168-3-163 mnt]# cat test.sh echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 [root@192-168-3-163 mnt]# sh test.sh 1 5 6 #傳入3個參數,結果顯示有誤 1 5 6 10 11 12 13 14 15 [root@192-168-3-163 mnt]# cat test.sh #$9以上的參數用大括號括起來結果輸出正常 echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} [root@192-168-3-163 mnt]# sh test.sh 1 5 6 1 5 6
腳本參考案例命令行
case "$1" in start) if [ -f $PIDFILE ] then echo "$PIDFILE exists, process is already running or crashed" else echo "Starting Redis server..." $EXEC $CONF fi ;; stop) if [ ! -f $PIDFILE ] then echo "$PIDFILE does not exist, process is not running" else PID=$(cat $PIDFILE) echo "Stopping ..." $CLIEXEC -p $REDISPORT shutdown while [ -x /proc/${PID} ] do echo "Waiting for Redis to shutdown ..." sleep 1 done
$# 特殊變量獲取腳本傳參個數的實踐指針
[root@192-168-3-163 scripts]# cat test.sh #!/bin/bash echo $1 $2 $3 $4 $5 echo $# [root@192-168-3-163 scripts]# sh test.sh {1..10} #傳入10個參數 1 2 3 4 5 #接收5個 10 #打印參數總數10個
範例rest
[root@192-168-3-163 scripts]# cat test.sh #!/bin/bash [ $# -ne 2 ] && { #若是執行腳本參數的個數不等於2 echo "must be two args" exit 1 #給出上面提示 退出 } echo Beijing #知足參數要求後 打印
if判斷寫法server
[root@192-168-3-163 scripts]# cat test.sh #!/bin/bash if [ $# -ne 2 ] #若是參數不等於2 then echo "USAGE:/bin/sh $0 arg1 arg2" #若是不知足參數提示用法 exit 1 fi echo $1 $2
$*和$@特殊變量功能及區別說明blog
範例 利用set設置位置參數(同命令行腳本的傳參)進程
[root@192-168-3-163 scripts]# set -- "I am" handsome boy [root@192-168-3-163 scripts]# echo $# #輸出參數個數 3 [root@192-168-3-163 scripts]# echo $1 I am [root@192-168-3-163 scripts]# echo $2 handsome [root@192-168-3-163 scripts]# echo $3 boy [root@192-168-3-163 scripts]#
測試$*和$@,注意此時不帶雙引號
[root@192-168-3-163 scripts]# set -- "I am" handsome boy [root@192-168-3-163 scripts]# echo $* I am handsome boy [root@192-168-3-163 scripts]# echo $@ I am handsome boy [root@192-168-3-163 scripts]# for i in $*; do echo $i; done I am handsome boy [root@192-168-3-163 scripts]# for i in $@; do echo $i; done I am handsome boy #上面測試結果相同
測試「$*」 和「$@」,注意,此時帶有雙引號:
[root@192-168-3-163 scripts]# set -- "I am" handsome boy [root@192-168-3-163 scripts]# echo "$*" I am handsome boy [root@192-168-3-163 scripts]# echo "$@" I am handsome boy [root@192-168-3-163 scripts]# for i in "$*";do echo $i;done #當作一個參數輸出 I am handsome boy [root@192-168-3-163 scripts]# for i in "$@";do echo $i;done I am handsome boy #每一個參數均獨立輸出
Shell進程中的特殊狀態變量
$? 獲取執行上一個指令的執行狀態返回值(0爲成功,非零爲失敗) $$ 獲取當前執行的Shell腳本的進程(PID) $! 獲取上一個在後臺工做的進程的進程號(PID) $_ 獲取在此以前執行的命令或腳本的最後一個參數
在企業場景下,「$?」 返回值的用法以下:
1.判斷命令、腳本或函數等程序是否執行成功
2.若在腳本中調用執行「exit 數字」,則會返回這個數字給「$?」變量
3.若是是在函數裏,則經過「return數字」 把這個數字以函數返回值的形式傳給「$?」
stop() { echo -n $"Stopping $prog: " killproc $prog #這個是中止rpcbind的命令 RETVAL=$? #將上述命令的返回值"$?" 賦值給RETVAL變量,用於後面的判斷 echo [ $RETVAL -eq 0 ] && { #這裏判斷,若是返回0,執行下面指令 rm -f /var/lock/subsys/$prog rm -f /var/run/rpcbind* } return $RETVAL #若是返回值不等於0,則跳過條件表達式判斷,在這裏直接做爲返回值傳給執行stop函數的腳本 }
$$特殊變量功能及實踐
[root@192-168-3-163 scripts]# more test.sh #!/bin/bash echo $$ > /tmp/a.pid #把進程id寫入到文件 sleep 300 [root@192-168-3-163 scripts]# sh test.sh & [1] 11485 [root@192-168-3-163 scripts]# cat /tmp/a.pid 11485
範例
[root@192-168-3-163 scripts]# cat test.sh #!/bin/bash pidpath=/tmp/a.pid #定義pid文件 if [ -f "$pidpath" ] #若是存在,執行下面then語句 then kill -9 `cat $pidpath` > /dev/null 2>&1 #殺掉與前一個進程號對應的進程 rm -f $pidpath fi echo $$ > $pidpath sleep 300 [root@192-168-3-163 scripts]# sh test.sh & [3] 12654 [2]- Killed sh test.sh [root@192-168-3-163 scripts]# sh test.sh & [4] 12668 [3]- Killed sh test.sh [root@192-168-3-163 scripts]# ps aux |grep test.sh |grep -v grep root 12668 0.0 0.0 113128 1408 pts/1 S 16:50 0:00 sh test.sh #不管運行多少此腳本,都只有一個進程
*提示:這個是一個生產案例的簡單模擬,腳本用於執行啓動或者定時任務時,相同的腳本中只能有一個運行,當新腳本運行時,必須關閉未運行完成或未退出的上一次的同名腳本進程
內置變量命令
echo -n 不換行輸出內容 -e 解析轉義字符(以下面的字符) \n 換行 \r 回車 \t 製表符 \b 退格 \v 縱向製表符
範例
[root@192-168-3-163 scripts]# echo beijing;echo shanghai beijing shanghai [root@192-168-3-163 scripts]# echo -n beijing;echo shanghai beijingshanghai [root@192-168-3-163 scripts]# echo "beijing\tshanghai\nnanjing\thangzhou" beijing\tshanghai\nnanjing\thangzhou [root@192-168-3-163 scripts]# echo -e "beijing\tshanghai\nnanjing\thangzhou" beijing shanghai nanjing hangzhou
exec使用
命令格式:exec命令參數
功能:exec 命令可以在不建立新的子進程的前提下,轉去執行指定的命令,當指定的命令執行完畢後,改進程(也就是最初的Shell)就終止了。
當使用exec 打開文件後,read命令每次都會將文件指針移動到文件的下一行進行讀取,直到文件末尾,利用這個能夠實現處理文件內容。
範例:
[root@192-168-3-163 ~]# cat /tmp/tmp.log 1 2 3 4 5 [root@192-168-3-163 ~]# cat exec.sh #!/bin/bash exec < /tmp/tmp.log while read line do echo $line done echo ok [root@192-168-3-163 ~]# sh exec.sh 1 2 3 4 5 ok
shift 命令使用
[root@192-168-3-163 scripts]# cat test.sh #!/bin/bash echo $1 $2 if [ $# -eq 2 ] then shift echo $1 fi [root@192-168-3-163 scripts]# sh test.sh 1 2 1 2 2
應用場景:當咱們寫Shell但願像命令行的命令經過參數控制不一樣的功能時,就會先傳一個相似-c的參數,而後再接內容。
[root@192-168-3-163 scripts]# cat test.sh #!/bin/bash echo $1 $2 if [ $# -eq 2 ] then shift echo $1 fi [root@192-168-3-163 scripts]# sh test.sh 1 2 1 2 2 [root@192-168-3-163 scripts]# sh test.sh -c 1 -c 1 1
能夠參考ssh-copy-id -i /root/.ssh/id_dsa.pub
[root@192-168-3-163 scripts]# sed -n '105,122p' /usr/bin/ssh-copy-id case "$1" in -i?*|-o?*|-p?*) OPT="$(printf -- "$1"|cut -c1-2)" OPTARG="$(printf -- "$1"|cut -c3-)" shift ;; -o|-p) OPT="$1" OPTARG="$2" shift 2 ;; -i) OPT="$1" test "$#" -le 2 || expr "$2" : "[-]" >/dev/null || { OPTARG="$2" shift } shift
做用:方便
有關set和eval命令的使用案例(特殊位置的變量用法)參考http://oldboy.blog.51cto.com/2561410/1175971