Shell變量知識進階

一,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

相關文章
相關標籤/搜索