1. 程式人生 > >Linux階段總結shell腳本

Linux階段總結shell腳本

bash環境 if for while grep sed awk

shell腳本知識儲備匯總

語言類型

強類型:定義變量必須指定類型;

    參與的運算必須要符合類型要求(字符串不能和數值相加等);

    調用未聲明變量會報錯

弱類型:定義變量無需指定類型;

    默認為字符型參與運算時會自動進行類型轉換;

    變量無需事先定義也可調用(空)

解釋器:

shell是解釋器bash是可用的具體解釋器(shell是車這個概念bash是寶馬車)

bash  sh ksh(需自己安裝) tcsh csh等   

bash的基本特性:快捷鍵;Tab補齊命令和路徑;history;命令別名;標準輸入輸出;重定向;管道;

    Redhat6選項不可Tab  需要裝bash-completion這個包才能Tab

更改用戶shell環境(解釋器):   useradd -s 創建用戶時

                usermod -s 改已存在用戶

                vim /etc/passwd 改配置

history:查看條數: grep HISTSIZE /etc/profile

            echo $HISTSIZE

            history | wc -l

            history | tail

     調用:        !1028

            !cat

     清空(兩條命令必須同時執行):     history -c 

                     > ~/.bash_history  空重定向到HISTFILE文件

別名alias:    grep ‘^alias‘ ~/.bashrc 家目錄下的隱藏文件

        unalias 取消

重定向:

>    (正確覆蓋輸出);

>>   (正確追加輸出);

2>   (錯誤覆蓋輸出);

2>>  (錯誤覆蓋輸出);

&>       (正確錯誤覆蓋輸出);

&>>      (正確錯誤追加輸出);

>&2      把正確變成錯誤輸出

<;  (導入文件)  

    tips:   寫腳本可以上來就date >(>>) xx.log  再在裏面把命令執行錯誤的信息2>(>>) xx.log以執行時間         

                         進行區分了方便查看某次執行時的錯誤

非交互式寫郵件三種:

    mail -s biaoti user <<EOF

            XX

            YY

            EOF

    echo haha | mail -s biaoti user  管道

    mail -s biaoti user < mail.txt   導入寫好文件

腳本的執行方式:

    /root/first.sh   ./first.sh     絕對路徑(相對)執行      需+x

    bash、sh /root/first.sh      解釋器執行(相當於作為參數)不需+x  開了子進程pstree可以驗證

    source、./root/first.sh      解釋器執行(相當於作為參數)  不需+x  當前進程執行

                    (用於使改的配置馬上生效而不重啟,相當於重讀配置文件。

shell變量:

變量的類型

    儲值類型:

        數值型  :整數型;浮點型;復數。。。

        字符型  :

    生效範圍:

        本地變量:當前Shell環境中有效,而在子Shell環境中無法直接使用 

        局部變量:

        全局變量:

    使用類型:

        自定義變量:  a=1 echo ${a}10  110 本地變量

TIPS:查看變量時,若變量名稱與後面要輸出的字符串連在一起,則應該以{}將變量名括起來以便區分

        環境變量:   PWD、USER、HOME、SHELL、HISTSIZE、HISTFILE、PATH、PS1一級提示符、

                PS2二級提示符、LOGNAME登錄名 RANDOM HOSTNAME TERM記錄終端類型

            環境變量相關文件:(註意開機時讀取文件順序)

                全局文件為/etc/profile,對所有用戶有效   

                用戶文件為~/.bash_profile,僅對指定的用戶有效

            env可查看所有環境變量:

            set可查看所有變量  

        位置變量:   $1、$2、$10、……

        預定義變量:  $0、$$、$?、$#、$*、$@   

            #!/bin/bash

            echo $0                                        //腳本的名稱

            echo $1                                        //第一個參數

            echo $2                                        //第二個參數

            echo $*                                        //所有參數 當成一個整體字符串

            echo $@                        //所有參數 每個參數為獨立字符串

            echo $#                                        //所有的綜合

            echo $$                                        //當前進程的進程號

            echo $?                                        //上一個命令執行狀態返回值

            shift 3                     //換崗 踢掉參數(默認為一個)

使用read命令從鍵盤讀取變量值

         read -p "請輸入。。:" i  用戶輸入的值賦予變量i

         將回顯功能關閉(stty -echo)  輸password時

         將回顯功能恢復(stty echo)   輸完password時

使用export發布全局變量  

        export PATH="$PATH:/usr/local/haha/bin"臨時加了個可執行路徑。

        export XX="1234" 

變量的定義:  名稱只能為字母數字下劃線且只能以數字和下劃線開頭

        a=123       字符串

        a=$b        引用其他變量的值為自己的值

        a=$(date)   命令結果引用為自己的值

三種引號對賦值的影響:

        強引用:    單引號     界定一個完整字符串

        弱引用:    雙引號         界定一個完整的字符串且屏蔽特殊符號

        命令結果引用:  反撇號或$()    引用命令執行的結果賦予變量       

變量的調用

        調用變量時,若變量名稱與後面輸出的字符串連在一起,以{}將變量名括起來以便區分

shell的數值運算

整數運算:

    expr             \*

    $[]或$(())       運算符兩側可以無空格  引用變量可省略 $

    let         不顯示結果

expr或$[]、$(())方式只進行運算,並不會改變變量的值;而let命令可以直接對變量值做運算再保存新的值

    let X++ X-- X+=7 X-=7 X*=7 X/=7 X%=7  強大!!

小數運算:

    bc      scale=N 小數位的長度

            echo ‘scale=4;12.34-5.678‘ | bc 

            6.662  雖然小數位長為4但運算數值最長為3 也只顯示3位。

        tips:bc支持條件測試正確返回1錯誤返回0 與$?相反

條件測試

“test 表達式”或者[ 表達式 ]都可以,表達式兩邊至少要留一個空格。註意空格空格空格!

        [  $USER == "root"  ] 等號兩邊有空格(沒有就相當字符串a) 表達式和[]間有空格!!!

字符串匹配

        ==  !=  -z 檢查變量的值是否為空      -n或!-z 檢查變量的值是否非空        

比較整數值的大小

        eq  

        ne

        gt

        ge

        lt

        le

識別文件/目錄的狀態

        -e

        -d

        -f

        -r

        -w

        -x

多個條件/操作的邏輯組合

        &&,邏輯與  第一個為假後面都不用執行

        ||,邏輯或  第一個為真後面都不用執行

        !,邏輯非

        短路運算:[ $X -gt 10 ] && echo "YES" || echo "NO"

              第一個為真必須yes而不會No了,因為前面整體為真了||運算已經結束。

if選擇結構

單分支就直接:     [ $X -gt 10 ] && echo "YES"

雙分支:        [ $X -gt 10 ] && echo "YES" || echo "NO"

    if  [ 條件測試 ];then  

        命令序列1

        else    命令序列2

    fi

多分支:    

    if  [ 條件測試 ];then  

        命令序列1   執行完就exit

    elif

        命令序列2   執行完就exit

        else   

        命令序列3   執行完就exit

    fi

案例:

    檢測/media/cdrom目錄,若不存在則創建

    檢測並判斷指定的主機是否可ping通

        ping -c 3 -i 0.2 -W 3 192.168.4.5   

            -c 3(3次)-i0.2間隔0.2秒-W 3反饋的超時秒數3

    從鍵盤讀取一個論壇積分,判斷論壇用戶等級

被閹割的選擇結構case

    case分支屬於匹配執行的方式,它針對指定的變量預先設置一個可能的取值,判斷該變量的實際取值是否與       預設的某一個值相匹配,如果匹配上了,就執行相應的一組操作,如果沒有任何值能夠匹配,就執行預先設     置的默認操作。

            case  變量值  in

            模式1)

                命令序列1 ;;

            模式2)

                命令序列2 ;;    註意格式!!!必須是雙分號。。

                .. ..

            *)

                默認命令序列

            esac

    #!/bin/bash

    case $1 in

    redhat)                 //可以換成-n-i來代表選項做一個功能強大的命令出來

             echo "fedora";;

    fedora)

             echo "redhat";;

         *)                                              //默認輸出腳本用法

                echo "用法: $0 {redhat|fedora}"

    esac

循環結構

for循環

    for  變量名  in  值列表或 {1..5} 或 `seq 5` 或((i=1;i<=5;i++))

    do

        命令序列

    done

幾個循環造數工具

    {1..n}

     seq 5(1開始到5) seq 2 10(2開始到10)seq 2 2 10(2開始中間跳2;即偶數)seq 1 2 10(奇數)

    [$RANDOM%10+1] 隨機產生1-10的數

    ((i=1;i<=5;i++))  初值1;條件<=5;步長為1

案例:

    利用for循環來檢測多個主機的存活狀態

while循環 

    while  [條件測試]

    do

            命令序列

    done

    死循環一般格式 while :

            do

                    命令序列

            done

    通常會寫成死循環加退出的格式

            while :

            do

                if[條件判斷];then

                    命令序列 && break

            done

    案例:  提示用戶猜測一個隨機數,直到才對為止

        檢測192.168.4.0/24網段,列出不在線的主機地址

shell函數

將一些需重復使用的操作,定義為公共的語句塊,即可稱為函數。通過使用函數,可以使腳本代碼更加簡潔,增強易 讀性,提高Shell腳本的執行效率

    相當於一段代碼(一串命令)取了一個名字類似定義了alias

    定義錯了直接重新定義會覆蓋,類似a=1;a=2後會覆蓋前。

    function  函數名 {

            命令序列

         .. ..

         }

    函數名() {

            命令序列

            .. ..

        }           

            mycd(){                        //定義函數

            > mkdir $1

            > cd $1

            > }

    案例:顏色輸出的命令:echo -e "\033[32;41mOK\033[0m"。3X為字體顏色分號隔開4X為背景顏色。

    #!/bin/bash

    cecho() {

            echo –e "\033[$1m$2\033[0m"

    }

        cecho 32 OK

        cecho 33 OK

        cecho 34 OK

        cecho 35 OK

中斷和退出

break可以結束整個循環;

continue結束本次循環,進入下一次循環;

exit結束整個腳本、

        #!/bin/bash

        for  i   in   {1..5}

        do

            [  $i  -eq  3 ]&& break 

            //這裏將break替換為continue,exit分別測試腳本執行效果       

        echo $i

        done

        echo  Over

            break 12Over  continue1245Over  exit12

    案例:求輸入數的和輸0退出

        #!/bin/bash

        while  read  -p  "請輸入待累加的整數(0表示結束):"     x

        do

            [ $x -eq 0 ]  &&  break

            SUM=$[SUM+x]

        done

        echo "總和是:$SUM"

    案例:求1-20內所有數的平方跳過非6的倍數

        #!/bin/bash

        i=0

        while  [ $i -le 20 ]

        do

                let i++

                [ $[i%6] -ne 0 ]  &&  continue

                echo $[i*i]

        done

        exit 2

文本處理

字符串截取及切割

    echo $變量名 | cut -b 起始位置-結束位置            

            echo $phone | cut -b 1-6    1-6

            echo $phone | cut -b 8-     8到最後

            echo $phone | cut -b 9      第9個

            echo $phone | cut -b 3,5,8  第3 5 8個

    expr substr "$變量名" 起始位置 長度

    ${變量名:起始位置:長度}      截取 (索引位置)   ${phone:0:6} ${phone::6}        

    ${變量名/old/new}      替換第一個

    ${變量名//old/new}     替換全部

    ${變量名#*關鍵詞} (關鍵詞也刪)左向右 最短匹配刪除   ${A#*:} 從左側到第一個:的所有

    ${變量名##*關鍵詞}        左向右 最長匹配刪除  ${A##*:}從左側到最後一個:的所有        

    ${變量名%關鍵詞*}     右向左 最短匹配刪除  ${A%:*} 從右側到第一個:的所有

    ${變量名%%關鍵詞*}        右向左 最長匹配刪除  ${A##*:}從右側到最後一個:的所有    

    ${變量名:-初值}          有初值就用初值 無初值就用賦予的初值  

                    ${XX:-123}xx無初值就賦予123為初值

隨機密碼    #!/bin/bash

        x=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

        //所有密碼的可能性是26+26+10=62(0-61是62個數字)

        for i in {1..8}

        do

        num=$[RANDOM%62]

        tmp=${x:num:1}

        pass=${pass}$tmp    字符串相加

        done

        echo $pass

改擴展名    touch {a,b,c,d,e,f,g,h,i}.doc

        #!/bin/bash

        for FILE in `ls *.doc($1)`

        do

            mv $FILE  ${FILE%.*}.txt("$2") (${FILE/doc/txt})  $1換成$2的擴展名

        done

初值的處理   #!/bin/bash

        read -p "請輸入一個正整數:" x

        x=${x:-1}

        i=1; SUM=0

        while [ $i -le $x ]

        do

             let SUM+=i

             let i++

        done

        echo "從1到$x的總和是:$SUM"

        #!/bin/bash

        read  -p   "請輸入用戶名:"   user

        read  -p   "請輸入用戶名:"   pass

        [ -z $user ] && exit                    //如果無用戶名,則腳本退出

        pass=${pass:-123456}                    //如果用戶沒有輸入密碼,則默認密碼為123456

        useradd  $user

        echo "$pass"  | passwd   --stdin   $pass

expect預期交互  :模擬人機交互過程(要提前對交互過程非常熟悉)

        install  expect

        #!/bin/bash

        for i in 10 11          {1..245} seq 1 254

        do

        expect << EOF

        spawn ssh -o StrictHostKeyChecking=no 172.25.0.$i   #//創建交互式進程           

        expect "password:" { send "123456\r" }              #//自動發送密碼

        expect "#   { send "pwd > /tmp/$user.txt \r" }      #//發送命令

        expect "#"  { send "exit\r" }

        EOF

        done

            expect腳本的最後一行默認不執行

            如果不希望ssh時出現yes/no的提示,遠程時使用如下選項:

            # ssh -o StrictHostKeyChecking=no server0

shell數組

    整體賦值:a=(haha xixi hehe )    a[0]=haha 0是索引值為0的量

    單個賦值:a[0]=haha  

          a[1]=xixi

          a[2]=hehe

文本處理三劍客grep

    三劍客都用‘‘單引號!

正則表達式

    字符匹配(單個字符).點        任意單個字符

            []  [xyz]   集合,裏面的任意單個字符

                [a-z]   [:lower:]

                [A-Z]   [:upper:]

                [a-Z]   [:alpha:]

                [0-9]   [:digit:]

                [0-9a-Z][:alnum:]

                [:space:]   

            [^] [^xyz]  集合取反    

                [^a-z]

                [^A-Z]

                [^a-Z]

                [^0-9]

                [^0-9a-Z]

            |(擴展)x|y    或者

    匹配次數        *       前一個字符出現任意次

            \{n,m\}     前一字符出現n到m次

            \{n}        前一字符出現n次

            \{n,\}      前一字符至少出現n次

            \(\)        保留(復制)後向引用

    次數匹配(擴展)    +       至少出現1次

            ?       出現0次或1次

            {n}         出現n次

            {n,}        至少出現n次  

            {n,m}       出現n到m次

            {0,m}       至多出現m次

    位置錨定        ^       匹配行首(以什麽開頭)

            $       匹配行尾(以什麽結尾)

            \>      詞尾  

            \<      詞首          

            \b(擴展)  單詞邊界

            ^$

            ^[[:space:]]*$ 

    後向引用        ()      組合為整體,保留(復制)

    分組(復制)  ( )復制   \1 \2 \3 粘貼

            \B      匹配非單詞邊界“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。

            ?       當該字符緊跟在任何一個其他限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的

                    非貪婪模式盡可能少地匹配所搜索的字符串,而默認的貪婪模式則盡可能多地匹配所搜索的字符串

                    例如,對於字符串“oooo”,“o+”將盡可能多地匹配“o”,得到結果[“oooo”]

                    而“o+?”將盡可能少地匹配“o”,得到結果 [‘o‘, ‘o‘, ‘o‘, ‘o‘]

正則表達式過濾案例:

        egrep -c ‘/sbin/nologin$‘ /etc/passwd = egrep ‘/sbin/nologin$‘ /etc/passwd | wc -l  內置了統計功能

        egrep -vc ‘/sbin/nologin$‘ /etc/passwd  

        egrep -cv ‘.‘ /etc/rc.local 統計空行

        egrep -c ‘^$‘ /etc/rc.local 統計空行

        egrep -c ".*" /etc/httpd/conf/httpd.conf      //總行數

        egrep -c "#" /etc/httpd/conf/httpd.conf   //含註釋的行數

        egrep -c -v ‘#|^$‘  /etc/httpd/conf/httpd.conf  有效配置行(多數配置文件適用)

        egrep -v ‘#|^$‘  /etc/httpd/conf/httpd.conf > httpd.conf.min 保存有效配置行

        egrep  ‘^ .+|^[^#]‘ test5-19-1.sh  腳本裏真正的有效配置的行?具體情況具體分析啊

        egrep -m 2 ‘/sbin/nologin$‘ /etc/passwd 只顯示匹配到的前2行  

        egrep ‘.*‘ /etc/rc.local 匹配所有

        egrep ‘exec(ution)*‘ /etc/rc.local 包含exec 和execution的行

        ifconfig | egrep ‘[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}‘ 包含MAC地址

         MAC03="20:69:74:R2:C5:27"  

        判斷mac地址是否有效

        echo $MAC03 | egrep -q ‘[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}‘ && echo "有效" || echo "無效"

        過濾有效的郵箱地址

        egrep ‘[0-9a-zA-Z_.]{3,}@[0-9a-zA-Z.-]{2,}(\.[0-9a-zA-Z-]{2,})+‘ mail.txt 

        sort -t: -k3 -n /etc/passwd |tail -1 | cut -d: -f3  UID最大的用戶名

        精確匹配root用戶(3種方式)

        egrep ‘^\broot\b‘ /etc/passwd

        egrep ‘^\<root\>‘ /etc/passwd  

        awk -F: ‘$1=="root"‘ /etc/passwd

        如果root存在顯示它的解釋器

        id root &> /dev/null && egrep ‘^\broot\b‘ /etc/passwd | cut -d: -f7

        id root &> /dev/null && awk -F: ‘$1=="root"{print $NF}‘ /etc/passwd

        egrep ‘\b[0-9]{2,3}\b‘ /etc/passwd  2-3位數字

        某個腳本的有效語句:

        egrep  ‘^[^#]‘ test5-19-1.sh | egrep ‘[^[:space:]]+.*#.*‘ 這個好惱火啊

        egrep  ‘^[^#]|[^[:space:]]+.*#.*‘ test5-19-1.sh 

        用戶名同shell名的:

        egrep ‘(^\b[a-Z0-9]+\b).*\1$‘ /etc/passwd

            sync:x:5:0:sync:/sbin:/bin/sync

            shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

            halt:x:7:0:halt:/sbin:/sbin/halt

            bash:x:1005:1025::/home/bash:/bin/bash

            nologin:x:1008:1028::/home/nologin:/sbin/nologin

        案例:傳遞兩個文件作為參數給腳本計算這兩個文件所有空白行之和  

        k1=$(egrep "^[[:space:]]*$" $1 | wc -l

        k2=$(egrep "^[[:space:]]*$" $2 | wc -l  

        echo "$[k1+k2]" 

        root centos user1用戶的默認shell和uid

        /etc/grub2.cfg文件中某單詞後面跟一個小括號的行

        使用echo輸出一個絕對路徑egrep找出其基名和目錄名

        ifconfig結果中1-255之間的數值(大量用|或者)

        ifconfig結果中的IP地址

文本處理三劍客sed:

    逐行處理軟件 讀一行處理一行 逐行處理讀一行處理一行。

    sed [選項] ‘條件指令‘ 文件

    選項:

            -n 屏蔽默認輸出

            -r 支持擴展正則

            -i 修改源文件

    條件:

        行號  4    4;5  4,5   4,+10  

            4~2(第4行和後面步長為2的行)

            sed -n ‘2~2P‘ sed.txt  偶數行

            sed -n ‘1~2P‘ sed.txt  奇數行  

            sed  -n ‘$=‘ a.txt            //輸出文件的行數

        /正則/

            sed  -n ‘p‘ a.txt            //輸出所有行,等同於cat a.txt

            sed  -n ‘4p‘ a.txt            //輸出第4行

            sed  -n ‘4,7p‘ a.txt        //輸出第4~7行

            sed  -n ‘4,+10p‘ a.txt        //輸出第4行及其後的10行內容

            sed  -n ‘/^bin/p‘ a.txt        //輸出以bin開頭的行

            sed  ‘/xml/!d‘ a.txt         //刪除不包含xml的行,!符號表示取反

            sed  ‘$d‘ a.txt                //刪除文件的最後一行

            sed  ‘/^$/d‘ a.txt             //刪除所有空行

        tips:   sed ‘s/xml//g‘     a.txt     //將所有的xml都刪除(替換為空串)

            sed -n ‘s/2017/xxxx/gp‘ sed.txt //替換所有並打印

            sed ‘s/xml/XML/‘  a.txt        //將每行中第一個xml替換為XML

            sed ‘s/xml/XML/3‘ a.txt     //將每行中的第3個xml替換為XML

            sed ‘s/xml/XML/g‘ a.txt     //將所有的xml都替換為XML

            sed ‘s/xml//g‘     a.txt     //將所有的xml都刪除(替換為空串)

            sed ‘s#/bin/bash#/sbin/sh#‘ a.txt  //將/bin/bash替換為/sbin/sh 

                            (涉及到路徑時用其他符合分隔)

            sed ‘4,7s/^/#/‘   a.txt         //將第4~7行註釋掉(行首加#號)

            sed ‘s/^#an/an/‘  a.txt         //解除以#an開頭的行的註釋(去除行首的#號)

            sed -n ‘s/.//2;s/.$//p‘ sed.txt 刪除文件中每行的第二個、最後一個字

            互換:(後向引用)

            sed -rn ‘s/^(.)(.*)(.)$/\3\2\1/p‘ sed.txt 第一個、倒數第1個字符互換

            sed -rn ‘s/^(.)(.)(.*)(.)(.)$/\1\4\3\2\5/p‘ sed.txt  第二第四互換

            sed ‘s/[0-9]//‘ nssw.txt        刪除文件中所有的數字

            sed -r ‘s/[0-9]//g;s/^( )+//‘ nssw2.txt 刪除所有數字、行首空格

            sed -rn ‘s/([A-Z])/[\1]/gp‘ nssw.txt    為文件中每個大寫字母添加括號

            sed -rn ‘s/([a-Z0-9])/[\1]/gp‘ sed.txt  為文件中每個字母和數字添加括號

            sed -rn ‘s/([a-Z0-9 ])/(\1)/gp‘ sed.txt 為文件中每個字母和數字空格添加括號

    指令:

            p 打印

            d 刪除

            s 替換s/舊/新/g

            a 指定行之後追加    

                sed  ‘2a XX‘   a.txt            //在第二行後面,追加XX

            i 指定行之前插入

                sed  ‘2i XX‘   a.txt            //在第二行前面,插入XX

            c 替換行

                sed  ‘2c XX‘   a.txt            //將第二行替換為XX

                sed  ‘1c mysvr.tarena.com‘ /etc/hostname    修改主機名

    腳本中修改配置文件時:

            cp /etc/vsftpd/vsftpd.conf{,.bak}  給配置文件備份

    /etc/hosts  這個文件非常有用:優先級比dns高 本地解析庫

                sed  -i  ‘$a 192.168.4.20  D  ‘  /etc/hosts

                    這一就可以ssh D 直接遠程這個ip了。

                sed  -i  ‘$a 192.168.4.20  www.baidu.com ‘  /etc/hosts

                    這樣訪問百度就快些了不用去找dns解析了 

文本處理三劍客awk:

    awk [選項] ‘[條件]{指令}‘ 文件      

    多條編輯指令,可用分號分隔

    默認將空格、制表符等作為分隔符             

    (cut sort 也是是默認空格Tab)

    grep sed 不能直接打印某列要結合字符串的截取工具使用

     -F 可指定分隔符  識別多種單個的字符   

        awk -F [:/] ‘{print $1,$10}‘ /etc/passwd

    awk常用內置變量:

        $0 文本當前行的全部內容

        $1  文本的第1列

        $3  文件的第3列,依此類推

        NR  文件當前行的行號

        NF  文件當前行的列數(有幾列

            awk -F: ‘{print NR,NF}‘ passwd.txt

            awk -F: ‘{print NR,$NF}‘ /etc/passwd  永遠打印最後一行!

            awk -F: ‘{print NR,$NR}‘ /etc/passwd  第幾行的時候就打印第幾列!

    可以打印常量:

        awk -F: ‘{print $1,"的解釋器:",$7}‘ /etc/passwd     

            打印常量必須要加雙引號, 加逗號有空格,不加逗號無空格!

        案例: 

            free |awk ‘/Mem/{print $NF}‘    查看目前可用內存

            ifconfig eth0 | awk ‘/RX p/{print $5}‘  查看接收流量!

            ifconfig eth0 | awk ‘/TX p/{print $5}‘  查看發送流量!

            df -h | awk ‘/\/$/{print $4}‘ #:\/$代表對/轉義!!看跟分區可用空間。

            df  | awk ‘/\/$/{print $4}‘  故意不加單位 在腳本中好當成數值比較!!!

            df -h / | tail -1 | awk ‘{print $4}‘ 第一個/ 代表要看/(根)的情況 提取最後一行 給awk

    在網頁中查看腳本:遠程監控服務器網卡 內存等等情況(相當於動態頁面了)

        rpm -qa | grep httpd

        cp /root/share/test5-19-1.sh /var/www/cgi-bin/test5-19-1.html   必須放在腳本專用目錄下

        chmod +x /var/www/cgi-bin/test5-19-1.html   必須要加X不然訪問不了要報404. 看到404就檢查有沒有X

        systemctl stop firewalld

        setenforce 0 

        ip/cgi-bin/test5-19-1.html   訪問驗證!!!

            tips:

                要想使訪問時換行顯示,要在/var/www/cgi-bin/test5-19-1.html 給這個文件加<br>然後再重啟服務!!

                而不是改之前的腳本文件,思路一定要清晰啊小夥子。

            tips:

                如果cp -P test5-19-1.html /var/www/html/

                http://192.168.4.20/test5-19-1.html

                訪問到的就不是腳本執行的結果了,就是html 代碼執行的結果了。如下

                #!/bin/bash echo "Content-type: text/html" echo "" ifconfig eth0 | awk ‘/netmask/{print "Ip:"$2}‘ echo "

                " ifconfig eth0 | awk ‘/RX p/{print "接收流量:"$5}‘ echo "

                " ifconfig eth0 | awk ‘/TX p/{print "發送流量:"$5}‘ echo "

                " df | awk ‘/\/$/{print "根分區可用:"$4}‘ echo "

                " free |awk ‘/Mem/{print "內存可用:"$NF}‘

                路徑一定要是/var/www/cgi-bin/test5-19-1.html 才能訪問到腳步執行結果。(在未修改配置文件前提下)

    格式化輸出:

        awk處理的時機:

            處理第一行之前做準備工作    只做預處理的時候,可以沒有操作文件

                        awk ‘BEGIN{print x+1}‘           #x可以不定義,直接用,默認值位0

            中間進行逐行處理

            處理完最後一行做總結

            awk  [選項]  ‘ BEGIN{指令} {指令} END{指令}‘  文件

                BEGIN{ }    行前處理,讀取文件內容前執行,指令執行1次

                { }     逐行處理,讀取文件過程中執行,指令執行n次

                END{ }      行後處理,讀取文件結束後執行,指令執行1次

                    統計系統中使用bash作為登錄Shell的用戶總個數

                    awk ‘BEGIN{x=0}/bash$/{x++} END{print x}‘ /etc/passwd

                    awk ‘/bash$/{x++} END{print x}‘ /etc/passwd  與上條命令等效 x未定義默認為0

    格式化輸出/etc/passwd    

        awk -F: ‘BEGIN{print "User\tUID\tHome"} 
                            {print $1 "\t"  $3  "\t"  $6}     \     使用“\t”顯示Tab制表位

                            END{print "Total",NR,"lines."}‘ /etc/passwd

        awk -F: ‘BEGIN{print "用戶名   家目錄   UID"} {print $1,$6,$3 x++} END{print "總共"x"行"}‘ /etc/passwd

        awk -F: ‘BEGIN{print "用戶名","家目錄","UID"} {print $1,$6,$3} END{print "總共"NR"行"}‘ /etc/passwd

        awk -F: ‘BEGIN{print "用戶名","家目錄","UID"} {print $1,$6,$3 x++} END{print "總用戶量:"x }‘ /etc/passwd

        END{print "總共"NR"行"}  END{print "總共"x"行"}  打印最後的時候:註意變量不要引號,常量要引號,這是個坑啊!!!      

        awk -F: ‘BEGIN{print "用戶名\t家目錄\tUID"} {print $1"\t"$6"\t"$3 x++}END{print "總用戶量:"x }‘ /etc/passwd | column -t

        column -t 自動排版對齊!!!awk -F: ‘{print $1,$2,$3 }‘ /etc/passwd | column -t

    awk處理條件:

        正則

            awk -F: ‘/bash$/{print}‘ /etc/passwd

            awk -F: ‘$1~/(zhangsan|root)/{print $7}‘ /etc/passwd  (支持擴展的正則)

            ~代表匹配:$1匹配後面的正則。並且是包含就算,模糊匹配 #第一列包含root或zhangsan的打印第7列。

                [root@D share]# awk -F: ‘$1~/^root/‘ /etc/passwd

                root:x:0:0:root:/root:/bin/bash

                roota:x:1004:1024::/home/roota:/bin/bash    模糊匹配

             awk -F: ‘$7!~/nologin$/{print $1,$7}‘ /etc/passwd    !~不匹配

        使用數值/字符串比較設置條件

            比較符號:== != > >= < <=

            awk -F: ‘$1=="root"‘ /etc/passwd   常量要引號  精確匹配用戶是為root的 不包含aroot root arootb 等等。    

            awk -F: ‘NR==3‘   打印第三行 不寫{指令}默認為打印整行(所有列)

            awk -F: ‘$3>=1000‘ /etc/passwd  大於等於1000的都是普通用戶。    

            awk -F: ‘$3>10  && $3<5‘  /etc/passwd  

                tips:帶邏輯判斷的 要寫合理  不然的話不會報錯但是腳本執行結果不對,就不好排錯了。

            seq 100 | awk ‘$1%6!=0‘  不能被6整除的。

        邏輯測試條件      

            seq 100 | awk ‘$1%6==0 && $1%5==0‘      5和6的公倍數。

            seq 100 | awk ‘$1%7==0 || $1~/7/‘   7整除或者包含7

            awk ‘/Failed/ && /invalid/‘ /var/log/secure  

        數學運算

            awk ‘BEGIN{a++;print a}‘  1     

        case:   

            [root@svr5 ~]# cat getupwd-awk.sh

            #/bin/bash

            A=$(awk -F:  ‘/bash$/{print $1}‘ /etc/passwd)        ## 提取符合條件的賬號記錄

            for i in $A

            do

                grep $i /etc/shadow | awk -F: ‘{print $1,"-->",$2}‘                

            done

                awk 命令內部不能直接調用shell中的外部變量 $1==$i 要用-v選項來重新定義調用 很麻煩。

    awk流程控制(if,for,while)

       if判斷:

        單分支:if(判斷){命令}      #第一個{表示命令開始    第二個}代表命令結束

        多分支:if(判斷){命令}else{命令}      #所有指令都要放在{}裏!!!!

        awk -F: ‘{if($3<=1000) {i++}} END{print i} ‘ /etc/passwd   #結構很重要哈!!不行就先把結構框架打出來再往裏面添加數據!!

        awk -F: ‘{if($3<=1000){x++}else{y++}} END{print x,y}‘ /etc/passwd  

       for循環:

        awk數組:

            awk ‘BEGIN{a++;print a}‘  1         未定義的變量對它++就是1!!!!a=a+1 a未出現過,為空 空+1=1

            awk ‘BEGIN{a[0]++;print a[0]}‘

            非常重要:awk ‘BEGIN{a[0]=00;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}‘ 

                    0 0

                    1 11

                    2 22結果證明:i取值不是a的值而是a的下標。a[i]才是數組a的值。

            awk數組的下標除了可以使用數字,也可以使用字符串,字符串需要使用雙引號:

            awk ‘BEGIN{a["192.168.4.254"]=11;print a["192.168.4.254"]}‘  11

            awk ‘BEGIN{a[192.168.4.254]=11;print a[192.168.4.254]}‘  11

        案例:        

            背景:

            awk 統計每一個ip的訪問次數來進行過濾

            ls  -lh /var/log/httpd/access_log   8.5k

            wc -l /var/log/httpd/access_log     31行

            ab -c 100 -n 100000 http://192.168.4.20/    

                dos攻擊:模擬100人訪問了網站10萬次,這時刷新頁面就會很卡。

            tips:如果下標是變量就不能用引號;會把它當字符串的!先不加,結果不對了再加這樣就不會錯了.

            awk ‘{IP["$1"]++}END{for (i in IP) {print IP[i],i}}‘ /var/log/httpd/access_log 

            63445 $1

            awk ‘{IP[$1]++}END{for (i in IP) {print IP[i],i}}‘ /var/log/httpd/access_log |sort -n 從小到大排序

            219 ::1

            63226 192.168.4.254 

awk腳本應用案例:

        案例:

            快速進行源碼包安裝

                yum repolist | awk ‘/repolist/ {print $2}‘ |sed ‘s/,//g‘

                源碼包裝的軟件不能用systemctl restart (enable) 來進行管理。

                netstat -ntulp |grep httpd

        tcp6       0      0 :::80                   :::*                    LISTEN      8002/httpd

                netstat -ntulp |grep :80        

        tcp6       0      0 :::80                   :::*                    LISTEN      8002/httpd

                netstat -ntulp |grep :80

                [ $? -ne 0 ]  && /usr/local/nginx/sbin/nginx

                a=$(netstat -ntulp |awk ‘/:80/{print $7}‘|cut -d/ -f2)

                [ $a == "httpd" ] && systemctl stop $a  

                b=(netstat -ntulp |awk ‘/:80/{print $7}‘|cut -d/ -f2|cut -d: -f1)

            啟動腳本niginx(case)

            看本機狀態信息

                uptime |awk ‘{print$9,$10,$11}
                ifconfig eth0 | awk ‘/RX p/{print $5}‘

                ifconfig eth0 | awk ‘/TX p/{print $5}‘

                free |awk ‘/Mem/{print $NF}‘

                df | awk ‘/\/$/{print $4}‘

                cat /etc/passwd |wc -l

                who |wc -l

                rpm -qa |wc -l

            $!最後一個後臺進程的進程號。   

            防止遠程ssh暴力破解密碼

            awk ‘/Failed/ && /invalid/{print $13}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘

            awk ‘/Failed/ && $9!~/invalid/{print $11}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘

          1 #!/bin/bash

          2 a=$(awk ‘/Failed/ && $9!~/invalid/{print $11}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘|awk ‘{if($2>5){print$1}}‘)

          3 

          4 b=$(awk ‘/Failed/ && $9!~/invalid/{print $11}‘ /var/log/secure |awk ‘{a[$1]++}END{for (i in a){print i,a[i]}}‘|awk ‘{if($2>5){print$1}}‘)

          5 echo $a

          6 echo $b

Linux階段總結shell腳本