shell腳本編程初步–吐血整理

shell腳本編程

編程基礎

程序:

程序的構成:指令 + 數據

程序的編程風格:

    過程式:以指令為中心,數據服務于指令

    對象式:以數據為中心,指令服務于數據

shell程序:提供了編程能力,解釋執行

shell,perl,python語言均為高級編程語言

編程的邏輯處理方式:

    順序執行

循環執行

選擇執行

shell編程:過程式、解釋執行

 

腳本基本格式

shell腳本是包含一些命令或聲明,并符合一定格式的文本文件

格式要求:首行shabanng機制

#!/bin/bash

#!/usr/bin/python

#!/usr/bin/perl

 

shell腳本用途:

自動化常用命令

執行系統管理和故障排除

創建簡單的應用程序

處理文本或文件

 

如何創建shell腳本

第一步:使用文本編輯器來創建文本文件

        第一行必須為shell聲明序列,即shebang

            例如:#!/bin/bash

        添加注釋:

            注釋以#開頭(以#開頭的行不會被執行)

第二步:運行腳本

        給予執行權限,在命令執行上指定腳本的絕對或相對路徑

        運行解釋器,將腳本作為解釋器程序的參數運行

   

#!/bin/bash

#author: wang

#Version: 1.0

#Description:This script displays some information about your# environment echo "Greetings. The date and time are $(date)" echo "Your working directory is: $(pwd)"

 

腳本調試:

bash –n /path/to/some_script:檢測腳本中的語法錯誤

bash –x /path/to/some_script:調試執行

 

變量

變量即是命名的內存空間

bash變量為弱類型變量

      即無需指定類型,默認均為字符型;參與運算會自動進行隱式類型轉換,變量無需實現定義,可直接調用

變量命名法則:

1、不能使用程序中保留字,如if,for…

2、只能使用數字、字母及下劃線,且不能以數字開頭

3、見名知義

4、統一命名法則:駝峰命名法

 

根據變量的生效范圍等標準可做以下歸類:

   本地變量:生效范圍為當前shell進程

   環境變量:生效范圍為當前shell進程及其子進程

   局部變量:生效范圍為當前shell進程中某代碼片段(通常為函數)

   位置變量:$1、$2…,用于表示腳本代碼中調用命令行的參數

   特殊變量:$?à 前一條命令的執行結果,0表示成功,1-255表示失敗

             $0à 命令本身

             $#à 參數的數量

 

本地變量:

變量賦值:name=‘value’,

可以使用引用value:

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

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

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

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

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

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

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

刪除變量:unset name

 

環境變量:

變量聲明、賦值:

export name=VALUE

declare -x name=VALUE

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

顯示所有環境變量:

export

env

printenv

刪除: unset name

bash有許多內建的環境變量: PATH, SHELL, USRE,UID,HISTSIZE, HOME, PWD, OLDPWD, HISTFILE, PS1

 

只讀和位置變量:

 

只讀和位置變量

只讀變量:只能聲時,但不能修改和刪除

readonly name

declare -r name

一般是常量中會使用

declare –rx name 表示既是一個常量又是一個環境變量

但是隨shell進程終止而終止

位置變量:在腳本代碼中調用通過命令行傳遞給腳本的參數

$1, $2, …:對應第1、第2等參數,shift [n]換位置

$0: 命令本身

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

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

$#: 傳遞給腳本的參數的個數

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

 

運算

算術運算:

+, -, *, /, %取模(取余), **(乘方)

實現算術運算:

(1) let var=算術表達式

(2) var=$[算術表達式]

(3) var=$((算術表達式))

(4) var=$(expr arg1 arg2 arg3 …)

(5) declare –i var= 數值

(6) echo ‘算術表達式’ | bc

乘法符號有些場景中需要轉義,如*

bash有內建的隨機數生成器:$RANDOM(1-32767)

echo $[$RANDOM%50] :0-49之間隨機數

如果要表示2-51:echo $[$RANDOM%50+2]

表示1-n: echo $[$RANDOM%N+1]

賦值

增強型賦值:

+=, -=, *=, /=, %=

let varOPERvalue

例如:let count+=3

自加3后自賦值

自增,自減:

let var+=1

let var++

let var-=1

let var–

 

邏輯運算

true, false

1     0

與:

1 與 1 = 1

1 與 0 = 0

0 與 1 = 0

0 與 0 = 0

或:

1 或 1 = 1

1 或 0 = 1

0 或 1 = 1

0 或 0 = 0

非:!

! 1 = 0

! 0 = 1

短路運算:

短路與:

第一個為0,結果必定為0;

第一個為1,第二個必須要參與運算;

短路或:

第一個為1,結果必定為1;

第一個為0,第二個必須要參與運算;

異或:^

異或的兩個值,相同為假,不同為真

 

例如:

#command1 && command2

command1為“假”,則command2 不會再執行

否則,command1為“真”,則command2必須執行

#command1 || command2

command1為“假”,則command2 必須執行

否則,command1為“真”,則command2不會再執行

要實現user1用戶不存在就添加用戶user1

id user1 || useradd user1

 

 

退出狀態

進程使用退出狀態來報告成功或失敗

0 代表成功,1-255代表失敗

$? 變量保存最近的命令退出狀態

例如:

ping-c1-W1hostdown&>/dev/null

echo$?

退出狀態碼

bash自定義退出狀態碼

exit [n]:自定義退出狀態碼;

注意:腳本中一旦遇到exit命令,腳本會立即終止;終止退出狀態取決于exit命令后面的數字

注意:如果未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決于腳本中執行的最后一條命令的狀態碼

 

 

 

條件測試

判斷某需求是否滿足,需要由測試機制來實現;

專用的測試表達式需要由測試命令輔助完成測試過程;

評估布爾聲明,以便用在條件性執行中

若真,則返回0

若假,則返回1

測試命令:

test EXPRESSION

[ EXPRESSION ]

[[ EXPRESSION ]]

注意:EXPRESSION前后必須有空白字符

 

條件性的執行操作符

根據退出狀態而定,命令可以有條件地運行

&& 代表條件性的AND THEN

 

|| 代表條件性的OR ELSE

例如:

grep-qno_such_user/etc/passwd ||echo'Nosuchuser'

Nosuchuser

ping-c1-W2station1&>/dev/null >&& echo"station1isup" || (echo'station1isunreachable';exit1)

station1isup

test命令

長格式的例子:

test "$A"=="$B" && echo "Stringsareequal"

test "$A" -eq "$B" && echo "Integersareequal"

簡寫格式的例子:

[ "$A" == "$B" ] && echo "Stringsareequal"

[ "$A" -eq "$B" ] && echo "Integersareequal"

數值測試:

-gt:是否大于;

-ge:是否大于等于;

-eq:是否等于;

-ne:是否不等于;

-lt:是否小于;

-le:是否小于等于;

字符串測試:

==:是否等于;

>:ascii碼是否大于ascii碼

<:是否小于

!=:是否不等于

=~:左側字符串是否能夠被右側的PATTERN所匹配

 

注意:此表達式一般用于[[ ]]中;

-z "STRING":字符串是否為空,空為真,不空為假

-n "STRING":字符串是否不空,不空為真,空為假

注意:用于字符串比較時的用到的操作數都應該使用引號

 

文件測試

存在性測試

-a FILE:同-es

-e FILE: 文件存在性測試,存在為真,否則為假;

存在性及類別測試

-b FILE:是否存在且為塊設備文件;

-c FILE:是否存在且為字符設備文件;

-d FILE:是否存在且為目錄文件;

-f FILE:是否存在且為普通文件;(存在為真)

-h FILE 或-L FILE:存在且為符號鏈接文件;

-p FILE:是否存在且為命名管道文件;

-S FILE:是否存在且為套接字文件;

文件權限測試:

-r FILE:是否存在且可讀

-w FILE: 是否存在且可寫

-x FILE: 是否存在且可執行

 

文件特殊權限測試:

-g FILE:是否存在且擁有sgid權限;

-u FILE:是否存在且擁有suid權限;

-k FILE:是否存在且擁有sticky權限;

文件大小測試:

-s FILE:是否存在且非空;

非空為真,空為假

文件是否打開:

-t fd:fd表示文件描述符是否已經打開且與某終端相關

-N FILE:文件自上一次被讀取之后是否被修改過(讀先發生,寫后發生)

就是讀的時間比較舊

 

雙目測試:

FILE1 –ef  FILE2: FILE1與FILE2是否指向同一個設備上的相同inode(硬鏈接)

FILE1 –nt  FILE2: FILE1是否新于FILE2;(修改的時間)

FILE1 –ot  FILE2: FILE1是否舊于FILE2;(修改的時間)

組合測試條件

第一種方式:

COMMAND1 && COMMAND2 并且

COMMAND1 || COMMAND2 或者

! COMMAND

如:[ -e FILE ] && [ -r FILE ]

第二種方式:

EXPRESSION1 -a EXPRESSION2 并且

EXPRESSION1 -o EXPRESSION2 或者

! EXPRESSION

必須使用測試命令進行,即進行test或者[ ];

 

意思是只要主機名沒有定義或者主機名為默認就改為www.magedu.com

# [ -z “$HOSTNAME” -o $HOSTNAME "== "localhost.localdomain" ] && hostname www.magedu.com

 

判斷/bin/cat是否為可執行文件,如果是就調用

# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

 

使用read命令來接受輸入

使用read來把輸入值分配給一個或多個shell變量:

-p:指定要顯示的提示

-t:TIMEOUT

read從標準輸入中讀取值,給每個單詞分配一個變量

所有剩余單詞都被分配給最后一個變量

read -p “Enter a filename:“ FILE

條件選擇if語句

選擇執行

注意:if語句可嵌套

單分支

if 判斷條件:then

條件為真的分支代碼

fi

雙分支

if 判斷條件; then

條件為真的分支代碼

else

條件為假的分支代碼

fi

多分支

if CONDITION1; then

if-true

elifCONDITION2; then

if-ture

elifCONDITION3; then

if-ture

else

all-false

fi

逐條件進行判斷,第一次遇為“真”條件時,執行其分支,而后結束整個if語句

 

條件判斷:case語句

case 變量引用in

PAT1)

分支1

;;

PAT2)

分支2

;;

*)

默認分支

;;

esac

   

case支持glob風格的通配符:

*:任意長度任意字符

?:任意單個字符

[]:指定范圍內的任意單個字符

a|b:a或b


練習:

1、寫一個腳本/root/bin/createuser.sh,實現如下功能:使用一個用戶名做為參數,如果指定參數的用戶存在,就顯示其存在,否則添加之;顯示添加的用戶的id號等信息

代碼:

[root@localhost bin]# cat creatuser.sh

#!/bin/bash

 

echo "Please input a username:"

read username

id $username &> /dev/null

if [[ $? -eq 0 ]];then

    echo "用戶已存在"

else

    useradd $username;echo "用戶$username添加成功"

    id $username

fi

測試:

[root@localhost bin]# creatuser.sh

Please input a username:

wang

用戶已存在

[root@localhost bin]# creatuser.sh

Please input a username:

li

用戶li添加成功

uid=1007(li) gid=1007(li) groups=1007(li)

 

2、寫一個腳本/root/bin/yesorno.sh,提示用戶輸入yes或no,并判斷用戶輸入的是yes還是no,或是其它信息

代碼:

[root@localhost bin]# cat yesorno.sh

#!/bin/bash

read -p "Please input yes or no:" x

case $x in

[Yy][Ee][Ss]|[Yy])

    echo you have inputde yes

;;

[Nn][Oo]|[Nn])

    echo you have inputed no

;;

*)

    echo illegal input

;;

esac

測試:

[root@localhost bin]# yesorno.sh

Please input yes or no:yes

you have inputde yes

 

[root@localhost bin]# yesorno.sh

Please input yes or no:Yes

you have inputde yes

 

[root@localhost bin]# yesorno.sh

Please input yes or no:no

you have inputed no

 

[root@localhost bin]# yesorno.sh

Please input yes or no:No

you have inputed no

 

[root@localhost bin]# yesorno.sh

Please input yes or no:aa

illegal input

 

3、寫一個腳本/root/bin/filetype.sh,判斷用戶輸入文件路徑,顯示其文件類型(普通,目錄,鏈接,其它文件類型)

代碼:

[root@localhost bin]# cat filetype.sh

#!/bin/bash

 

echo "請輸入一個文件路徑"

read file

if [[ -L $file ]];then

    echo $file 是一個符號鏈接文件

elif [[ -f $file ]];then

    echo $file 是一個普通文件

elif [[ -b $file ]];then

    echo $file 是一個塊設備文件

elif [[ -c $file ]];then

    echo $file 是一個字符設備文件

elif [[ -d $file ]];then

    echo $file 是一個目錄文件

elif [[ -p $file ]];then

    echo $file 是一個管道文件

elif [[ -S $file ]];then

    echo $file 是一個套接字文件

else

    echo No such file

fi

測試:

[root@localhost bin]# filetype.sh

請輸入一個文件路徑

/etc/rc1.d

/etc/rc1.d 是一個符號鏈接文件

[root@localhost bin]# filetype.sh

請輸入一個文件路徑

/etc/issue

/etc/issue 是一個普通文件

[root@localhost bin]# filetype.sh

請輸入一個文件路徑

/testdir

/testdir 是一個目錄文件

[root@localhost bin]# filetype.sh

請輸入一個文件路徑

/run/systemd/notify

/run/systemd/notify 是一個套接字文件

[root@localhost bin]# filetype.sh

請輸入一個文件路徑

/dev/sda

/dev/sda 是一個塊設備文件

[root@localhost bin]# filetype.sh

請輸入一個文件路徑

/dev/null

/dev/null 是一個字符設備文件

[root@localhost bin]# filetype.sh

請輸入一個文件路徑

/dev/zero

/dev/zero 是一個字符設備文件

 

4、寫一個腳本/root/bin/checkint.sh,判斷用戶輸入的參數是否為正整數

[root@localhost bin]# cat checkini.sh

代碼:

#!/bin/bash

 

echo "Please input a number"

read num

if [[ -z $num ]];then

    echo "至少要輸入一個數值"

exit

fi

 

NUM=$(echo $num |egrep -o '^\-?[[:digit:]]+$')

if [[ $num == $NUM ]];then

 

   if [[ $num -gt 0 ]];then

    echo $num 是一個正整數

   elif [[ $num -eq 0 ]];then

    echo 輸入的是0

   else

    echo $num 是一個負整數

   fi

 

else

    echo $num 不是一個整數

fi

測試:

[root@localhost bin]# checkini.sh

Please input a number

0

輸入的是0

[root@localhost bin]# checkini.sh

Please input a number

1

1 是一個正整數

[root@localhost bin]# checkini.sh

Please input a number

-8

-8 是一個負整數

[root@localhost bin]# checkini.sh

Please input a number

sss

sss 不是一個整數

原創文章,作者:Mr.Lee,如若轉載,請注明出處:http://www.www58058.com/36625

(0)
Mr.LeeMr.Lee
上一篇 2016-08-18
下一篇 2016-08-18

相關推薦

  • linux中硬鏈接與軟鏈接的區別

    硬連接和軟鏈接的區別: 1、          首先,兩者的作用對象不同: 硬鏈接,只能應用于文件,而不能應用于目錄,而且不能跨文件系統(即分區)。 軟(符號)鏈接,可以應用于文件,而且可以應用于目錄和可跨文件系統(分區)。 2、   &n…

    Linux干貨 2016-10-20
  • mysql5.5.32多實例配置

    操作系統:CentOS release 6.7 (Final) 內核版本:2.6.32-573.el6.x86_64 mysql版本號:mysql-5.5.32 1)安裝mysql所需的依賴包 # adduser mysql -s /sbin/nologin -M # mkdir -p&n…

    Linux干貨 2016-12-05
  • 磁盤配額

    磁盤配額 1 啟用磁盤配額 首先創建新的分區 /dev/sd5,并創建文件系統。 [root@local ~]# mkfs.ext4 /dev/sda5 由于xfs 不磁盤配額能成功,這里使用ext4. 然后把/dev/sda5分區掛載到 /home [root@local ~]# mount /dev/sda5 /home [root@local ~]# …

    Linux干貨 2017-05-02
  • DNS and BIND 進階

    主DNS服務器的ip地址:192.168.1.109 主DNS服務器主機名:bogon 正向區域名:sh.com 反向區域名:1.168.192.in-addr.arpa 正向區域文件名稱:/var/named/sh.com.hosts 反向區域文件名稱:/var/named/192.168.1.rev 配置主文件/etc/named.conf過程 1、編輯…

    Linux干貨 2016-12-06
  • 網絡基本概念介紹

    Linux網絡屬性管理 網絡節點分布:廣域網、城域網、局域網 按交換方式:線路交換、報文交換、分組交換 按網絡拓撲結構:以太網,令牌環網、星型網絡、樹型網絡、總線型網絡、網狀網絡 Ethernet: CSMA/CD 載波偵探/多路訪問/沖突檢測機制 1.想發送信息的接點首先“監聽”信道,看是否有信號在傳輸。如果信道空閑,就立即發送。2.如果信道忙,則繼續監聽…

    Linux干貨 2016-07-29
  • zabbix low-level discover 監控端口

    zabbix通過調用jason格式的輸出,實現數據的收集 獲取端口的shell腳本   #!/bin/bash port_array=(`netstat -tnl|egrep -i "$1"|awk {'print $4'}|awk -F':' '{if ($NF~/^[0-9]…

    Linux干貨 2016-06-09

評論列表(1條)

  • 馬哥教育
    馬哥教育 2016-08-19 15:17

    博客作業要按時完成,壓得太多,你就越不想寫了。

欧美性久久久久