Linux Shell指令碼程式設計-基礎1

luck-luck發表於2018-10-26

概述:
  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.”

相關文章