概述:
shell指令碼在Linux系統管理員的運維工作中非常重要。shell指令碼能夠幫助我們很方便的管理伺服器,因為我們可以指定一個任務計劃,定時的去執行某一個指令碼以滿足我們的需求。本篇將從程式設計基礎、指令碼基本格式、變數、運算、條件測試這幾個方面詳細介紹shell指令碼程式設計的基礎內容,也是我們必須要掌握熟練的內容。
程式語言:事先定義了一組規範,通過關鍵字按照特定的語法結構編寫出來的程式,通過編譯器或直譯器轉換成彙編程式
程式執行邏輯:順序執行,至上而下;選擇執行(條件判斷);迴圈執行
動態語言:解釋型語言,變數隨時申明隨時分配記憶體空間,不能合理分配記憶體空間(perl、bash、python)
靜態語言:編譯型語言,所有的變數在程式執行之前都要分配好記憶體空間,變數必須手動釋放,合理分配記憶體空間
Shell指令碼
shell程式設計:程式式程式設計,解釋執行,依賴於外部程式檔案執行;是一個過程式的直譯器,提供了程式設計能力,然後解釋執行。
程式語言的基本結構:
資料儲存:變數、陣列
表示式:a + b、a=1
語句:if語句
常見直譯器:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
shell指令碼的用途有:
自動化常用命令
執行系統管理和故障排除
建立簡單的應用程式
處理文字或檔案
shell指令碼除錯:
檢測指令碼中的語法錯誤
bash -n /path/to/some_script
除錯執行(單步執行)
bash -x /path/to/some_script
shell指令碼的執行方式:
1、相對路徑執行(需要執行許可權):./some_script
2、絕對路徑執行(需要執行許可權):/path/to/some_script
3、命令列執行(不需要執行許可權):bash /path/to/some_script
4、.執行(不需要執行許可權):. /path/to/some_script
5、source命令執行(不需要執行許可權):source /tmp/scriptname
總結:方法3、4、5不需要執行許可權是因為指令碼是作為命令的引數去執行的。前3種方法執行shell指令碼時都是在當前shell下(稱為父shell)開啟一個子shell環境,此shell指令碼就在這個子shell環境中執行;shell指令碼執行完後子shell環境隨即關閉,然後又回到父shell中(因為執行完後子shell已退出,shell指令碼中得變數也會被釋放掉)。第4、5種則是在當前shell中執行(指令碼中的變數不會被釋放)
bash指令碼中的變數
變數:
資料儲存格式:ASCII(一個字元佔用8bit)、Binary(二進位制)
按照其變數是否需要嚴格定義其型別來劃分
強型別語言:事先需要定義變數儲存型別的如C
弱型別語言:無需定義變數儲存型別,bash預設所有變數都認為字元儲存格式
定義變數型別的作用:資料儲存格式、資料的有限儲存範圍、比較機制不同、參與的運算型別不同
變數型別:分為兩大類字元型和數值型
字元型:
數值型:正 負
精確數值型:整數
近似數值型:
浮點數:
單精度:
雙精度:
布林型:真與假
bash變數的型別:
本地變數:作用域為整個bash程式,只對當前shell程式有效,對其子shell以及其他shell都無效
定義變數 set Var_Name=”Value”
區域性變數:作用域為當前程式碼段,只對某一部分有效(在函式中會用到)
定義變數 local Var_Name=”Value”
位置變數:通過位置變數引用指令碼名稱和指令碼執行後面指定的引數$0……$n
$0 表示指令碼名稱
$1 表示執行指令碼後面指定的第一個引數,$2指定的第二個引數;後面依次類推
位置引數輪替shift
在指令碼給定的位置引數不確定,指令碼求給定數字的和,但是給定的數字個數不確定;這個時候用到shift位置輪替,位置輪替的意思類似$1剔除,原來的$2變為$1,迴圈一次剔除一次,如果後面跟數值就是剔除幾個位置變數預設不加數值就是剔除一個
#!/bin/bash
sum=0
for i in `seq 1 $#`;do
let sum+=$1
shift
done
echo $sum
特殊變數:
$? 上一條命令的執行狀態碼,狀態碼用0-255數字表示;0表示執行成功,1-255表示失敗;1、2、127、255預留
$# 傳入指令碼的引數的個數
$* 傳給指令碼的所有引數(所有引數作為一個字串)
$@ 傳給指令碼的所有引數是列表方式(每個引數都作為獨立的字串)
$$ 當前shell程式的PID
$! 後臺執行的最後一個作業的PID
$- 顯示shell當前使用的選項(通過set命令開啟和關閉的shell選項)
$_ 上一條命令的最後一個引數
注意:$*和 $@都表示傳遞給函式或指令碼的所有引數,不被雙引號(” “)包含時,都以”$1” “$2” … “$n” 的形式輸出所有引數。但是當它們被雙引號(” “)包含時,”$*” 會將所有的引數作為一個整體,以”$1 $2 … $n”的形式輸出所有引數;”$@” 會將各個引數分開,以”$1″ “$2” … “$n” 的形式輸出所有引數
環境變數:作用域為當前shell程式及其子shell有效(反過來子shell定義的環境變數對父shell沒效)
定義變數 export Var_Name=”Value”
或下面方式先定義本地變數在通過export匯出為環境變數
Var_Name=”Value”
export Var_Name
bash的內建環境變數:用來定義bash的工作特性,用於儲存當前會話的屬性資訊
$PATH 命令的搜尋路徑
$HOSTNAME 顯示主機名
$HISTFILE 設定命令歷史檔案的路徑檔名
$HISTSIZE 定義了history命令能記錄命令最大數
$HISTFILESIZE 設定命令歷史檔案儲存命令的最大數
$HISTCONTROL 控制命令是否存入命令歷史檔案中
$BASH bash二進位制程式檔案的路徑
$BASH_SUBSHELL 子shell的層次
$BASH_VERSION bash程式的版本
$EDITOR 系統預設編輯器
$EUID 有效的使用者ID(執行程式的實際使用者ID)
$UID 當前使用者的ID號
$FUNCNAME 當前函式的名稱
$GROUPS 當前使用者所屬的組
$HOME 當前使用者的家目錄
$HOSTTYPE 主機型別,用來識別系統硬體平臺
$MACHTYPE 平臺型別(硬體平臺-釋出版本-OS型別)
$OSTYPE OS型別
$OLDPWD 上一次的工作目錄
$PWD 當前工作目錄
$IFS 輸入資料時欄位分隔符,預設為空白符(空格、製表符、換行符)
$PPID 父程式的程式號
$PS1 登陸主提示符
$PS2 第二提示符,補充完全命令輸入時的提示符(預設為>)
$PS3 第三提示符,用於select命令中
$PS4 第四提示符,當使用-x選項呼叫指令碼時,顯示的提示符,預設為+號
$SECONDS 當前指令碼已經執行的時長
$SHLVL shell級別,bash被嵌入的深度
引用變數 ${Var_Name}
撤銷變數 unset Var_Name
變數的命名要求:只能使用數字、字母和下劃線組成;不能以數字開頭;不能使用程式中的關鍵字;見名知義
set 不帶任何引數顯示當前系統的所有變數
export 不帶任何引數顯示所有環境的變數(env、printenv)
declare 定義變數型別
-i 宣告整形變數
-x 宣告環境變數,類似於export
-a 宣告陣列
-f 宣告函式
-r 宣告只讀變數,相當於readonly(不能撤銷變數及修改變數的值),shell程式終止才會消失
name=king ; readonly name或者declare -r name=king都表示宣告只讀變數
bash配置檔案
bash的配置檔案只會登入的時候讀取一次,如果手動修改了bash的配置檔案可以通過重新登入讓配置生效,或者通過source或.重讀bash的配置檔案其實就是通過source或.重新執行了配置檔案
例子:source ~/.bashrc 或者 . ~/.bashrc
shell型別:
登入式shell:
通過終端輸入使用者資訊登陸系統
su – UserName或su -l UserName或su –login UserName
非登入shell:
su UseName
圖形介面下開啟的終端
執行指令碼(執行指令碼前會先讀取bash的配置檔案)
bash配置檔案詳解:
profile類:登入式shell提供配置
profile類功能:設定環境變數、執行命令或者指令碼
/etc/profile 全域性
/etc/profile.d/*.sh 全域性
~/.bash_profile 個人配置,僅對當前使用者有效
登入式shell讀取配置檔案順序
/etc/profile—>/etc/profile.d/*.sh—>~/.bash_profile—>~/.bashrc—>/etc/bashrc—>~/.bash_logout
bashrc類:非登入式shell提供配置
bashrc類功能:設定本地變數、定義命令別名
/etc/bashrc 全域性
~/.bashrc 個人配置
非登入讀取配置檔案順序
~/.bashrc—>/etc/bashrc—>/etc/profile.d/*.sh—>~/.bash_logout
bash算術運算
let varName=算術表示式
varName=$[算術表示式]
varName=$((算術表示式))
varName=`expr 變數1 + 變數2 `
除法運算有餘數被省略(圓整)
操作符:+、-、*、/、%(餘數)
num=10
let num+=2或num=$[$num+2] 將變數num加2後的值再存回變數num
+=、-=、*=、/=、%= 這些符號和前面的例子同理
let varName++、varName– 先引用變數在運算(+1或-1存回變數自身)
let ++varName、–varName 每次先+1或-1存回變數自身,先運算在引用
bash中有內建的隨機數生成器
$RANDOM 生成0-32767之間的隨機數
示例:echo $[$RANDOM%50] :0-49之間隨機數(取餘數肯定小於50)
bash邏輯運算
與運算:
真 && 真 = 真(0)
真 && 假 = 假
假 && 真 = 假
假 && 假 = 假
或運算:
真 || 真 = 真(0)
真 || 假 = 真
假 || 真 = 真
假 || 假 = 假
非運算:
!真 = 假
!假 = 真
邏輯與:&&(兩個條件都為真的時候才為真,任何一個為假就為假)
第一個條件為假時,第二條件不用再判斷,最終結果已經為假所以第二條件不執行
第一個條件為真時,第二條件必須判斷;只有第二條件執行才能得最終結果
邏輯或:||(兩個條件其中任何一個為真就為真,同時為假才為假)
第一個條件為假時,第二條件必須判斷,只有第二條件執行才能得最終結果
第一個條件為真時,第二條件不用再判斷,最終結果已經為真所以第二條件不執行
&& 命令1&&命令2 當命令1正確執行,命令2才會執行
當命令1執行不正確,命令2不會執行
|| 命令1||命令2 當命令1執行不正確時,命令2才會執行
當命令1正確執行,命令2不會執行
例子:判斷某條命令是否執行成功,執行成功列印yes,執行錯誤列印no(&&的優先順序大於||,所以先執行左邊的判斷)
command && echo yes || echo no
如果命令執行成功,就執行echo yes;前面邏輯與結果為真,所以後面的echo no就不會執行
如果命令執行不成功,就不會執行echo yes;前面邏輯與結果為假,所以後面的echo no就會執行
如果使用者user6不存在,就新增使用者user6
! id user6 && useradd user6
id user6 || useradd user6
如果/etc/inittab檔案的行數大於100,就顯示好大的檔案;
[ `wc -l /etc/inittab | cut -d` ` -f1` -gt 100 ] && echo “Large file.”