shell俗稱殼(用來區別于核),提供使用者使用界面(命令解析器),它接受用戶命令,然后調用相應的應用程序。
同時它還是一種程序設計語言,作為命令語言,它交互式解釋和執行用戶輸入的命令或者自動地解釋和執行預先設計好的一連串的命令。作為程序涉及語言,它定義了各種變量和參數,并提供了許多在高級語言中才具有的控制結構,包括循環和分支。
一、shell腳本基礎概念
shell的編程風格是過程式,即以指令為中心,數據服務指令。
shell程序提供了編程能力,解釋執行。
shell編程語言的基本結構
數據存儲:變量、數組
表達式:a+b
語句:if
shell編程邏輯處理方式
順序執行
循環執行
選擇執行
shell腳本是包含一些命令或聲明,并符合一定格式的文本文件
格式要求:首行shebang機制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
shell腳本的用途
自動化常用命令
執行系統管理和故障排除
創建簡單的應用程序
處理文本或文件
創建shell腳本
第一步:使用文本編輯器來創建文本文件
第一行必須包括shell聲明序列:#!
#!/bin/bash
添加注釋
注釋以#開頭
第二步:運行腳本
給予執行權限,chmod +x file.sh 在命令行上指定腳本的絕對或相對路徑
直接運行解釋器,將腳本作為解釋器程序的參數運行
腳本調試
bash -n /wang/jiaoben.sh
檢查腳本中的語法錯誤
bash -x /wang/jiaoben.sh
調試執行
[root@localhost wang]# bash -x jiaoben1.sh + wang=100 + echo 100 100 ++ 200 jiaoben1.sh: line 5: 200: command not found + laowang= + echo '' 注:一邊執行,一邊檢查語法:jiaoben1.sh第五行 200這個命令找不到
二、變量
命名的內存空間
數據存儲方式
字符:
數值:整型,浮點型
變量類型
作用
數據存儲格式
參與的運算
表示的數據范圍
類型
字符
數值:整型,浮點型
強類型:定義變量時必須指定類型,參與運算必須符合類型要求,調用未聲明變量會產生錯誤
例:java,python
弱類型:無須指定類型,默認均為字符型,參與運算會自動進行隱式類型轉換,變量無須事先定義可直接調用
例:bash 不支持浮點數
變量命名法則:
不能使用程序中的保留字,例:if,for
只能使用數字、字母及下劃線,且不能以數字開頭
見明知億
統一命名規則:駝峰命名發,例:大駝峰SumFile,小駝峰sumFile
bash中變量的種類
根據變量的生效范圍等標準
本地變量:生效范圍為當前shell進程,對當前shell之外的其它shell進程,包括當前shell的子shell進程均無效。
環境變量:生效范圍為當前shell進程及其子進程
局部變量:生效范圍為當前shell進程中某代碼片段(通常指函數)
位置變量:$1,$2…來表示,用于讓腳本在腳本代碼中調用通過命令行傳遞給它的參數
特殊變量:$?,$0,$*,$@,$#
本地變量
變量賦值:name=‘函數(value)’
可以使用引用value:
可以是直接字符串:name=“root”
變量引用:name=“$USER”
命令引用:name=`command`或name=$(command)
變量引用:${name},$name
"":弱引用,其中的變量引用會被替換為變量值
'':強引用,其中的變量引用不會被替換為變量值,而保持原字符串
顯示已定義的所有變量:set
刪除變量:unset name
本地變量不可給子shell進程使用。
[root@localhost wang]# cat jiaoben1.sh #!/bin/bash wang=100 echo $wang [root@localhost wang]# bash jiaoben1.sh 100 [root@localhost wang]# echo $wang [root@localhost wang]#
環境變量
變量聲明、賦值
export name=value
declare -x name=value
變量引用:${name},$name
顯示所有環境變量
export
env
printenv
刪除環境變量
unset name
環境變量可以在當前shell生效,exit退出就不會生效,可以給子進程使用
bash有許多內建的環境變量:PATH,SHELL,USER,UID,HISTSIZE,HOME,PWD,OLDPWD,HOSTFILE,PS1
[root@localhost wang]# export wang=100 [root@localhost wang]# cat jiaoben1.sh #!/bin/bash echo $wang [root@localhost wang]# bash jiaoben1.sh 100
只讀變量
只能聲時,但不能修改和刪除
readonly name
declare -r name
定義之后永久保存在緩存中,exit退出即可取消定義
[root@localhost wang]# readonly wang=1 [root@localhost wang]# echo $wang 1 [root@localhost wang]# wang=2 -bash: wang: readonly variable [root@localhost wang]# wang=1 -bash: wang: readonly variable
位置變量
在腳本代碼中調用通過命令行傳遞給腳本的參數
$1,$2…:對應第1,第2等參數,shift[n]換位置
$0:命令本身
$*:傳遞給腳本的所有參數,全部參數合為一個字符串
$@:傳遞給腳本的所有參數,每個參數為獨立字符串
$#:傳遞給腳本的參數的個數
$@,$*只在被雙引號包起來的時候才會有差異
[root@localhost wang]# cat jiaoben1.sh #!/bin/bash echo "第一個參數是$1" echo "第二個參數是$2" echo "第三個參數是$3" echo "所有參數是$*" echo "所有參數是$@" echo "參數的個數是$#" [root@localhost wang]# bash jiaoben1.sh aaa bbb ccc 第一個參數是aaa 第二個參數是bbb 第三個參數是ccc 所有參數是aaa bbb ccc 所有參數是aaa bbb ccc 參數的個數是3 [root@localhost wang]# cat jiaoben1.sh #!/bin/bash maxuid=`cat $1 | cut -d: -f3 |sort -nr | head -n1` echo "$maxuid" [root@localhost wang]# bash jiaoben1.sh /etc/passwd 1000
三、算術運算
bash中的算術運算:help let
+,-,*,/,%(取余),**(乘方)
實現算術運算
let var=算術表達式
var=$[算術表達式]
var=$((算術表達式))
var=$(expr arg1 arg2 arg3…)
echo '算術表達式' |bc
declare -i var=數值
乘法符號有些場景中需要轉義。例:*
bash有內建的隨機數生成器:$RANDOM(0-32767)
[root@localhost ~]# let wang=2*3 [root@localhost ~]# echo $wang 6 [root@localhost ~]# wang=$[3*4] [root@localhost ~]# echo $wang 12 [root@localhost ~]# wang=$((1+3+4)) [root@localhost ~]# echo $wang 8 [root@localhost ~]# echo "3*(5+6)"|bc 33 [root@localhost ~]# echo $[RANDOM%10] 1 [root@localhost ~]# echo $[RANDOM%10] 6 [root@localhost ~]# echo $[RANDOM%10] 5
四、邏輯運算
true:1 false: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,第二個必須要參與運算
command1 command2
command1成功,執行command2
command1失敗,不執行command2
短路或||
第一個為1,結果必定為1
第二個為0,第二個必須要參加運算
command1 command2
command1成功,不執行command2
command1失敗,執行command2
異或:^
異或的兩個值,相同為假,不同為真
五、聚集命令
有兩種聚集命令的方法
復合式:date; who|wc -l
命令會一個接一個的運行
子shell:(date; who|ec -l)>>/tmp/trace
所有的輸出都被發送給單個輸出和輸入
[root@localhost sh.log]# date;hostname;who Thu Aug 11 19:49:53 CST 2016 localhost.localdomain root tty1 2016-08-09 17:41 root pts/0 2016-08-11 18:53 (192.168.1.106) root pts/3 2016-08-11 14:06 (192.168.1.106) [root@localhost sh.log]# date;hostname;who|wc -l Thu Aug 11 19:50:08 CST 2016 localhost.localdomain 3 [root@localhost sh.log]# (date;hostname;who)|wc -l 5 [root@localhost sh.log]# (date;hostname;who)|wc -l
六、退出狀態
進程使用退出狀態來報告成功或失敗
0 代表成功,1-255代表失敗
$?變量保存最近的命令退出狀態
[root@localhost sh.log]# ping -c1 -W1 192.168.1.1 &> /dev/null [root@localhost sh.log]# echo $? 0 [root@localhost sh.log]# ping -c1 -W1 192.168.1.256 &> /dev/null [root@localhost sh.log]# echo $? 2 [root@localhost sh.log]# useradd wang [root@localhost sh.log]# grep -q "laowang" /etc/passwd [root@localhost sh.log]# echo $? 1 [root@localhost sh.log]# grep -q "wang" /etc/passwd [root@localhost sh.log]# echo $? 0
退出狀態碼
bash自定義退出狀態碼
exit[n]:自定義退出狀態碼
注:腳本中一旦遇到exit命令,腳本會立即終止,終止退出狀態取決與exit命令后面的數字
注:如果未給腳本制定退出狀態碼,整個腳本的退出狀態碼取決于腳本中執行的最后一條命令的狀態碼
七、條件測試
判斷某需求是否滿足,需要由測試機制來實現
專用的測試表達式需要由測試命令輔助完成測試過程
評估布爾聲明,以便用在條件性執行中
若真,則返回0
若假,則返回1
測試命令
test expression
[ expression ]
[[ expression ]]
注:expression前后必須有空白字符
條件性的執行操作符
根據退出狀態而定,命令可以有條件地運行
&&代表條件性的and then
||代表條件性的or else
[root@localhost sh.log]# ping -c1 -W1 192.168.1.1 &> /dev/null && echo "能ping通" || echo “不能ping通” 能ping通 [root@localhost sh.log]# ping -c1 -W1 192.168.1.256 &> /dev/null && echo "能ping通" || echo "不能ping通" 不能ping通
bash測試類型
數值測試
-gt:是否大于
-ge:是否大于等于
-eq:是否不等于
-ne:是否小于
-le:是否小于等于
字符串測試
==:是否等于
>:ascii碼是否大于ascii碼
<:是否小于
!=:是否不等于
=~:左側字符串是否能夠被右側的pattern所匹配
注:此表達式一半用于[[]]中
-z‘string’:字符串是否為空,空為真,不空為假
-n‘string’:字符串是否不空,不空為真,空為假
注:用于字符比較時的用到的操作數都應該使用引號
[root@localhost wang]# cat jiaoben1.sh #!/bin/bash maxdisk=`df|grep "^tmpfs"|tr -s " " "%" |cut -d% -f5|sort -nr|head -n1` maxshiyonglv=80 [ $maxdisk == $maxshiyonglv ] && echo "磁盤空間要爆滿" || echo "磁盤空間沒爆滿" [root@localhost wang]# bash jiaoben1.sh 磁盤空間沒爆滿 [root@localhost wang]# cat jiaoben2.sh #!/bin/bash maxdisk=`df|grep "^tmpfs"|tr -s " " "%" |cut -d% -f5|sort -nr|head -n1` maxshiyonglv=80 [ $maxdisk -gt $maxshiyonglv ] && echo "磁盤空間要爆滿" || echo "磁盤空間沒爆滿" [root@localhost wang]# bash jiaoben2.sh 磁盤空間沒爆滿
文件測試
存在性測試
-a file:同-e
-e file:文件存在性測試,存在為真,否則為假
存在性及類別測試
-b file:是否存在且為塊設備文件
-c file:是否存在且為字符設備文件
-d file:是否存在且為目錄文件
-f file:是否存在且為普通文件
-z 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:文件自動上一次被讀取之后是否被修改過
-O file:當前有效用戶是否為文件屬主
-G file:當前有效用戶是否為文件屬組
雙目測試
file1 -ef file2:file1與file2是否指向同一個設備上的相同inode
file1 -nt file2:file1是否新于file2
file1 -ot file2:file1是否舊于file2
組合測試條件
第一種方式
command1 && aommand2 并且
command1 || aommand2 或者
!command 非
如:[ -e file ] && [ -r file ]
第二種方式
expression1 -a expression2 并且
expression1 -o rxpression2 或者
!expression
必須使用測試命令進行
[wang@www wang]$ ll total 16 ----------. 1 root root 0 Aug 11 23:36 file1 -rwxrwxrwx. 1 root root 16 Aug 11 11:21 file2 drwxr-xr-x. 2 root root 4096 Aug 11 10:11 jiaoben -rwxr-xr-x. 1 root root 111 Aug 12 00:30 jiaoben1.sh -rw-r--r--. 1 root root 110 Aug 11 23:28 jiaoben2.sh [wang@www wang]$ cat jiaoben1.sh #!/bin/bash [ -r $1 -o -x $1 ] && echo "該文件有讀或寫權限" || echo "該文件沒有讀或寫權限" [wang@www wang]$ bash jiaoben1.sh file1 該文件沒有讀或寫權限 [wang@www wang]$ bash jiaoben1.sh file2 該文件有讀或寫權限 [wang@www wang]$ cat jiaoben2.sh #!/bin/bash [ -r $1 -a -x $1 ] && echo "這個文件有讀寫權限" ||echo "這個文件沒有讀寫權限" [wang@www wang]$ bash jiaoben2.sh file1 這個文件沒有讀寫權限 [wang@www wang]$ bash jiaoben2.sh file2 這個文件有讀寫權限
使用read來輸入值分配給一個或多個shell變量
-p 指定要顯示的提示
-t timeout
read 從標準輸入中讀取值,給每個單詞分配一個變量
所有剩余單詞都被分配給最后一個變量
read -p “Enter a filename:” FILE
[root@www wang]# cat jiaoben1.sh #!/bin/bash read -p "input a number:" [root@www wang]# bash jiaoben1.sh input a number:laowang
流程控制
過程是編程語言
順序執行
選擇執行
循環執行
原創文章,作者:DYW,如若轉載,請注明出處:http://www.www58058.com/34064