shell腳本編程入門

什么是shell腳本,其實,shell腳本就是利用shell的功能所寫的一個程序,這個程序是使用純文本文件,將一些shell的語法與命令(包含外部命令)寫在里面,搭配正則表達式、管道命令與數據流重定向等功能等這些命令的組合起來,以達到我們所想要的目的。


程序編程風格有兩種:

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

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

過程式編程有 順序執行、循環執行、選擇執行。

shel程序就是過程式式的解釋器,提供編程能力,然后解釋執行。


shell腳本編寫要注意一下事項:

1、命令的執行時由上而下、從左到右執行的。

2、命令、參數間的多個空白會被忽略。

3、如果讀取到空白符(Enter),就嘗試執行該命令。

4、如果一行內容太多可以用\[Enter]換行編寫

5、"#"作為注釋,任何加在#后面的數據將會被忽略為注釋。


創建腳本

1、第一行必須用#!/bin/bash來聲明這個腳本的shell名稱

2、第二行一下可以用#來注釋shell腳本的內容、功能、信息版本和作者和聯系方式、建立日期、歷史記錄等良好習慣。有助于將來的拍錯。 好記性不如爛筆頭!

3、建議將一些重要的環境變量設置好,如此一來,就可以直接使用外部命令,而不必寫絕對路徑。

4、然后就將主要的程序寫好輸出

可以下用下面的命令來校驗腳本

bash -n /path/to/some_script

檢測腳本中的語法錯誤

?bash -x /path/to/some_script

調試執行


bash變量

那么什么變量呢?額,簡單的說變量就是用一個簡單特定的字符來代替另一個比較復雜或者是容易變動的數據。

變量類型

變量類型的作用有

1、數據存儲格式

2、參與的運算

3、表示的數據范圍

變量的類型有:字符型、數值型。 數值型分為:整型和浮點型

變量對于編程語言來講分為強類型和弱類型

強類型:定義變量時必須指定類型、參與運算必須符合類型要求;調用未聲明變量會產生錯誤

弱類型:無須指定類型,默認均為字符型;參與運算會自動進行隱式類型轉換;變量無須事先定義可直接調用。 shell為弱類型

變量命名法則:

1、不能使程序中的保留字:例如if, for;

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

3、見名知義

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

變量與變量的內容以一個等號"="來連接

例如   first_Name=Alan

等號兩邊不能直接接空格符。若使用空格符可以用雙引號即弱引用( " )或單引號即強引用( ' )將變量結合起來

當時雙引號內的特殊符號如"$",可以保留原本的特性

var="lang is $LANG"  則echo顯示為"lang is en_US.UTF-8 

單引號內的特殊符號僅為純文本字符如

var='lang is $LANG'  則echo顯示為"lang is $LANG"

可用轉義字符"\"將特殊符號變成一般符號如($、\、空格符、!等)

根據變量的生效范圍可分為

本地變量:生效范圍為當前shell進程;對當前shell之外的其它shell進程,包括當前shell的子shell進程均無效

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

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

位置變量:$1, $2, …來表示,用于讓腳本在腳本代碼中調用通過命令行傳遞給它的參數

特殊變量:$?, $0, $*, $@, $#

本地變量賦值:name=‘value’,

?可以使用引用value:

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

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

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

變量引用:${name}, $name 也可以累加

例如:  PATH=$PATH:~/bin: 累加~/bin到原有的PATH變量中

[root@localhost bin]# echo $PATH

/bin:/sbin:/usr/bin:/usr/sbin:usr/local/bin:/usr/local/sbin:/root/bin:/root/bin:

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

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

單引號和雙引號最大不同之處在于雙引號仍然可以保有變量的內容,但單引號內僅能是一般字符,而不會有特殊符號。

顯示已定義的所有變量(包括環境變量):set

刪除變量:unset name

環境變量

變量聲明、賦值:

export name=VALUE

export也可以把本地變量轉換環境變量

declare -x name=VALUE

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

?顯示所有環境變量:

export

env

printenv

刪除:unset name

bash有許多內建的環境變量:PATH, SHELL, HOME等用大寫字母來定義環境變量。

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

readonlyname

declare -r name

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

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

$0: 命令本身

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

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

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

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

bash中的算術運算:help let

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

實現算術運算:

(1) let var=算術表達式

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

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

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

(5) declare –ivar= 數值

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

增強型賦值:

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

?let varOPERvalue

例如:let count+=3

自加3后自賦值

?自增,自減:

let var+=1

let var++

let var-=1

let var–

邏輯運算又稱布爾運算 布爾用數學方法研究邏輯問題,成功地建立了邏輯演算。他用等式表示判斷,把推理看作等式的變換。

這種變換的有效性不依賴人們對符號的解釋,只依賴于符號的組合規律 。 true作1 false作0 與運算用& 或運算用||

與運算:

1 && 1 = 1 真

1 && 0 = 0 假

0 && 1 = 0 假

0 && 0 = 0 假

或運算:

1 || 1 = 1 真

1 || 0 = 1 真

0 || 0 = 1 真

0 || 0 = 0 假

非:!

! 1 = 0

! 0 = 1

?短路運算:

短路與:

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

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

短路或:

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

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

?異或:^

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

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

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

?例如:ls /dev && echo "This is device file"

     ls /tmp/cpwd|| mkdir /tmp/cpwd

 ls /dev/abc && echo "exist" || echo "no exist"

test命令是shell環境中測試條件表達式的實用工具

-b<文件>:如果文件為一個塊特殊文件,則為真;

-c<文件>:如果文件為一個字符特殊文件,則為真;

-d<文件>:如果文件為一個目錄,則為真;(常用)

-e<文件>:如果文件存在,則為真;(常用)

-f<文件>:如果文件為一個普通文件,則為真;(常用)

-g<文件>:如果設置了文件的SGID位,則為真;

-G<文件>:如果文件存在且歸該組所有,則為真;

-k<文件>:如果設置了文件的粘著位,則為真;

-O<文件>:如果文件存在并且歸該用戶所有,則為真;

-p<文件>:如果文件為一個命名管道,則為真;

-r<文件>:如果文件可讀,則為真;

-s<文件>:如果文件的長度不為零,則為真;

-S<文件>:如果文件為一個套接字特殊文件,則為真;

-u<文件>:如果設置了文件的SUID位,則為真;

-w<文件>:如果文件可寫,則為真;

-x<文件>:如果文件可執行,則為真。

兩種文件之間的比較 如 test file1 -nt file2

-nt file1 -nt file2 判斷file1是否比file2新(newer than)

-ot file1 -ot file2 判斷file1是否比file2舊(older than)

-er file1 -er file2 判斷file1和file2為同一文件 (inode相同的文件)

兩個整數之間的判斷,例如 test file -eq file1

-eq 兩數值相等(equal)

-ne 兩數值不相等(not equal)

-gt file1大于file2(greater than)

-lt file1小于fiel2(less than)

-ge file1大于等于file2(greater than or equal)

-le file1小于等于file2(less than or equal)

判斷字符串的數據

字符串測試:

==:是否等于;

>: ascii碼是否大于ascii碼

<: 是否小于

!=: 是否不等于

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

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

test -z string  判斷字符串是否為0,若string為空字符串,則為真

test -n string  判斷字符串是否為非0,若string為空字符串,則為假

組合測試條件

?第一種方式:

COMMAND1 && COMMAND2 并且

COMMAND1 || COMMAND2 或者

! COMMAND 非

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

?第二種方式:

EXPRESSION1 -a EXPRESSION2 并且

EXPRESSION1 -o EXPRESSION2 或者

! EXPRESSION

必須使用測試命令進行;

[ -z “$HOSTNAME” -o $HOSTNAME "=="localhost.localdomain" ] && hsotname.alan

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

read命令從鍵盤讀取變量的值,通常用在shell腳本中與用戶進行交互的場合。該命令可以一次讀取多個變量的值,變量和輸入的值都需要使用空格隔開。在read命令后面,如果沒有指定變量名,讀取的數據將被自動賦值給特定的變量REPLY

-p:指定讀取值時的提示符;
-t:指定讀取值時等待的時間(秒)。

read -p “Enter a filename:“ FILE

作業

1、編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,包括主機名,IPv4地址,操作系統版本,內核版本,CPU型號,內存大小,硬盤大小。

[root@localhost work]# cat systeminfo.sh 
#!/bin/bash
#
#編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,
包括主機名,IPv4地址,操作系統版本,內核版本,CPU型號,內存大小,硬盤大小。
I_p=$(ifconfig|grep -A 1 '^e.*[^[:space:]]\+'|tr -s ' '|cut -d' ' -f3|tr -sc [[:digit:].] ' ')
C_pu=$(lscpu|grep 'Model name'|tr -s ' '|cut -d' ' -f3-)
M_em=$(grep 'MemTotal' /proc/meminfo)
H_ard=$(fdisk -l|grep '/dev/sda\>'|tr -s ' '|cut -d' ' -f3-4)
echo -e  "hostname:\033[31m ${hostname} \033[0m"
echo -e  "ipaddress is:\033[31m${I_p} \033[0m"
echo -e "OS is:\033[31m$(cat /etc/redhat-release)\033[0m"
echo -e "kernet is:\033[31m$(uname -r)\033[0m"
echo -e "CPU tpye is:\033[31m${C_pu}\033[0m"
echo -e "Mem size is\033[31m${M_em}\033[0m"
echo -e "hardwqre size is:\033[31m${H_ard}\033[0m"
[root@localhost work]# ./systeminfo.sh 
hostname:  
ipaddress is: 10.1.36.6 192.168.200.6  
OS is:CentOS release 6.8 (Final)
kernet is:2.6.32-642.el6.x86_64
CPU tpye is:Intel(R) Celeron(R) CPU N2940 @ 1.83GHz
Mem size isMemTotal:        1906276 kB
hardwqre size is:214.7 GB

2、編寫腳本/root/bin/backup.sh,可實現每日將/etc/目錄備份到/root/etcYYYY-mm-dd中

#!/bin/bash
#編寫腳本/root/bin/backup.sh,可實現每日將/etc/目錄備份到/root/etcYYYY-mm-dd中
back_up=$(cp -r /etc /root/etc`date +%F`)
echo -e "backup /etc directory:\033[31m${back_up}\033[0m"
[root@localhost work]# ./backup.sh #腳本執行
backup /etc directory:
[root@localhost work]# ll -d /etc/ /root/etc2016-08-14 #查看備份是否成功
drwxr-xr-x. 102 root root 12288 Aug 16 13:33 /etc/
drwxr-xr-x  102 root root 12288 Aug 14 19:36 /root/etc2016-08-14

3、編寫腳本/root/bin/disk.sh,顯示當前硬盤分區中空間利用率最大的值

[root@localhost work]# cat disk.sh 
#!/bin/bash
#
#編寫腳本/root/bin/disk.sh,顯示當前硬盤分區中空間利用率最大的值
disk_d=$(df |tr -s ' '|cut -d" " -f5|tr -d "%"|sort -n|tail -1)
echo "disk:${disk_d}"
[root@localhost work]# ./disk.sh #腳本執行
disk:22

4、編寫腳本/root/bin/links.sh,顯示正連接本主機的每個遠程主機的IPv4地址和連接數,并按連接數從大到小排序

[root@localhost work]# cat link.sh 
#!/bin/bash
#編寫腳本/root/bin/links.sh,顯示正連接本主機的每個遠程主機的IPv4地址和連接數,并按連接數從大到小排序
L_ink=$(netstat -nt|tr -s ":" ' '|cut -d" " -f4|grep '[[:digit:].]'|sort -nr|uniq -c)
echo "ipddress is:${L_ink}"
[root@localhost work]# ./link.sh #腳本執行
ipddress is:      2 192.168.200.6

5、寫一個腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第20用戶的ID之和

[root@localhost work]# cat sumid.sh 
#!/bin/bash
#寫一個腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第20用戶的ID之和
u_id1=$(head -10 /etc/passwd|tail -1|cut -d: -f3)
u_id2=$(head -20 /etc/passwd|tail -1|cut -d: -f3)
let sum=$u_id1+$u_id2
echo "$sum"
[root@localhost work]# ./sumid.sh #腳本執行結果
42

6、寫一個腳本/root/bin/sumspace.sh,傳遞兩個文件路徑作為參數給腳本,計算這兩個文件中所有空白行之和

[root@localhost work]# cat sumspace.sh 
#!/bin/bash
#寫一個腳本/root/bin/sumspace.sh,傳遞兩個文件路徑作為參數給腳本,計算這兩個文件中所有空白行之和
space1=$(grep "^[[:space:]]*$" $1 |wc -l) 
space2=$(grep "^[[:space:]]*$" $2 |wc -l)
let space=$space1+$space2
echo "$space"
[root@localhost work]# ./sumspace.sh /etc/fstab /etc/rc.d/init.d/functions#執行腳本
107

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

[root@localhost work]# cat sumfile.sh 
#!/bin/bash
#寫一個腳本/root/bin/sumfile.sh,統計/etc, /var, /usr目錄中共有多少個一級子目錄和文件
one=`ls -A /etc|wc -l`
two=`ls -A /var|wc -l`
three=`ls -A /usr|wc -l`
let all=$one+$two+$three
echo "all line is$all"
[root@localhost work]# ./sumfile.sh #腳本執行
all line is264

7、寫一個腳本/root/bin/argsnum.sh,接受一個文件路徑作為參數;如果參數個數小于1,則提示用戶“至少應該給一個參數”,并立即退出;如果參數個數不小于1,則顯示第一個參數所指向的文件中的空白行數

[root@localhost work]# cat argsnum.sh 
#!/bin/bash
#寫一個腳本/root/bin/argsnum.sh,接受一個文件路徑作為參數;如果參數個數小于1,
#則提示用戶“至少應該給一個參數”,并立即退出;如果參數個數不小于1,
#則顯示第一個參數所指向的文件中的空白行數
rgum=`[ $# -le 1 ] && echo "At least one  path" && exit 0 || grep '^[[:space:]]*$' $1 |wc -l`
echo "$rgum"
[root@localhost work]# sh argsnum.sh /etc/fstab #一個參數
At least one  path
[root@localhost work]# sh argsnum.sh /etc/fstab /etc/passwd #2個參數
1

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

(0)
ladsdmladsdm
上一篇 2016-08-18 10:10
下一篇 2016-08-18 10:10

相關推薦

  • 邏輯卷實例

    1、創建一個至少有兩個PV組成的大小為20G的名為testvg的VG;要求PE大小為16MB, 而后在卷組中創建大小為5G的邏輯卷testlv;掛載至/users目錄 2、新建用戶archlinux,要求其家目錄為/users/archlinux,而后su切換至archlinux用戶,復制/etc/pam.d目錄至自己的家目錄 3、擴展testlv至7G,要…

    Linux干貨 2016-09-01
  • 計算機及Linux系統基礎簡介

    一、計算機的組成及其功能 計算機由運算器,控制器,存儲器,輸入裝置和輸出裝置五大部件組成計算機,每一部件分別按要求執行特定的基本功能。 運算器或稱算術邏輯單元(Arithmetical and Logical Unit) 運算器的主要功能是對數據進行各種運算。這些運算除了常規的加、減、乘、除等基本的算術運算之外,還包括能進行“邏輯判斷”的邏輯處理能力,即“與…

    Linux干貨 2017-07-02
  • 網絡25期學習宣言

    馬哥Linux運維學院 學習宣言 親愛的小伙伴:        歡迎大家報名馬哥Linux運維網絡學習班,跟隨馬哥學習Linux技術,成就Linux大牛之夢。在這里,我們不僅可以學習到最優秀的技術課程,還可以跟著追夢的小伙伴們一起學習、一起進步。 為了督促大家一直積極認真努力的學習,請各位同學在評論區寫出你的學習宣言?!?/p>

    Linux干貨 2016-11-14
  • rsyslog同步history日志

    前言   由于公司業務是由公司內部開人員及外包團隊共同開發,所以需要使用rsyslog對history日志做收集、審計。雖然搭建及配置非常簡單,但是在日常運維工作中很實用,所以記錄下,方便日后快速搭建。如果有錯誤,望大神指正。 syslog簡介 syslog是Linux系統默認的日志守護進程。默認的syslog配置文件是/etc/sysl…

    Linux干貨 2015-04-03
  • Linux進程及作業管理

    process 運行中的程序的一個副本,是被載入內存的一個指令集合 進程ID(Process ID,PID)號碼被用來標記各個進程 UID、GID、和SELinux語境決定對文件系統的存取和訪問權限, 通常從執行進程的用戶來繼承 存在生命周期 task struct:Linux內核存儲進程信息的數據結構格式 task list:…

    Linux干貨 2016-09-11
  • Linux磁盤管理詳解

    linux磁盤管理 添加磁盤步驟: fdisk 管理磁盤分區 格式化文件系統。 設備掛載 開機自動掛載 UUID掛載 取消掛載點 Parted(gpt大于2G分區) 查看文件系統的使用情況。 df 查看掛載信息與磁盤使用量 du 查看使用量 查看分區狀況lsblk 查看設備信息blkid linux磁盤管理 當全新安裝了一塊新的硬盤設備后,為了更充分、安全的…

    Linux干貨 2016-09-07
欧美性久久久久