程序:指令+數據
程序:算法+數據結構
shell腳本編程:
編程的語言分類:根據運行方式
編譯運行:源代碼——>編譯器——>程序文件
解釋運行:源代碼——>運行時啟動解釋器,由解釋器邊解釋邊執行
根據其編程過程中功能的實現是否調用庫還是調用外部的程序文件:
shell腳本編程:
利用系統上的命令及編程組件進行編程
完整編程:
利用庫或編程組件進行的編程
編程模型:
過程式:以指令為中心,數據服務于指令
對象式:以數據為中心,指令服務于數據
shell程序:提供了編程能力,解釋執行,依賴于外部程序文件運行
如何編程shell腳本:
格式要求:首行shebang機制
腳本第一行,頂格,給出shebang(解釋器刻路徑),用于指明解釋器執行當前腳本的解釋器程序文件
常見的解釋器
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
注意:腳本中除了shebang行,余下的所有以#開頭的行都會被視作注釋而忽略
注意:腳本中的空白行會被忽略
shell腳本是什么?
命令的堆積,但許多命令不具有冪等性(冪等性:能多次執行不出現錯誤),需要程序邏輯來判斷運行條件是否滿足,以避免其運行中發生錯誤
運行腳本:
給予執行權限,在命令行上指定腳本的絕對或相對路徑
chmod +x /path/to/script_file
運行:
全路徑運行:/path/to/script_file
相對路徑運行:./script_file
直接運行解釋器,將腳本作為解釋器程序的參數運行
bash /pash/to/script_file
腳本調試
bash -n /path/to/some_script
檢測腳本中的語法錯誤
bash -x /path/to/some_script
調試執行
變量:
命名的內存空間
變量賦值:name=‘value’,
指定了變量名及其所對應的物理內存空間
變量類型:存儲格式,表示數據范圍,參與的運算
編程程序語言分類:
強類型:定義變量時必須指定類型、參與運算必須符合類型要求;調用未聲明變量會產生錯誤
如 java,python
弱類型:無須指定類型,默認均為字符型;參與運算會自動進行隱式類型轉換;變量無須事先定義可直接調用
如:bash 不支持浮點數
變量替換:把變量名出現的位置替換成其所指向的內存空間中數據
變量引用:${var_name},$var_name
變量命名法則:
1、不能使程序中的保留字:例如if, for;
2、只能使用數字、字母及下劃線,且不能以數字開頭
3、見名知義
4、統一命名規則:駝峰命名法
bash變量類型:
本地變量:作用域僅為當前shell
環境變量:作用域為當前shell及其子進程
局部變量:作用域為某代碼片段
位置參數變量:向執行腳本的sell進程傳遞的參數,$1, $2, … 來表示
特殊變量:shell內置的特殊功能的變量,$?, $0, $*, $@, $#
本地變量:
變量賦值:name=‘value’, ,
可以使用引用value:
(1) 可以是直接字串; name=“root"
(2) 變量引用:name="$USER"
(3) 命令引用:name=` COMMAND `, name =$(COMMAND)
變量引用:${name}, $name
"" :弱引用,其中的變量引用會被替換為變量值
'' :強引用,其中的變量引用不會被替換為變量值,而保持原字符串
顯示已定義的所有變量:set
刪除變量:unset name
環境變量:
變量聲明、賦值:
(1)export name=VALUE
(2)name=VALUE ;export name
(3)declare -x name=VALUE
(4)name=VALUE :declare -x name
變量引用:$name, ${name}
顯示所有環境變量:
export
env
declare -x
printenv
刪除:unset name
bash 有許多內建的環境變量:PATH, SHELL, USRE,UID,HISTSIZE, HOME, PWD, OLDPWD, HISTFILE, PS1
只讀變量:
只讀變量:只能聲時,但不能修改和刪除,存活在當前shell中,隨shell的中止而中止
readonly name
declare -r name
位置參數變量:
$1, $2, … :對應第1 、第2等參數
在腳本中使用:shift [n] 表示以此置換出多少個位置參數變量
比如:shift 1 ,表示把$!置換出去,則老的$2變成新的$1,老的$3變成新的$2,以此類推
shift 2 ,表示以此置換出去2個位置參數
特殊變量:
$0:命令本身
$#:傳遞給腳本的參數的個數
$*:傳遞給腳本的所有參數,全部參數合為一個字符串
$@:傳遞給腳本的所有參數,每個參數為獨立字符串
$@ $* 只在被雙引號包起來的時候才會有差異
算術運算:
bash中的算術運算:help let
+, -, *, /, % 取模(取余), ** (乘方)
注意:右手乘法*需要轉義使用
實現算術運算:
(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之間隨機數
增強型賦值:
+=, -=, *=, /=, %=
例如:let count+=3
自加3后自賦值
自增:
let var+=1
let var++
自減:
let var-=1
let var–
寫一個腳本/root/bin/sumid.sh ,計算/etc/passwd文件中的第10個用戶和第20用戶的ID之和
#!/bin/bash #description #version 0.1 #author gm #date 20160810 id_1=`sed -n '10p' /etc/passwd | cut -d: -f3` id_2=`sed -n '20p' /etc/passwd | cut -d: -f3` let sum_id=$id_1+$id_2 echo "user10 sum user20 = $sum_id"
[root@CentOS6 bin]# sumid.sh user10 sum user20 = 180
寫一個腳本/root/bin/sumspace.sh,傳遞兩個文件路徑作為參數給腳本,計算這兩個文件中所有空白行之和
#!/bin/bash #description #version 0.1 #author gm #date 20160810 spaceline1=`grep "^[[:space:]]*$" $1 | wc -l | cut -d' ' -f2` spaceline2=`grep "^[[:space:]]*$" $2 | wc -l | cut -d' ' -f2` let sumspaceline=$spaceline1+$spaceline2 echo "space lines is : $sumspaceline"
[root@CentOS6 bin]# sumspace.sh /etc/fstab /etc/rc.d/init.d/functions space lines is : 107
寫一個腳本/root/bin/sumfile.sh, 統計/etc, /var,/usr
#!/bin/bash #description #version 0.1 #author gm #date 20160810 file_etc=`ls -l /etc | wc -l` file_var=`ls -l /var | wc -l` file_usr=`ls -l /usr | wc -l` file_sum=$[file_etc+file_var+file_usr] echo "etc var usr sum file is : $file_sum"
[root@CentOS6 bin]# sumfile.sh etc var usr sum file is : 311
邏輯運算:
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
異或:^
異或的兩個值, 相同為假,不同為真
1^1=0
1^0=1
0^1=0
0^0=0
短路運算:
短路與:COMMAND1 && COMMAND2
第一個為0,結果必定為0;
第一個為1,第二個必須要參與運算;
短路或:COMMAND1 || COMMAND2
第一個為1,結果必定為1; ;
第一個為0,第二個必須要參與運算;
退出狀態碼:
進程使用退出狀態來報告成功或失敗
0 代表成功,1 -255 代表失敗
$?:保存最近一次命令的返回碼
bash 自定義退出狀態碼
exit [n] :自定義退出狀態碼;
注意:腳本中一旦遇到exit命令,腳本會立即終止;退出狀態碼取決于exit命令后面的數字
注意:如果未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決于腳本中執行的最后一條命令的狀態碼
條件測試:
判斷某需求是否滿足,需要由測試機制來實現;
專用的測試表達式需要由測試命令輔助完成測試過程;
評估布爾聲明,以便用在條件性執行中
若真,則返回0
若假,則返回1
如何編寫測試表達式以實習所需的測試:
(1)執行命令。并利用命令狀態返回值來判斷:
0:成功
1~255:失敗
(2)測試表達式:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
注意:EXPRESSION前后必須有空白字符
注意:當EXPRESSION中有>,<或者=~符號時,請使用[[ EXPRESSION ]],否則會報錯
bash的測試類型:
數值測試:(數值比較)
-gt:是否大于
-ge:是否大于等于
-eq:是否等于
-ne:是否不等于
-lt:是否小于
-le:是否小于等于
字符串測試:
==:是否等于;
>:左邊字符的ascii碼是否大于右邊字符的ascii碼
<:是否小于
!=:是否不等于
=~:左側字符串是否能夠被右側的PATTERN所匹配
注意:此表達式一般用于[[ ]]中;
-z "STRING" :字符串是否為空,空為真,不空為假
-n "STRING" :字符串是否不空,不空為真,空為假
注意:用于字符串比較時的用到的操作數都應該使用引號
寫一個腳本/root/bin/argsnum.sh ,接受一個文件路徑作為參數;如果參數個數小于1 ,則提示用戶“至少應該給一個參數”,并立即退出;如果參數個數不小于1 ,則顯示第一個參數所指向的文件中的空白行數
#!/bin/bash #description file space lines #version 0.1 #author gm #date 20160810 [ $# -lt 1 ] && echo "please give one argments or more " || echo " `basename $1` space lines is :`grep -c '^[[:space:]]*$' $1 `"
[root@CentOS6 bin]# argsnum.sh please give one argments or more [root@CentOS6 bin]# argsnum.sh /etc/fstab fstab space lines is :1
寫一個腳本/root/bin/hostping.sh ,接受一個主機的IPv4 地址做為參數,測試是否可連通。如果能ping 通,則提示用戶“該IP 地址可訪問” ;如果不可ping 通,則提示用戶“該IP地址不可訪問”
#!/bin/bash #description ping ip address #version 0.1 #author gm #date 20160810 ping $1 -c1 -W1 &> /dev/null && echo "$1 is up" || echo "$1 is down"
[root@CentOS6 bin]# hostping.sh 10.1.0.1 10.1.0.1 is up
文件測試:
1、存在性測試:
-a FILE:同-e
-e FILE:文件存在性測試,存在為真,否則為假
2、存在性及類別測試:
-b FILE:是否存在且為塊設備文件
-c FILE:是否存在且為字符設備文件
-d FILE:是否存在且為目錄文件
-f FILE:是否存在且為普通文件
-h FILE 或 -L FILE:存在且為符號鏈接文件
-p FILE:是否存在且為命名管道文件
-S FILE:是否存在且為套接字文件
3、文件權限測試:
-r FILE:是否存在且當前用戶可讀
-w FILE:是否存在且當前用戶可寫
-x FILE:是否存在且當前用戶可執行
4、文件特殊權限測試:
-g FILE:是否存在且擁有sgid權限
-u FILE:是否存在且擁有suid權限
-k FILE:是否存在且擁有sticky權限
5、文件大小測試:
-s FILE: 是否存在且非空
6、時間戳:
-N FILE:文件自動上一次被讀取之后是否被修改過
7、從屬關系測試:
-O FILE:當前用戶是否為文件屬主
-G FILE:當前用戶是否為文件屬組
8、雙目測試:
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
如:[ -e FILE -a -r FILE ]
練習:
1、chmod -rw /tmp/file1 ,編寫腳本/root/bin/per.sh,判斷當前用戶對/tmp/fiile1件文件是否不可讀且不可寫
#!/bin/bash #description #version 0.1 #author gm #date 20160810 [ ! -r /tmp/file1 -a ! -w /tmp/file1 ] && echo "`whoami` is rw /tmp/file1" || echo "`whoami` is not w or rw /tmp/file1"
2、編寫腳本/root/bin/nologin.sh 和login.sh, 實現禁止和充許普通用戶登錄系統
/root/bin/nologin.sh
#!/bin/bash #description #version 0.1 #author gm #date 20160810 [ -e /etc/nologin ] || mkdir /etc/nologin &> /dev/null && echo "/etc/nologin is exist"
[root@CentOS6 bin]# nologin.sh /etc/nologin is exist
/root/bin/login.sh
#!/bin/bash #description #version 0.1 #author gm #date 20160810 [ -e /etc/nologin ] && rm -rf /etc/nologin && echo "delete /etc/nologin."
[root@CentOS6 bin]# login.sh delete /etc/nologin.
read:
read從標準輸入中讀取值,給每個單詞分配一個變量,所有剩余單詞都被分配給最后一個變量
-p :指定要顯示的提示
-t TIMEOUT:指定用戶不輸入數據的最長時間
例如:read -p “Enter a filename: “ FILE
原創文章,作者:megedugao,如若轉載,請注明出處:http://www.www58058.com/37058