1. 程式人生 > >bash shell

bash shell

Linux之路

編程基礎

程序:指令+數據
程序編程風格:
過程式:以指令為中心,數據服務於指令
對象式:以數據為中心,指令服務於數據
shell程序:提供了編程能力,解釋執行

程序的執行方式

計算機:運行二進制指令
編程語言:
低級:匯編
高級:
編譯:高級語言-->編譯器-->目標代碼 java,C#
解釋:高級語言-->解釋器-->機器代碼 shell, perl, python

編程邏輯處理方式:

  • 順序執行
  • 循環執行
  • 選擇執行

shell 腳本的組成

對於shell腳本來是,它是一種弱類型,過程式的語言。不包括浮點型。
> 強類型:一個變量給他確定一個類型,賦值後,這個類型不可改變。

弱類型一個變量你不用給它指定類型,拿來就用。以至於拿到一個變量,你不知道它是個什麽類型,默認是字符型。參與運算會自動進行隱式類型轉換,變量無需事先定義可以直接調用。

shell腳本的用途有:

  • 自動化常用命令
  • 執行系統管理和故障排除
  • 創建簡單的應用程序
  • 處理文本或文件

shell腳本: 包含一些命令或聲明,並符合一定格式的文本文件

第一步:使用文本編輯器來創建文本文件
格式要求:首行shebang機制

    • #!/bin/bash
    • #!/usr/bin/python
    • #!/usr/bin/perl
    • 添加註釋
    • 註釋以#開頭
  1. 各種命令的組合

第二步:運行腳本
給予執行權限,在命令行上指定腳本的絕對或相對路徑

直接運行解釋器,將腳本作為解釋器程序的參數運行

腳本規範
腳本代碼開頭約定
1、第一行一般為調用使用的語言
2、程序名,避免更改文件名為無法找到正確的文件
3、版本號
4、更改後的時間
5、作者相關信息
6、該程序的作用,及註意事項
7、最後是各版本的更新簡要說明

我們知道,一臺Linux主機開機運行時,系統啟動什麽樣的shell時,是由用戶的個ID配置決定。也就是在/etc/passwd文件中個人用戶的第7個字段決定。

我們目前所啟用遠程連接的偽終端還是物理機上開的虛擬終端開啟的默認 shell為父shell。而在系統中輸入bash或/bin/bash 會開啟一個子shell

bash變量種類

本地變量

變量賦值:name="value"

  • 可以直接是字符串:name="username"
  • 變量引用:name="$PATH"
  • 命令引用:name=`cmd` name=$(cmd)
    變量引用中的強引用與弱引用
    “”:弱引用,變量引用會被替換為變量值
    ‘‘:強引用,變量引用不會被替換,而保持原字符串。

註意

  • 變量賦值時,變量建議加雙引號。變量賦值用等號, 前後不帶空格
  • 變量裏存放多行時,變量要用雙引號才能保留原來的格式
  • 當變量覆值含有空格的時候,變量的值要用雙引號來界定字符的首尾。若不加引號,系統會以為空格後的字符是你輸的命令。賦值時等號前後不能帶有空格。
  • 引用變量時是否要加$
    echo默認顯示的是字符串,變量不加$,echo會把他當字符串,
    能識別變量的命令可以不用加$。
  • $naem${name}本質相同,但出現十個以上的參數要加大括號,建議加上大括號。
    變量要存一個新值,會存在一個新的內存中,以前的值所存放的空間會被系統回收,給別的應用程序來用。
  • 雖然echo顯示字符串可以不加雙引號。但在腳本裏要顯示自己的文本消息時,如:echo Let‘s see if this‘ll work這串文本消息中有自己的單引號,必須要用雙引號給引起來。如果文本消息內有雙引號出現,要加上“轉義字符” \ 為了穩妥起見雙引號比較好。

shell腳本裏定義的變量在腳本的整個生命周期裏有效,但在shell腳本結束時會被刪除掉。

變量命名法則:

  • 不能使程序中的保留字:例如if, for
  • 只能使用數字、字母及下劃線,且不能以數字開頭
  • 見名知義
  • 統一命名規則:駝峰命名法

局部變量

  • 局部變量:生效範圍為當前shell進程;對當前shell之外的其它shell進程,包括當前shell的子shell進程均無效
  • 只在當前shell有效。
  • 在下級的子進程定義的變量不會影響上一級進程。

環境變量

  • 環境(全局)變量:生效範圍為當前shell進程及其子進程
    子進程可以用父進程的定義的變量也可以對變量進行更改,改完之後不能傳給上級進程,但可以傳給下級進程。

  • 如果子進程把父進程定義的變量用unset給刪了,父進程不受影響,只會影響到下一級子進程中。

位置變量

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

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

  • $1, $2, ...:對應第1、第2等參數,shift [n]換位置
    shift的用法:無法判斷用戶會輸入幾個參數,有兩種方法來判斷
    1、先獲取參數的個數。再來處理。
    2、不管參數有多少,用shift,把參數住左移,默認是移一位,移多少位,在後面加個數字。

  • $0: 命令本身======會寫上全路徑,可以用basename取基名
    如果用的是軟鏈接,$0會顯示軟鏈接的路徑。
  • $*: 傳遞給腳本的所有參數,全部參數合為一個字符串
  • $@: 傳遞給腳本的所有參數,每個參數為獨立字符串
  • $#: 傳遞給腳本的參數的個數
    $@ $* 只在被雙引號包起來的時候才會有差異
  • set -- 清空所有位置變量

腳本調試

  • 檢測腳本中的語法錯誤
    bash -n /path/to/some_script
  • 調試執行
    bash -x /path/to/some_script

查看變量與進程號

  • $$:一個進程的進程編號
  • $PPID:代表的是父進程的進程編號
  • pstree -p:查看進程與進程之間的關系
  • export :可以聲明一個變量為環境變量。
    先聲明後賦值,先賦值後來聲明,都是可以的。
  • export:顯示的是系統中目前的環境變量。
  • declare -x:也可以聲明環境變量。
  • env:顯示所有的環境變量
  • printenv :顯示所有的環境變量

set 顯示已定義的所有變量
銷毀變量:unset name
變量使用完畢以後,用unset將變量刪掉。在程序運行期間,變量不會在內存中釋放空間的。日積月累,會被占用內存的空間。


bash內建的環境變量:

  • PATH
  • SHELL
  • USER
  • UID
  • HOME
  • PWD
  • SHLVL
  • LANG
  • MAIL
  • HOSTNAME
  • HISTSIZE

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

聲明只讀變量:

  • readonly name
  • declare -r name
    查看只讀變量:
  • readonly –p
  • declare -r
    只讀變量只能使用,不能修改,也不能刪。常量的生命有效期是當前進程的有效期。

小括號與大括號的用
加上小括號相當於開了子進程,執行完又退回到父進程。可以認為是一次性任務,不影響當前進程
大括號不開啟shell,會影響當前環境。
它們的相同點是:把括號裏的命令做為一個整體,統一執行。

  • { cmd; }
  • (cmd)
    示例
    [root@centos7 bin]#x=1;echo "pid=$$";(echo "subpid=$$";echo "subx=$x";x=2;echo "subx2=$x");echo x=$x
    pid=3201
    subpid=3201
    subx=1
    subx2=2
    x=1

    小括號的特性:這種開啟子shell可繼承父進程的變量和進程編號。

    [root@centos7 ~]#false || (echo cmd1;exit)  
    cmd1
    [root@centos7 ~]#false || { echo cmd1;exit; }
    cmd1
    logout

    寫腳本時用小括號 是退不出腳本的。

退出腳本

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

  • 0 代表成功,1-255代表失敗
  • $? 變量保存最近的命令退出狀態。
    例如:
    ping -c1 -W1 hostdown &> /dev/null
    echo $?

退出狀態碼

  • bash自定義退出狀態碼
    exit [n]:自定義退出狀態碼
    註意:
  • 腳本中一旦遇到exit命令,腳本會立即終止;終止退出狀態取決於exit命令後面的數字
  • 如果未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決於腳本中執行的最後一條命令的狀態碼
  • 當腳本裏,有命令錯誤時,執行腳本還是會執行 下面的命令。
  • 如果是語法錯誤,就不會向下執行命令了。

算術運算

  • 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(0-32767)
    echo $[$RANDOM%50] :0-49之間隨機數

賦值

  • 增強型賦值:
    +=, -=, *=, /=, %=
  • let varOPERvalue
    例如:let count+=3
    自加3後自賦值
  • 自增,自減:
    let var+=1
    let var++
    let var-=1
    let var--

###邏輯運算

  • 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
  • 短路運算
    短路與
    第一個為0,結果必定為0
    第一個為1,第二個必須要參與運算
    短路或
    第一個為1,結果必定為1
    第一個為0,第二個必須要參與運算
  • 異或:^
    異或的兩個值,相同為假,不同為真

異或:
相同為假flase
不同為真true

[root@centos7 ~]#a=4
[root@centos7 ~]#b=6
[root@centos7 ~]#echo $a $b
4 6
[root@centos7 ~]#a=$[a^b];b=$[a^b];a=$[a^b];echo $a $b
6 4
[root@centos7 bin]#false || echo cmd1 && echo cmd2 
cmd1
cmd2
[root@centos7 bin]#true || echo cmd1 && echo cmd2 
cmd2
[root@centos7 bin]#true || (echo cmd1;echo cmd2)    
[root@centos7 bin]#false || (echo cmd1;echo cmd2) 
cmd1
cmd2

條件測試

判斷某需求是否滿足,需要由測試機制來實現
專用的測試表達式需要由測試命令輔助完成測試過程
?評估布爾聲明,以便用在條件性執行中
?若真,則返回0
?若假,則返回1
?測試命令:
?test EXPRESSION
?[ EXPRESSION ]
?[[ EXPRESSION ]]
註意:EXPRESSION前後必須有空白字符

  • -z 測試字符串是否為,空為真,非空為假。
  • -n 測試字符串是否為非空。非空為真,空為假。-n可以省略

?根據退出狀態而定,命令可以有條件地運行
?&& 代表條件性的AND THEN
?|| 代表條件性的OR ELSE

bash的字符串測試

  • 字符串測試:
  • == 是否等於
  • \> ascii碼是否大於ascii碼
  • \< 是否小於
  • != 是否不等於
  • =~ 左側字符串是否能夠被右側的PATTERN所匹配
  • 註意: 此表達式一般用於[[ ]]中;擴展的正則表達式
  • -z "STRING“ 字符串是否為空,空為真,不空為假
  • -n "STRING" 字符串是否不空,不空為真,空為假
    註意:用於字符串比較時的用到的操作數都應該使用引號

    用到時正則表達式用兩個中括號 ,test與一個中括號 是等價的。

bash的數值測試

  • 數值測試:
    -v VAR
    變量VAR是否設置-v VAR被賦過值 和也算有值和空字符串是兩碼事
    數值測試:
  • -gt 是否大於
  • -ge 是否大於等於
  • -eq 是否等於
  • -ne 是否不等於
  • -lt 是否小於
  • -le 是否小於等於

註意
變量在中括號裏寫時要加雙引號
當判斷軟鏈接時,判斷的是軟鏈接指向的文件。
判斷權限判斷的是實際權限

bash shell