天天看點

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

1.1 開頭(環境使用shebang機制)

#!/bin/bash 必須寫在檔案首行

符号#!用來告訴系統它後面的參數是用來執行該檔案的程式。

當編輯好腳本時,如果要執行該腳本,還必須使其可執行。

要使腳本可執行:

編譯 chmod +x filename 這樣才能用./filename或source filename 來運作。

1.2 注釋

在進行shell程式設計時,以#開頭的句子表示注釋,直到這一行的結束。我建議在程式中使用注釋。如果使用了注釋,那麼即使相當長的時間内沒有使用該腳本,我們也能在很短的時間内明白該腳本的作用及工作原理。

1.3格式

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

腳本中如果有文法錯誤可以用來:  bash -n /path/to/some_script

調試跟蹤:  bash -x /path/to/some_script

第一行的#!/bin/bash是聲明這個腳本使用的shell格式,因為我們使用的是bash,是以必須要以“#!/bin/bash”來告訴别人這個腳本裡的文法使用的是bash文法,這樣它在執行的時候,就能加載bash相關配置檔案,使我們的指令能夠更好的執行下去。(如果不加,有可能腳本無法執行,無法判斷腳本是使用的什麼shell。當然如果預設選擇bash格式,可以不寫,但最好還是腳本第一行寫上shebang機制,還有就是建立文本的時候,字尾加上.sh為結尾。

2.1 變量定義

所有的變量都由字元串組成,用一個字元串,替代更多更複雜的内容 ,并且您不需要對變量進行聲明。在變量使用指令時需要加` ` 或者$( ).

指派給一個變量,并列印出内容如下:

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

有時候變量名很容易與其他文字混淆,比如:

num=2 echo “this is the $numnd” 這并不會列印出“this is the 2nd”,而僅僅列印”this is the “,因為shell會去搜尋變量numnd的值,但是這個變量時沒有值的。可以使用花括号來告訴shell我們要列印的是num變量:echo “this is the ${num}nd”   這将列印:this is the 2nd。 注意:變量名外面的花括号是可選的,加不加都行,加花括号是為了幫助解釋器識别變量的邊界

2.2 變量格式

1、必須以字母開頭後面可以使用下劃線,數字

2、中間不能有空格,不能使用标點符号,不能使用程式中的保留字如:if,for。

3、駝峰文法:首個字母小寫,其餘開頭字母大寫如 mageJiaoYu

2.3變量分類

本地變量,環境變量,位置變量,特殊變量

變量指派:name=‘value’

可以使用引用value:

(1)可以是直接字串; name=“root”

(2)變量引用:name=”$USER”

(3)指令引用:name=`COMMAND`, name=$(COMMAND)

變量引用:${name}, $name

" ":弱引用,其中的變量引用會被替換為變量值”;

例:[root@localhost ~]# var1=1 [root@localhost ~]# echo "$var1 * '' \$a\\ 1 * $a\ (雙引号比起單引号比較有人情味,也比較聰明,它能識别裡面的變量,不會屏蔽\和$這兩個字元的含義,如果需要屏蔽這些字元含義,除了用單引号外,還可以在前面加個\符号。)

' ':強引用,其中的變量引用不會被替換為變量值,而保持原字元串;

例:[root@localhost ~]# var1=2 [root@localhost ~]# echo '$var1 * \$a\\' $var1 * \$a\\ (單引号可以屏蔽全部字元的特殊意義,但是不能表示一個字元:(單引号')。由于她沒有轉義字元,是以不能表示她本身。強引用)

顯示已定義的所有變量:set

删除變量:unset name  腳本運作完畢要釋放變量。

變量聲明、指派:

export name=VALUE

declare -x name=VALUE

變量引用:$name, ${name}

删除變量:unset name

顯示所有環境變量(環境變量的查詢):

env

printenv

export

declare -x

#env列出環境下所有環境變量與其内容

#set可檢視所有的變量(含環境變量與本地變量)

bash内建的環境變量:PATH   SHELL  UID   HOME   PWD LANG     MAIL     HOSTNAME   HISTSIZE PS1等

例:[root@centos7  ~  ]#  echo  $HOME       [root@centos7 ~]#   /root

$1, $2, …:對應第1、第2等參數,shift  [n]換位置。當位置參數遇到10及10以上的要用{  };例:echo 10st        結果為arg is {10}。

$0:指令本身,是用于取腳本本身的名字

[root@centos7  tmp]# vim file1 #!/bin/bash dirname $0 basename $0 [root@centos7  tmp]# bash ./file1 . file1 [root@centos7  tmp]# bash /tmp/file1 /tmp

$#:傳遞給腳本的參數的個數,一般用于控制參數個數。

[root@centos7  tmp]#vim file2 echo $# [root@centos7  tmp]# bash file2  123 3 [root@centos7  tmp]# bash file2  123456 6

$?:判斷上個指令腳本,函數是否執行成功,指令執行的傳回值,0表示沒有錯誤,其他表示有錯誤,代表上個指令執行失敗

[root@centos7  tmp] # ls    file1    file2 [root@centos7  tmp] # echo $? [root@centos7  ~] # lls bash:lls:command not found... [root@centos7  ~] # echo $?  1

$*:傳遞給腳本的所有參數,全部參數合為一個字元串

$@:傳遞給腳本的所有參數,每個參數為獨立字元串

$@ $*隻在被雙引号包起來的時候才會有差異

set —清空所有位置變量

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

小總結:變量内容若有空格符可使用雙引号"  "或者單引号'  '将變量内容結合起來:

a.雙引号内的特殊字元如$等,可以保持原本的特性,如:

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

b.單引号内的特殊字元則僅為一般字元(純文字),如:

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

c.可用轉義字元“\”将特殊符号(如$、\、!)變成一般字元。如

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

d.在一串指令中,還需要通過其他的指令提供的資訊,可以使用反單引号“`指令`”或者“$(指令)”,如:

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

e.若該變量為了增加變量内容時,則可用“$變量名稱”或${變量}累加内容,如:給變量PATH增加内容,不能直接用”PATH=内容“,這樣會覆寫掉原本的變量值,應該用“PATH=$PATH:内容”.

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

f.若該變量需要在其他子程序(子程序:在目前這個shell的情況下,去打開另一個新的shell,新的shell就是子程序)執行,則需要以export來使變量變成環境變量。如:

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

g.取消變量的方法為使用“unset變量名稱”,如:

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

3.1按生效範圍劃分,存在兩類:

全局配置:/etc/profile            /etc/profile.d/*.sh          /etc/bashrc

個人配置:~/.bash_profile         ~/.bashrc

3.2按功能劃分,存在兩類:

profile類和bashrc類

profile類:為互動式登入的shell提供配置

全局:/etc/profile, /etc/profile.d/*.sh

個人:~/.bash_profile

功用:(1)用于定義環境變量   (2)運作指令或腳本

bashrc類:為非互動式和互動式登入的shell提供配置

全局:/etc/bashrc

個人:~/.bashrc

功用:(1)定義指令别名和函數   (2)定義本地變量

3.3shell登入兩種方式

互動式登入:(不能繼承上一個shell)

(1)直接通過終端輸入賬号和密碼登入

(2)使用“su -l UserName 或su - UserName”切換的使用者

執行順序:/etc/profile –> /etc/profile.d/*.sh –> ~/.bash_profile–> ~/.bashrc–> /etc/bashrc

非互動式登入:(繼承上一個shell)

(1)su  UserName

(2)圖形界面下打開的終端,執行腳本

執行順序:~/.bashrc–> /etc/bashrc–> /etc/profile.d/*.sh

例子:在這幾個檔案分别設定環境變量A,B,C,D,E

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

沒有重新登陸時,這幾個變量就不會生效,echo $A   $B $C $D $E,什麼都不顯示。重新登陸後,這幾個變量就會生效。

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

用非互動式登陸guanyu使用者,就會繼承上一個shell,是以echo 5個變量都會顯示。而用互動式登陸guanyu使用者,不能繼承上一個shell,就隻能讀取/etc/profile,/etc/profile.d/*.sh,~/.bash_profile,~/.bashrc,/etc/bashrc這幾個檔案,而變量C,D都是在使用者root的家目錄設定的,隻能讀取到變量A,B,E,是以echo這幾個變量隻顯示變量A,B,E的值。

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

在root使用者下,将變量A的值改為A6,變量B的值改為B7,變量D的值改為D9,變量E的值改為E10

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

然後不退出重新登陸,直接echo這幾個變量,當然不變,因為這幾個變量沒有生效,此時用非互動式登陸切到guanyu使用者下,變量A的值不變,盡管,變量A的值變為A6,但是用非互動式登陸,繼承了上一個shell變量A的值A1,但是不讀取/etc/profile這個檔案,是以不更新變量A的值,變量B的值變為B7,是因為繼承了上一個shell變量B的值然後讀取/etc/profile.d/mage.sh這個檔案,更新變量B的值。變量C3的值不變,變量D的值為D4,是因為繼承了上一個shell的變量D的值D4,又因為變量D在root使用者的家目錄裡,是以不讀取,不更新變量D的值。變量E5的值為E10,是因為繼承了上一個shell的變量D的值,又讀取/etc/bashrc是以更新變量E的值,是以變量E的值為E10.

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句
Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

在用互動式登陸guanyu使用者,echo這幾個變量,不繼承上一個shell,隻讀取檔案,因為是互動式登陸,是以/etc/profile,/etc/profile.d/mage.sh,/etc/bashrc這幾個檔案都能讀取,是以變量A,B,E的值為A6,B7,E10,又因為變量C,D都在root使用者的家目錄裡,是以不能讀取,變量C,D的值為空。

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

3.4   read

變量的定義—read讀入    預設存儲位置$REPLY

如果傳的參數多于指派,最後一個值會全部接收

–p增加提示

[root@centos7 ~]# read  -p "輸入密碼" e  (必須有空格) 輸入密碼123456 [root@centos7 ~]# echo $e 123456

–s 隐藏輸入

[root@centos7 ~]# read -s -p "輸入密碼" e  (将密碼隐藏) 輸入密碼

-t  設定逾時時間

[root@centos7 ~]# read -t5 -p "輸入密碼" e    (表示5秒後直接退出目前操作) 輸入密碼[root@centos7~]#

4.1條件判斷

[root@centos7 ~]# [ -f /etc/hosts ]    判斷是否是檔案 [root@centos7~]# echo $?

4.2  &&  ||

&&表示前面執行成功,執行後面.

||表示前面執行成功,不執行後面,前面執行失敗,執行後面

[root@centos7 ~]# [ -f /etc/hosts ]&& echo "檔案存在" || echo "檔案不存在"   相當于傳回值0和1 檔案存在
[root@centos7 ~]# [ -f /etc/host ]&& echo "檔案存在" || echo "檔案不存在" 檔案不存在

4.3  測試檔案符号(test)

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

4.4  測試字元串

Shell腳本基礎入門一、shell腳本介紹 二、變量四、邏輯判斷語句五、循環語句

特别注意:字元串必須要用雙引号引起來。字元串比較,比較符号兩端必須有空格。

4.5測試大小

[root@centos7 ~]# [ 1 -eq 1 ] && echo "表達式成立" || echo "表達式不成立" 表達式成立 [root@centos7 ~]# [ 1 -eq 2 ] && echo "表達式成立" || echo "表達式不成立" 表達式不成立
[root@centos7 ~]# [ 1 -ne 2 ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ 1 -gt 2 ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ 1 -gt 0 ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ 1 -gt 1 ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ 1 -ge 1 ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ 1 -le 1 ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ 1 -lt 1 ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ 1 -lt 2 ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ 1 = 1 ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ 1 = 2 ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ "1" = "2" ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ "1" != "2" ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ "1" > "2" ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ "1" \> "2" ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ "1" \< "2" ] && echo "表達式成立" || echo "表達式不成立" [root@centos7 ~]# [ "1" \<= "2" ] && echo "表達式成立" || echo "表達式不成立" -bash: [: <=: binary operator expected [root@centos7 ~]# [ "1" \<\= "2" ] && echo "表達式成立" || echo "表達式不成立"

4.6  與或非  -a   -o  !

-a 前一個條件成立,後一個條件成立,整個表達式才成立,有一個是錯的都不會成立

-o 隻要任意一個條件成立,表達式就成立,隻有倆個都不成立,才不成立,則表達式不成立

[root@centos7 ~]# [ "1" = "1" -a "2" = "2" ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ "1" = "1" -a "2" = "3" ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ "1" = "1" -o "2" = "3" ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ "1" = "2" -o "2" = "3" ] && echo "表達式成立" || echo "表達式不成立"
[root@centos7 ~]# [ "1" = "1" -a !"2" = "3" ] && echo "表達式成立" || echo "表達式不成立" -bash: !"2": event not found
[root@centos7 ~]# [ "1" = "2" -o ! "2" = "3" ] && echo "表達式成立" || echo "表達式不成立"

if 語句    單分支語句

文法格式:

如果if  [條件語句]

然後 then

執行指令

fi

執行個體:編寫一個腳本/root/bin/createuser.sh,腳本的執行文法必須是:createuser.sh -u username -m password,選項與參數間可支援多空格,但不能順序颠倒。

當未指定正确的選項或參數時,以錯誤輸出方式提示“createuser.sh -u username -m password ”後退出腳本。

使用者名必須以字母開頭,可包括數字和_。否則不合法。以錯誤輸出提示使用者"使用者名僅包含字母資料和下劃線"

當使用者名檢測合法後,判斷使用者名是否已存在,若存在,再判斷使用者是否已設定過密碼,若設定過密碼,直接退出,未設定,則将密碼設定為所指定的密碼後以正确輸出方式顯示“username 密碼已更新後退出”

當使用者名不存在,則建立使用者,并為該使用者設定所指定的密碼後以正确輸出方式顯示“使用者username已建立并更新密碼”

要求腳本執行過程中不能有非要求的其他輸出結果出現。腳本在非正确方式退出時應反回給?參數非0值。

#判斷使用者名是否規範,并且給出傳回值

decide=`(echo $2|grep "^[[:alpha:]]\([[:alpha:]]\|[[:digit:]]\|_\)*$" &>/dev/null;echo $?)`

#判斷使用者是否存在,并給出傳回值

id=`id $2 &>/dev/null;echo $?`

#截取使用者密碼位

mima=`getent  shadow $2 |cut -d: -f 2`

#判斷第一個參數

if [ "$1" != "-u" ];then

echo "createuser.sh -u username -m password"

exit 1

#判斷第三個參數

if [ "$3" != "-m" ];then

#判斷參數個數

if [ $# -ne 4 ];then

echo " createuser.sh -u username -m password"

#判斷第二個參數

if  [ $decide -ne 0 ];then

echo "使用者僅包含字母數字和下劃線"

else

if [ $id -eq 0 ];then

if [ "$mima" == "!!" -o "$mima" == "" ];then

`echo "$4" |passwd --stdin $2 &>/dev/null`

echo "$2密碼已更新"

`useradd $2`

`echo $4 |passwd --stdin $2  &>/dev/null`

echo "使用者$2已建立并更新密碼"

#删除變量

unset decide

unset id

unset mima

解析:先定義變量decide,id,mima,再對變量進行測試。

練習:

1.寫一個腳本名為jiaozuoyexx.sh 當執行該腳本時如jiaozuoyeXX.sh testXX.sh,就會自動将該testXX.sh傳給教師機,

路徑是scp testXX.sh [email protected]:~/scripts  密碼為mage26

1、vim jiaozuoye.sh

--------------------------

# Filename:

# Revision:

# Date:

# Author:

# Email:

# Website:

# Description:

# ------------------------------------------

scp $1 [email protected]:~/scripts

2、chmod +x createshXX.sh            添權重限

3、./jiaozuoyeXX.sh jiaozuoyeXX.sh   檢視結果

思路:這裡的$1實際是個參數,代表腳本名稱。

2.寫一個能夠建立新腳本的Shell script,如名為createshXX.sh 當執行時createsh /root/bin/test1.sh

則會自動建立并打開/root/bin/test1.sh,且其中包含以下内容。

1、vim createshXX.sh

2、#!/bin/bash

echo "#!/bin/bash

" >>$1

chmod +x createshXX.sh

vim $1

3、修改腳本要進入vim createshXX.sh

4、./jiaozuoyeXX.sh createshXX.sh

此處>>表示追加

3、編寫腳本/root/bin/sumid.sh,計算/etc/passwd檔案中的第10個使用者和第20使用者的ID之和

1、./createsh36.sh(相當于一個指令) /root/bin/sumid.sh 進入編輯界面

#--------------------------------------------------

# Filename:/root/bin/sumid.sh

# Version:1.0

# Date:'date "+%F %T"'

# Author:Lemon.

# Description:ID之和

echo "$[$(cat /etc/passwd|head -10|tail -1|cut -d: -f3)+$(cat /etc/passwd|head -20|tail -1|cut -d: -f3)]"

chmod +x /root/bin/sumid.sh

4、cd /root/bin/   需要進入腳本目錄才能檢視結果

5、./sumid.sh   檢視檔案結果

或uid=10  uid=20

Uid1=`head -$1 /etc/passwd|tail -1|cut -d: -f3`

Uid2=`head -$2 /etc/passwd|tail -1|cut -d: -f3`

Sumid=$[Uid1+Uid2]

echo "Sumid is $Sumid"

unset Uid1 Uid2  Sumid

分析:分别表示出第10個使用者和第20個使用者

4、編寫腳本/root/bin/sumfile.sh,統計/etc, /var, /usr目錄中共有多少個一級子目錄和檔案

1、./createsh36.sh sumfile.sh

file1=`ls -A /etc|wc -l`

file2=`ls -A /var|wc -l`

file3=`ls -A /usr|wc -l`

let sum=$file1+$file2+$file3

echo "$sum"

unset file1 file2 file3 sum

chmod +x sumfile.sh

3、 ./sumspace.sh /etc /var /usr

注意:要想引用一串指令需要用` `和$( )引用。

5、編寫腳本/root/bin/checkdisk.sh,檢查磁盤分區空間和inode使用率,如果超過80%,就發廣播警告空間将滿

diskused_max=`df | grep "/dev/sd"|sort -nr -k5|head -1|tr -s ' ' %|cut -d% -f5`

inodeused_max=`df -i| grep "/dev/sd"|sort -nr -k5|head -1|tr -s ' ' %|cut -d% -f5`

[ "$diskused_max" -gt "80" ] && wall "空間即将滿"||echo "空間使用率不超過80%"

[ "$inodeused_max" -gt "80" ] && wall "inode即将滿"||echo "inode使用率不超過80%"

unset diskused_max inodeused_max

解釋:搜尋到磁盤分區中的分區/dev/sd,sort -nr -k5表示取第5列然後按數字從大到小排列,tr -s ' ' %将空格替換成%,再剪切,随後和80比較。

-----------------------答案2---------------------------------------------------

dev=`df|grep "/dev/sd"|egrep -o "[0-9]{1,3}%"|sort -n|tail -n 1|cut -d% -f1`

ino=`df -i|egrep -o "[0-9]{1,3}%" |sort -n|tail -n 1|cut -d% -f1`

[[ "$dev" -gt 80 ]] || [[ "$ino" -gt 80 ]] && echo $(wall 磁盤已滿)||echo 還有很多利用空

間呦

unset dev

unset ino

解釋:egrep -o 隻顯示被模式比對的字串,[0-9]{1,3}%表示在空間使用率這裡前面的字元比對至少1次,最多3次,随後剪切,排序。這裡的比較用或表示,隻要有一個滿了,另一個不用比較,就能發出警報。

本文轉自 優果馥思 51CTO部落格,原文連結:http://blog.51cto.com/youguofusi/1965690