shell 指令碼-基本用法(一)

2020-08-08 13:29:09

變數基礎概念

變數型別

內建變數(環境變數) ,如:PS1,PATH,UID,HOSTNAME,$,BASHPID,PPID,,BASHPID,PPID,?,HISTSIZE 等
使用者自定義變數

數據型別:字元和數值。數值包含整型、浮點型,bash 不支援浮點數

變數命名法則

1 不能使用程式中的關鍵字和內建變數,如:if,for
2 只能使用數位、字母及下劃線,且不能以數位開頭。注意:不支援短橫線「-」,和主機名相反
3 見名知意,建議用英文單詞命名,並體現實際作用,最好不要用簡寫
4 統一命名規則:駝峯命名法(studentname),大駝峯(StudentName),小駝峯(studentName)
5 變數名大寫:STUDENT_NAME
6 區域性變數小寫
7 函數名小寫

變數定義和應用

變數的生效範圍等標準劃分變數型別

普通變數:生效範圍爲當前shell 進程;對當前shell 之外的其他shell 進程,包括當前shell 的子shell 進程均無效

環境變數:生效範圍爲當前shell 進程及其子進程

本地變數:生效範圍爲當前shell 進程中某程式碼片段,通常指函數

變數賦值

name='value'

value的多種形式
直接字串	name='root'
變數參照	name="$USER"
命令參照	name=`COMMAND` 或者 name=$(COMMAND)

需要注意的是:

變數賦值是臨時生效,當退出終端後,變數會自動刪除,無法持久儲存。指令碼中的變數也會隨着指令碼結束,自動刪除

變數參照

$name${name} 	建議使用${name}

"$name" 弱參照,其中的變數參照會被替換爲變數值
'$name' 強參照,其中的變數參照不會被替換爲變數值,而保持原字串

範例:變數的各種賦值方式和參照

#變數的賦值方式
[root@CentOS8 ~]#TITLE='cto'
[root@CentOS8 ~]#echo $TITLE
cto
[root@CentOS8 ~]#TITLE='cto'
[root@CentOS8 ~]#echo $TITLE
cto
[root@CentOS8 ~]#echo "i am $TITLE"
i am cto
[root@CentOS8 ~]#echo 'i am $TITLE'
i am $TITLE

[root@CentOS8 ~]#FILE=`ls /run`
[root@CentOS8 ~]#echo $FILE
agetty.reload auditd.pid console cron.reboot cryptsetup dbus faillock fsck initctl initramfs lock log mount NetworkManager plymouth rsyslogd.pid sepermit setrans sshd.pid sssd.pid sudo systemd tmpfiles.d tuned udev user utmp vmware

#變數的參照
[root@CentOS8 ~]#NAME=dawn
[root@CentOS8 ~]#AGE=17
[root@CentOS8 ~]#echo $NAME $AGE
dawn 17
[root@CentOS8 ~]#echo $NAME$AGE
dawn17
[root@CentOS8 ~]#echo $NAME_$AGE
17
[root@CentOS8 ~]#echo ${NAME}_$AGE
dawn_17

#變數的間接賦值和參照,ps:原變數的值修改後,被賦值的變數的值不會隨之變更
[root@CentOS8 ~]#TITLE=cto
[root@CentOS8 ~]#NAME=dawn
[root@CentOS8 ~]#TITLE=$NAME
[root@CentOS8 ~]#echo $NAME
dawn
[root@CentOS8 ~]#echo $TITLE
dawn
[root@CentOS8 ~]#NAME=haha
[root@CentOS8 ~]#echo $NAME
haha
[root@CentOS8 ~]#echo $TITLE
dawn

#利用變數實現動態命令
[root@CentOS8 ~]#CMD=hostname
[root@CentOS8 ~]#$CMD
CentOS8.dawn

變數的顯示和刪除

set		顯示已定義的所有變數
unset <name>	刪除變數name

範例

[root@CentOS8 ~]#NAME=dawn
[root@CentOS8 ~]#TITLE=ceo
[root@CentOS8 ~]#echo $NAME $TITLE
dawn ceo
[root@CentOS8 ~]#unset NAME TITLE
[root@CentOS8 ~]#echo $NAME $TITLE

[root@CentOS8 ~]#

環境變數

  • 可使子進程(子子孫孫進程)繼承父進程的變數,但無法讓父進程使用子進程的變數
  • 一旦子進程修改從父進程繼承的變數,會將新的值傳遞給孫子進程,不影響父進程的值
  • 一般只在系統組態檔中使用,在指令碼使用較少

宣告賦值參照

#宣告並賦值
export name=VALUE
declare -x name=VALUE

#也可先賦值再宣告
name=VALUE
export name

#變數參照
$name${name}

顯示所有環境變數

[root@CentOS8 ~]#env
[root@CentOS8 ~]#printenv
[root@CentOS8 ~]#export
[root@CentOS8 ~]#declare -x

刪除變數

unset name

只讀變數

只能宣告定義,後續不能修改和刪除,即常數

宣告檢視

#宣告
readonly name  或declare -r name

#檢視
readonly [-p]
declare -r

範例

#宣告常數PI
[root@CentOS8 ~]#readonly PI=3.1415926
[root@CentOS8 ~]#echo $PI
3.1415926
#無法修改常數
[root@CentOS8 ~]#PI=3.14
-bash: PI: readonly variable
#無法刪除
[root@CentOS8 ~]#unset PI
-bash: unset: PI: cannot unset: readonly variable

#退出當前shell,常數就被銷燬了
[root@CentOS8 ~]#exit

位置變數

在bash shell 中內建的變數,在指令碼程式碼中呼叫通過命令列傳遞給指令碼的參數

$1,$2,...$n 	對應第1個,第2個等第n個參數,shift [n]換位置
$0	命令本身,包括路徑
$*	傳遞給指令碼的所有參數,全部參數視爲一個字串
$@	傳遞給指令碼的所有參數,每個參數視爲獨立字串
$#	傳遞給指令碼的參數的個數
$$	指令碼執行的過程ID號

ps:$@ $* 只有在被雙引號抱起來的時候纔會有差異

清空所有位置變數

set --

範例

[root@CentOS8 script]#cat args.sh 
#!/bin/bash
#********************************************************************
# Author:dawn
# Date:2020-08-08 10:21:18
# FileName:args.sh
# URL:https://blog.csdn.net/xiao_dan_
# Version:1.0
# Description:The test script
#********************************************************************
echo "1st arg is $1"
echo "2st arg is $2"
echo "3st arg is $3"
echo "10st arg is ${10}"
echo "11st arg is ${11}"

echo "\$# The number of arg is $#"
echo "\$* All args are $*"
echo "\$@ All args are $@"
echo "The scriptname is `basename $0`"
echo "\$\$ PID is $$"

[root@CentOS8 script]#bash args.sh {a..z}
1st arg is a
2st arg is b
3st arg is c
10st arg is j
11st arg is k
$# The number of arg is 26
$* All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
$@ All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
The scriptname is args.sh
$$ PID is 3052

範例-@@ 和* 的區別

#$@ 和$* 的區別 --主要用在輪詢的時候
[root@CentOS8 script]#cat test.sh
echo "\$* 展示的所有參數:$*"
for i in "$*";do
   echo $i
done

echo "\$@ 展示的所有參數:$@"
for i in "$@";do
    echo $i
done

[root@CentOS8 script]#bash test.sh dawn li 22 33
$* 展示的所有參數:dawn li 22 33
dawn li 22 33
$@ 展示的所有參數:dawn li 22 33
dawn
li
22
33

範例-利用軟鏈接實現同一個指令碼不同功能

[root@CentOS8 script]#vim ln.sh
#!/bin/bash
echo $0
#設定軟鏈接
[root@CentOS8 script]#ln -snf ln.sh a.sh
[root@CentOS8 script]#ln -snf ln.sh b.sh

#執行軟鏈接
[root@CentOS8 script]#bash a.sh 
a.sh
[root@CentOS8 script]#bash b.sh 
b.sh

退出狀態碼變數

在shell 指令碼中使用 $? 儲存程式執行狀態碼的相關數位,不同的值反應成功或失敗,$? 取值範圍在0-255

$?	上一條命令執行後的狀態,0:執行正常,非零爲異常,一般結果爲1

自定義退出狀態碼
exit [n]	n的取值範圍在0-255

範例

[root@CentOS8 ~]#curl http://www.wangxiaochun.com &> /dev/null
[root@CentOS8 ~]#echo $?
0

ps:

  • 指令碼中一旦遇到exit 命令,指令碼會立即終止;終止退出狀態碼取決於exit 命令後的數位
  • 如果未給指令碼指定退出狀態碼,整個指令碼的退出狀態碼取決於指令碼中執行的最後一條命令的狀態碼

指令碼安全和set

set

可用來定製shell 環境

set 命令實現指令碼安全

-u	在擴充套件一個沒有設定的變數時,顯示錯誤資訊,等同set -o nounset
-e	如果一個命令返回一個非0退出狀態值(失敗)就退出,等同set -o errexit
-o	option 顯示,開啓或關閉選項
	顯示選項:set -o
	開啓選項:set -o 選項
	關閉選項:set +o	選項
-x	當執行命令時,列印命令及其參數,類似bash -x

範例

[root@CentOS8 ~]#set -o
allexport      	off
braceexpand    	off
emacs          	on
……省略……

$- 變數

h	hashall,開啓選項後,shell 會將命令所在的路徑hash 下來,避免每次都要查詢。通過set +h 將h 選項關閉
i	interactive-comments,包含這個選項說明當前的shell 是一個互動式的shell。所謂互動式shell,在指令碼中,i 選項是關閉的
m	moniter,開啓監控模式,可通過job control來控制進程的停止、繼續,後臺或前臺執行等
B	braceexpand,大括號擴充套件
H	history,H選項開啓,可展開歷史列表的命令,可通過感嘆號! 來完成,例如:!! 返回最近一個歷史命令,!n 返回第n 個歷史命令

範例

[root@CentOS8 ~]#echo $-
himBHs
[root@CentOS8 ~]#echo {1..10}
1 2 3 4 5 6 7 8 9 10
[root@CentOS8 ~]#set +B
[root@CentOS8 ~]#echo $-
himHs
[root@CentOS8 ~]#echo {1..10}
{1..10}