天天看點

08·Shell程式設計-循環

  • 循環的基本概述
    • 循環分類
    • while循環介紹
    • until循環(忘記)
    • for循環
  • 循環控制語句
    • break 跳出循環
    • continue 跳出循環
  • 循環讀取檔案内容
  • 日志分析案例
  • 面試題案例
-曾老濕, 江湖人稱曾老大。

-多年網際網路運維工作經驗,曾負責過大規模叢集架構自動化運維管理工作。

-擅長Web叢集架構與自動化運維,曾負責國内某大型金融公司運維工作。

-devops項目經理兼DBA。

-開發過一套自動化運維平台(功能如下):

1)整合了各個公有雲API,自主建立雲主機。

2)ELK自動化收集日志功能。

3)Saltstack自動化運維統一配置管理工具。

4)Git、Jenkins自動化代碼上線及自動化測試平台。

5)堡壘機,連接配接Linux、Windows平台及日志審計。

6)SQL執行及審批流程。

7)慢查詢日志分析web界面。

循環的基本概述

循環分類

循環名稱 循環含義 使用場景
while循環 當型循環 死循環/有條件的循環/一行一行的讀取檔案
do until循環 直到型循環,一直循環直到不滿足條件 沒啥場景,因為有for循環
for循環 通用型 很多場景都可以使用

while循環介紹

while循環文法
while <條件表達式>;do
  cmd1
  cmd2
done

while <條件表達式>
do
  cmd1
  cmd2
done

while 沒有女朋友;do
  找到死
done

while 話費充足;do
  打電話
done

## 死循環
while true;do
  echo 'hei hei hei'
done

while [ 1 -eq 1 ];do 
  echo 'hei hei hei'
done

while :;do
  echo 'hei hei hei'
done           

複制

使用while模拟seq
#!/bin/bash

i=1
while [ $i -le 10 ];do
    echo $i
    ((i++))
done

[root@zabbix01 ~]# sh seq.sh
1
2
3
4
5
6
7
8
9
10           

複制

使用while從1加到100
#!/bin/bash

i=1
num=0
while [ $i -le 100 ];do
  ((num=num+i))
  ((i++))
done

echo $num


## 如果你對指令很精通,那麼其實一條指令可以完成這個循環。

[root@zabbix01 ~]# echo {1..100}|tr ' ' '+'|bc
5050

[root@zabbix01 ~]# seq -s+ 100|bc
5050

[root@zabbix01 ~]# seq 100|awk '{sum=sum+$1}END{print sum}'
5050

[root@zabbix01 ~]# awk 'BEGIN{for(i=1;i<=100;i++)sum=sum+i;print sum}'
5050           

複制

until循環(忘記)

until循環文法

until 循環執行一系列指令直至條件為 true 時停止。

until 循環與 while 循環在處理方式上剛好相反。

一般 while 循環優于 until 循環,但在某些時候—也隻是極少數情況下,until 循環更加有用。

until <條件表達式>;do
  cmd1
done


until 話費是否充足;do
  打電話
done           

複制

看一眼,忘了就完事,用不着。

for循環

for循環文法
  • 文法一:

無法指定循環次數,表達式有多少内容就循環多少次

for var in 變量表達式;do
  cmd1
  cmd2
done

for var in 變量表達式
do
  cmd1
  cmd2
done

# 變量表達式:
1.可以是以空格為分隔符的字元串
2.可以是以空格為分隔符的數字
3.可以是數組
4.可以是指令結果
5.可以是檔案内容(但是要注意for并不是按行讀取,如果每一行都沒有空格還行,但是一旦遇到空格就...)

# 例:
## 循環以空格為分隔符的字元串
for name in "zls cls wls";do
  echo $name
done

## 循環以空格為分隔符的數字
for num in 1 2 3 4 5;do
  echo $num
done

for num in {1..10};do
  echo $num
done

for zm in {a..z};do
  echo $zm
done

## 循環數組
array=("zls" "cls" "wls" "boduols")
for str in ${array[@]};do
  echo $str
done

##  循環指令結果
for file in `ls -1 /`;do
  echo $file
done

for text in `cat /etc/passwd`;do
  echo $text
done           

複制

  • 文法二:

可指定循環次數格式

for((i=1;i<=10;i++));do
  echo $i
done           

複制

for也可以無限循環
for (( ; ; ));do
  echo 123
done           

複制

循環控制語句

break 跳出循環

break指令允許跳出所有循環(終止執行後面的所有循環)。

下面的例子中,腳本進入死循環直至使用者輸入數字大于5。要跳出這個循環,傳回到shell提示符下,需要使用break指令。

[root@zabbix01 ~]# vim break.sh
#!/bin/bash

while true;do
  read -p 'Please Input A Number: ' num
  if [ $num -ne 5 ];then
      echo "你輸入的是 $num"
  else
      break
  fi
done


[root@zabbix01 ~]# sh break.sh
Please Input A Number: 1
你輸入的是 1
Please Input A Number: 2
你輸入的是 2
Please Input A Number: 3
你輸入的是 3
Please Input A Number: 4
你輸入的是 4
Please Input A Number: 5           

複制

continue 跳出循環

continue指令與break指令類似,隻有一點差别,它不會跳出所有循環,僅僅跳出目前循環。

#!/bin/bash

while true;do
  read -p 'Please Input A Number: ' num
  if [ $num -ne 5 ];then
      echo "你輸入的是 $num"
  else
      continue
  fi
done

[root@zabbix01 ~]# sh continue.sh
Please Input A Number: 1
你輸入的是 1
Please Input A Number: 2
你輸入的是 2
Please Input A Number: 3
你輸入的是 3
Please Input A Number: 4
你輸入的是 4
Please Input A Number: 5
Please Input A Number: 6
你輸入的是 6
Please Input A Number: 7
你輸入的是 7           

複制

循環讀取檔案内容

while讀取檔案内容
## 方法一:使用exec讀取檔案内容,然後進入while循環
[root@zabbix01 ~]# cat student.txt
曾老濕
蒼井空
武藤蘭
天海翼
西野翔
        
[root@zabbix01 ~]# vim while.sh       

#!/bin/bash

exec < student.txt

while read name;do
  echo $name
  echo "------"
done

[root@zabbix01 ~]# sh while.sh
曾老濕
------
蒼井空
------
武藤蘭
------
天海翼
------
西野翔
------


## 方法二:使用管道符,将檔案内容交給while循環
cat student.txt|while read line_name;do

  echo $line_name
  echo "------"
done

## 方法三:使用标準輸入,将檔案内容交給while循環
#!/bin/bash 

while read name;do
  echo $name
  echo "------"
done < student.txt           

複制

while讀檔案練習

寫一個腳本,讀取下面檔案内容,并算出所有人年齡總和

[root@zabbix01 ~]# cat student.txt
曾老濕 18
蒼井空 20
武藤蘭 33
天海翼 32
西野翔 18           

複制

日志分析案例

寫一個shell腳本,防止DDOS攻擊,先分析日志,監控某一個IP并發連接配接數,若短時内PV達到100門檻值,則調用防火牆指令,封掉該IP。

可以分析nginx日志或者檢視目前網絡連接配接數 ss -ant 或者 netstat -ant

這裡使用一個生産的日志 netstat.log

面試題案例

生成随機檔案名

在指定目錄下,通過随機10個小寫字母,然後生成一個檔案名為:

随機字母_zls.txt

的檔案

生成随機内容的方法

## 方法一:
[root@zabbix01 ~]# openssl rand -base64 10
UUBtKUvUkEfcEw==

## 方法二:
[root@zabbix01 ~]# echo $((RANDOM))|md5sum

## 方法三:
[root@zabbix01 ~]# date +%N|md5sum
3fd3a5c57def5f89481e1961fceb13e8

## 方法四:
tr -cd 'a-zA-Z0-9'</dev/urandom|head -c 10           

複制

批量修改檔案名
# 提示一:變量子串方法
 
 # 提示二:sed awk方法
 
 # 提示三:指令拼接
 
 # 提示四:rename
 rename zls.txt cls.TXT /root/*.txt           

複制

批量建立系統使用者設定8位随機密碼

之前我們使用的awk指令拼接的方式

[root@zabbix01 ~]# seq 5|awk '{print "pass=echo 123|md5sum|cut -c 1-8;useradd zls"$1";echo $pass|tee -a /tmp/pass.log|passwd --stdin zls"$1}'           

複制

掃描網段内,存活的主機

現在我們要模拟黑客,來掃描,指定網段記憶體活的主機

## 方法一:在沒有學習任何攻防指令的情況下,我們可以使用for循環
for n in `seq 255`;do
  ping 10.0.0.$n
done


# 優化

for n in `seq 255`;do
  ping -c1 -W1 -i1 10.0.0.$n &>/dev/null
  if [ $? -eq 0 ];then
    echo 10.0.0.$n is ok
  fi
done

## 專業點
. /etc/init.d/functions

for n in `seq 255`;do
{
  ping -c1 -W1 -i1 10.0.0.$n &>/dev/null
  if [ $? -eq 0 ];then
    action 10.0.0.$n /bin/true
  fi
} &
done

# 并發執行
for n in `seq 255`;do
{
  ping -c1 -W1 -i1 10.0.0.$n &>/dev/null
  if [ $? -eq 0 ];then
    echo 10.0.0.$n is ok
  fi
} &
done

## 并發執行bug解決
. /etc/init.d/functions

for n in `seq 255`;do
{
  ping -c1 -W1 -i1 10.0.0.$n &>/dev/null
  if [ $? -eq 0 ];then
    action 10.0.0.$n /bin/true
  fi
} &
usleep 200
done

## 方法二:nmap  簡單粗暴
nmap 10.0.0.0/24
nmao -n -sn 10.0.0.0/24           

複制

歡迎界面優化

figlet

[root@zabbix01 ~]# figlet zls

[root@zabbix01 ~]# showfigfonts

[root@zabbix01 ~]# figlet zls -f banner

[root@zabbix01 ~]# watch -n1 "date +%D%n%T|figlet -k"           

複制