Linux運維學習歷程-第九天-bash腳本初步了解

概述:

  本章重點在于講解bash腳本的基礎知識,為今后學習使用bash腳本打下基礎

一、bash基礎特性

        程序:指令+數據

            指令:由程序文件提供

            數據:IO設備、文件、管道、變量

        程序:算法+數據結構

        變量:變量名+指向的內存空間

        變量賦值:name=value

        變量類型:存儲格式(變量存儲數據的數據類型)、表示數據范圍、參與的運算

            編程語言:

                 強類型變量:變量類型不可變,是什么類型就是什么類型;例如C語言

                 弱類型變量:

                       bash把所有變量統統視作字符型

                       bash正常情況下不支持浮點型數據,除非借助其他工具

                       bash中的變量無需事先聲明:相當于把聲明和賦值過程同時實現

                          聲明:說明數據類型,定義變量名

        變量替換(引用):把變量名出現的位置替換為其所指向的內存空間中數據

        變量引用:${var_name},$var_name

        變量名:變量名只能包含數字、字母和下劃線,而且不能以數字開頭

            變量名:見名知義,命名機制遵循某種法則:不能夠使用程序的保留字,例如if,else,then,while等等

        bash變量類型:根據作用范圍劃分的

            本地變量:作用域范圍僅為當前shell進程

            環境變量:作用域為當前shell進程及其子進程

            局部變量:作用域僅為某代碼片段(函數上下文)

            位置參數變量:向執行腳本的shell進程傳遞的參數

            特殊變量:shell內置的有特殊功用的變量;例如$?保存上一個命令執行的狀態結果

                                                       0:成功

                                                       1-255:失敗

        本地變量:只對當前shell進程有效

            變量賦值:name=value

                  name=$user

                  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

            注意:bash內嵌了許多環境變量(通常為全大寫字符),用于定義bash的工作環境

                 PATH,HISTFILE,HISTSIZE,HISTFILESIZE,HISTCONTROL,SHELL,HOME,UID,PWD,OLDPWD

            查看環境變量:export,declare -x,printenv,env

            撤銷環境變量:unset name

        只讀變量:不能修改和撤銷

             (1)declare -r name

             (2)readonly name

             只讀變量無法重新賦值,并且不支持撤銷;存活時間為當前shell進程的生命周期,隨shell進程終止而終止

            位置變量:見下文第二部分整理

            局部變量:對當前shell進程中的某代碼片段有效(通常指函數上下文)

PATH變量定義位置:.bash_profile  –>  $PATH:$HOME/binPATH=$PATH:$HOME/.local/bin:$HOME/bin     –.local/bin  centos7普通用戶有的隱藏的目錄,可以放寫隱藏的腳本
寫腳本的時候可以先mkdir /home/bin 在bin目錄下寫腳本,可省去相對路徑。
source bash.sh 也可以執行腳本:其執行過程相當于直接在當前shell進程中進行,而不是開一個子進程進行,所有腳本執行完,echo 變量,還可以查看到變量的值。(正常父進程是不能查看子進程的變量的)shadow 默認權限000  但是root用戶屬于超級用戶 可讀可寫,但是如果文件沒有x權限,root也不能執行

算數運算符bash中的算數運算符:+、-、*、/、%、**(平方) 注意:在使用expr的時候“*” 要轉義“\*”實現算數運算:                let var=算數表達式                var=$[算數表達式]                var=$((算數表達式))                var=$(expr arg1 arg2 arg3)   注意:每個參數之間要用空格隔開

declare -i var =數字

echo ‘算數表達式’| bc

隨機數生成器:echo $[RANDOM%50]:0-49之間的隨機數                           echo $[RANDOM%50+1]:1-50之間的隨機數                           $RANDOM :1-32767 聚合命令 #!/bin/bash
echo xxx;(echo zzz;exit)     ############():代表開個子shell,exit退出子shell非當前shell
echo yyy

退出狀態

0 代表成功, 1-255代表失敗$? 變量保存最近的命令退出狀態

我們也可以指定程序退出的狀態碼,根據狀態碼的數值,來判斷工作狀態,腳本中一旦遇到exit命令,腳本會立即終止,終止,終止退出狀態取決于exit命令后面的數字,如果沒有執行exit,則取腳本最后一條命令的執行狀態結果。


條件測試

測試命令:test [expression]
                   [ $a = $b ]           判斷 一對[]或兩對[[]] 都可以
                   [[ $a == $b ]]      兩個等號也可以  
                  [ -f /bin/cat -a -x /bin/cat ]    此時必須使用 一對[]  否則會報錯 數值測試:                        -gt:大于                        -ge:大于等于                        -lt:小于                        -le:小于等于                        -eq:等于                        -ne:不等于字符串測試:                          ==:是否相等                          >:大于(比較ascll碼)                          <:小于                          !=:是否不等于                          =~:左側字符串是否能夠被右側的PATTERN所匹配,注意: 此表達式一般用于[[ ]]中;                          -z “string”:判斷字符串是否為空,如果為空則為真                           -n “string”:判斷字符串是否為空,如果不為空則為真 注意:用于字符串比較的時候,操作數應該使用引號存在性測試:               -a file:文件存在為真,否則為假               -e file:同-a              存在性及類別測試:         -b FILE:是否存在且為塊設備文件           
         -c FILE:是否存在且為字符設備文件        
          -d FILE:是否存在且為目錄文件                
          -f 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 && COMMAND2 并且
         COMMAND1 || COMMAND2 或者
         ! COMMAND 非
如: [ -e FILE ] && [ -r FILE ]
第二種方式:
         EXPRESSION1 -a EXPRESSION2 并且
         EXPRESSION1 -o EXPRESSION2 或者
         ! EXPRESSION

  bash特性之多命令執行:

      ~]#COMMAND1;COMMAND2;COMMAND3;…

      邏輯運算:

          運算數:真(true,yes,on,1)

                  假(false,no,off,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,不同則為1

        短路法則:可以提前判斷出結果

        ~]#COMMAND1 && COMMAND2

           COMMAND1為“假”,則COMMAND2不會再執行

           否則,COMMAND1為“真”,則COMMAND2必須執行

        ~]#COMMAND1 || COMMAND2

          COMMAND1為“真”,則COMMAND2不會再執行

           否則,COMMAND1為“假”,則COMMAND2必須執行

           示例:~]#id $username || useradd $username

       示例: ~】#id $username ||useradd $username

        shell腳本編程:

            編程語言的分類:根據運行方式

                編譯運行:源代碼–>編譯器(編譯)–>程序文件

                解釋運行:源代碼–>運行時啟動解釋器,由解釋器邊解釋邊運行

        根據其編程過程中功能的實現是調用庫還是外部的程序文件

            shell腳本編程:利用系統上的命令及編程組件進行編程

            完整程序:利用庫或編程組件進行編程

        編程模型:過程式編程語言,面向對象的編程語言

           程序=指令+數據

               過程式:以命令為中心來組織代碼,數據是服務于代碼

                       順序執行

                       選擇執行

                       循環執行

                       代表:C,bash

               對象式:以數據為中心來組織代碼,圍繞數據來組織指令

                       類(class):實例化對象(數據結構),method;

                       代表:java,C++,Python

        shell腳本編程:過程式編程、解釋運行、依賴于外部程序文件運行;

             如何寫shell腳本:

               常見的解釋器:shellbang

                #!/bin/bash

                #!/user/bin/python

                #!/user/bin/perl

        文本編輯器:nano

            行編輯器:sed

            全屏幕編輯器:nano、vi、vim

        shell腳本是什么?

             命令的堆積:

               但很多命令不具有冪等性,需要用程序邏輯來判斷運行條件是否滿足,,以避免其運行中發生錯誤

        運行腳本:

           (1)賦予執行權限。并直接運行此程序文件;

                 chmod +x /PATH/SCRIPT_FILE

                 /PATH/TO/SCRIPT_FILE

           (2)直接運行解釋器,將腳本以命令行參數傳遞給解釋器程序

                bash/PATH/TO/SCRIPT_FILE

          注意:腳本中的空白行會被解釋器忽略

                腳本中,除了shebang,余下所有以#開頭的行,都會被視作注釋行而被忽略;此即為注釋行;

                shell腳本的運行是通過運行一個子shell進程實現的

    bash的配置文件:

      兩類:

      profile類:為交互式登錄的shell提供配置

      bashrc類:為非交互式登錄的shell進程提供配置

      登錄類型:

          交互式登錄shell進程:

              直接通過某終端輸入賬號和密碼后登陸打開的shell進程

              使用su命令:su – USERNAME,或者使用su -l USERNAME執行的登錄切換

          非交互式登錄shell進程:

             su USERNAME執行的登錄切換

             圖像界面下打開的終端

             運行腳本(bash子進程)

    profile類:

         全局:對所有用戶都生效;

            /etc/profile

            /etc/profile.d/*.sh

         用戶個人:僅對當前用戶有效

             ~/.bash_profile

         功用:

             1、用于定義環境變量

             2、運行命令或腳本

    bashrc類:

          全局:/etc/bashrc

          用戶個人:~/.bashrc

          功用:

              1、定義本地變量

              2、定義命令別名

    注意:僅管理員可修改全局配置文件

  

    交互式登錄shell進程:

          /etc/profile–>/etc/profile.d/*–>~/.bash_profile–>~/.bashrc–>/etc/bashrc

    非交互式登錄shell進程:

         ~/.bashrc–>/etc/bashrc–>/etc/profile.d/* 

    命令行中定義的特性,例如變量和別名作用域為當前shell進程的生命周期

    配置文件定義的特性,只對隨后新啟動的shell進程有效

    讓通過配置文件定義的特性立即生效:

       (1)通過命令行重復定義一次

       (2)讓shell進程重讀配置文件

            ~]#source /PAHT/FROM/CONF_FILE

            ~]#./PATH/FROM/CONF_FILE

    問題1:定義對所有用戶都生效的命令別名,例如lftps='lftp 172.16.0.1/pub'?

    問題2:讓centos用戶登錄時。提供其已經登錄,并顯示當前系統時間?

     bash的特性:hash變量

           命令hash:hash命令

           變量:

                本地變量、環境變量、局部變量、位置參數變量、特殊變量

                變量賦值:name=value,export name=value,declare -x name=value

                變量引用:$name,${name}

                        注意:有些時候{}不能省略,例如

                myvalue=

                撤銷:unset name

     bash腳本編程,運行腳本

          #!/bin/bash      shebang

          #                注釋

          空白行           忽略不顯示行

     bash的配置文件

         porfile類:登錄式shell

         bashrc類:非登錄式shell

         登錄式shell:/etc/profile–>/etc/profile.d/*.sh–>~/.bash_profile–>~/.bashrc–>/etc/bashrc

         非登錄式shell:~/.bashrc–>/etc/bashrc–>/etc/profile.d/*.sh

二、總結位置變量:

$1,$2.. ${10},${11}..:對應調用的第1、第2個等參數;用于讓腳本在腳本代碼中通過調用命令行中的傳遞的參數,1和2 等分別代表第一個參數和第二個參數…,shift可以替換參數

特殊變量:$?:判斷執行結果0-255

     $0:表示命令本身腳本名稱

     $#:傳遞給腳本參數的個數

     $*:傳遞給腳本的所有參數(所有參數整體一次性傳遞給腳本)

     $@:引用傳遞給腳本的所有參數(每個參數單獨為一個整體一次性傳遞給腳本)

     $*與$@的區別:

    相同點:都是引用所有參數

    不同點:只有在雙引號中體現出來
      假設你的腳本運行時你寫了三個參數 分別存儲在$1 $2 $3中 
      則"$*" 等價于 “$1 $2 $3" —>傳遞了一個參數
      而“$@" 等價于 "$1" "$2" "$3" —>傳遞了三個參數

例證:

wKioL1ezAdrzxVGDAACxW1TOM0o970.jpg

三、作業:

1、編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,包括主機名,IPv4地址,操作系統版本,內核版本,CPU型號,內存大小,硬盤大小。

解決思路:

     分步拆解,將所要的信息用合理的方法先單獨獲取到,再整合到shell script中

主機名:有兩種簡單的獲取方式

hostname       #hostname命令(推薦)
echo $HOSTNAME    #利用hostname命令所調用的環境變量
uname -n        #利用uname命令直接獲?。ɑ旧习ê芏嘞到y信息)

IPv4地址:利用ifconfig命令、擴展正則表達式、head命令獲取

ifconfig |egrep -o "((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])"|head -1

此種方法看上去雖然很亂和繁瑣,但是此公式的實用性很廣,在Centos6與7中,ifconfig中獲取的ip信息格式有些許不同,這就會造成我們從一個版本到另一個版本時,要調整表達式,而用上述表達式則可以盡量避免此種情況

操作系統版本:

cat /etc/redhat-release   #適用于6、7版本(推薦適用性廣、直接獲取到我們需要的,沒有其它)
lsb_release               #適用于6
cat /etc/issue            #適用于6

內核版本:

uname -r

CPU型號:

lscpu |head -n 13|tail -n +13|cut -d: -f2|tr -s " "

內存大?。?/p>

free -h |head -2|tail -1|tr -s " "|cut -d" " -f2

硬盤大?。?/p>

lsblk -d|egrep "^sd.*"|tr -s " "|cut -d" " -f1,4

注意:在不同版本中和不同的語言環境下,命令行不一定通用,例如CPU型號,我的centos7安裝了中文環境,在不調整語言環境和命令行的情況下是與centos6英文版,不通用,所以大家要多多注意

根據上面的信息逐一獲取方法我們可以編寫以下內容作為/root/bin/systeminfo.sh腳本

vim /root/bin/systeminfo.sh

wKiom1ex3BvD9xbmAAGPT2mMy_Y768.jpg

wKioL1ex3Dihdq9LAAA8Z-vYwn8431.jpg

wKiom1ex3DnyyjGfAACQwcXaOeE323.jpg

注意:在運行之前需要給腳本添加執行權限哦

chmod +x /root/bin/systeminfo.sh

這樣就可以直接運行腳本文件了

直接運行

絕對路徑:/root/bin/systeminfo.sh

相對路徑:./systeminfo.sh

不賦予執行權限就只能再打開一個bash子進程解析運行此腳本了,但是注意結果能得到,但是在我們以后用配置腳本的話,則不見用用此方法,因為子進程運行的變量是不能影響父進程的

間接運行:

bash /root/bin/systeminfo.sh

以下每題都是默認賦予執行權限我就不說了

2、編寫腳本/root/bin/backup.sh,可實現每日將/etc/目錄備份到/root/etcYYYY-mm-dd中

wKioL1eyrifC_a2tAAE0ZJlzUF0021.jpg

3、編寫腳本/root/bin/disk.sh,顯示當前硬盤分區中空間利用率最大的值

wKioL1eyrkKBRc0zAAFXu3ivfsE757.jpg

4、編寫腳本/root/bin/links.sh,顯示正連接本主機的每個遠程主機的IPv4地址和連接數,并按連接數從大到小排序

wKioL1eyrmSzqTKOAAFVCh0q8EU853.jpg

5、寫一個腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第20用戶的ID之和

wKioL1eyrn6TPeufAAF4dq-Feto236.jpg

6、寫一個腳本/root/bin/sumspace.sh,傳遞兩個文件路徑作為參數給腳本,計算這兩個文件中所有空白行之和

wKiom1eyrpuCxZIgAAFwz7VjVaw872.jpg

7、寫一個腳本/root/bin/sumfile.sh,統計/etc, /var, /usr目錄中共有多少個一級子目錄和文件

wKioL1eyswuSHYYMAAFIcsJrdak625.jpg

wKioL1eyswuRLFlWAAAfyz6B45w600.jpg

8、寫一個腳本/root/bin/argsnum.sh,接受一個文件路徑作為參數;如果參數個數小于1,則提示用戶“至少應該給一個參數”,并立即退出;如果參數個數不小于1,則顯示第一個參數所指向的文件中的空白行數

wKiom1eyt4uh_TGiAAFbcx2svCU569.jpg

9、寫一個腳本/root/bin/hostping.sh,接受一個主機的IPv4地址做為參數,先判斷是否合格IP,否,提示IP格式不合法并退出,是,測試是否可連通。如果能ping通,則提示用戶“該IP地址可訪問”;如果不可ping通,則提示用戶“該IP地址不可訪問”

wKiom1eyy83g_rRGAAGvkWzhR-U983.jpg

10、chmod -rw /tmp/file1,編寫腳本/root/bin/per.sh,判斷當前用戶對/tmp/file1文件是否不可讀且不可寫

wKiom1ey1IrDiegHAACE62dmHrI480.jpg

wKioL1ey1IyCdQTBAAFWvJnwiYI529.jpg

11、編寫腳本/root/bin/nologin.sh和login.sh,實現禁止和充許普通用戶登錄系統。

wKiom1ey3XOTCuC9AAEqVZtat2Q978.jpg

wKiom1ey3XSx8i_VAAEmhBTPdyA659.jpg

12、計算1+2+3+…+100的值

echo {1..10}|tr " " "+"|bc
echo $((`echo {1..10}|tr " " "+"`))

13、計算從腳本第一參數A開始,到第二個參數B的所有數字的總和,判斷B是否大于A,否提示錯誤并退出,是則計算之

wKiom1ey_GPzFBkUAAGlYdAt9zg207.jpg

原創文章,作者:NameLess,如若轉載,請注明出處:http://www.www58058.com/36670

(0)
NameLessNameLess
上一篇 2016-08-18
下一篇 2016-08-18

相關推薦

  • 軟件包管理之yum

    本節主要是對linux軟件包管理中的yum的淺解 1、冒泡法對數組內數據排序 2、博客:        yum命令淺解    yum [options] [command] [package …]      …

    Linux干貨 2016-08-25
  • 招聘Linux運維工程師

    崗位職責: 公司集群硬件的日常維護及管理 負責公司內網的服務器安裝,部署和維護 監控服務器狀態,發現問題并及時維護 負責產品發布上線 承擔mangoDB的日常巡檢 集群數據服務器的備份 編寫服務器維護腳本,減少工作量,提高工作效率 任職要求: 1年以上Linux系統管理經驗,精通Linux的管理和維護 能夠熟練編排查運維過程中出現的服務故障,系統故障,網絡故…

    Linux干貨 2017-12-04
  • 用戶與用戶組相關的配置文件與命令總結

    Linux 中用戶與用戶組相關的配置文件與命令總結 用戶與用戶組 UID、GID 名稱解析與解析庫(passwd、group、shadow、gshadow) 用戶信息庫/etc/passwd 用戶密碼信息/etc/shadow 組的信息庫/etc/group 組的密碼信息/etc/gshadow 用戶管理命令 用戶組管理命令 用戶與用戶組 Linux是一種多…

    2016-10-23
  • 推薦CentOS Linux下的分區及格式化工具

    簡介 伴隨著科技的飛速發展,越來越多的企業對于服務器的穩定要求越來越高,越來越多的企業開始采用linux系統來部署自己的服務,以求高效的穩定性,當然任何操作系統都需要一個最基本的基礎,那就是硬盤,及硬盤分區,今天來給大家推薦幾款CentOS Linux下的分區工具及如何查看分區環境,也會給大家來帶一些硬盤的基本知識 一、硬盤的接口類型 分區肯定是對硬盤進行分…

    2017-03-19
  • Linux 文本編輯器三劍客之 sed

    參考手冊: http://www.gnu.org/software/sed/manual/sed.html 轉載請注明:馬哥教育??!

    Linux干貨 2017-01-12
  • Linux命令date命令詳解

    在linux環境中,熟練運用date命令來表示自己想要表示的時間,肯定可以給自己的工作帶來諸多方便,下面是詳細的使用說明和示例 在linux環境中,不管是編程還是其他維護,時間是必不可少的,也經常會用到時間的運算,熟練運用date命令來表示自己想要表示的時間,肯定可以給自己的工作帶來諸多方便。 1.命令格式:date[參數]… [+格式] 2.命…

    2017-07-18

評論列表(1條)

  • 馬哥教育
    馬哥教育 2016-08-19 11:12

    總結的很詳細,希望以后的作業能按時完成

欧美性久久久久