shell-循環(huán)語(yǔ)句-for-while

1. shell循環(huán)語(yǔ)句

1.1 for循環(huán)語(yǔ)句

1.1.1 語(yǔ)法

for 變量名  in [ 取值列表 ] 
do 
    循環(huán)體
done

1.1.2 簡(jiǎn)單實(shí)現(xiàn)

for n in 1 2 3 4 5
do
    echo $n
done


for n in `seq 10`                                                                                                        
do
        echo $n
done

1.1.3 舉例

計(jì)算從1加到100之和

for ((i=1;i<=100;i++))
do
    let sum+=i
done
echo $sum

第二種
sum1=0
for i in `seq 100`
do
    let sum1=$sum1+$i
done
echo $sum1

批量創(chuàng)建用戶

#!/bin/sh
for i in `cat user.txt`
do
        id $i &>/dev/null
        if [ $? -ne 0 ];then
           useradd $i
           echo "123"|passwd --stdin $i &>/dev/null
           echo "Create $i OK"
        else
           echo "useradd: $i already exists"
        fi
done

測(cè)試網(wǎng)段ip連通性

[root@shell ~]# cat ping.sh
#!/bin/
#循環(huán)主機(jī)
for i in {1..254}
do       #并發(fā)執(zhí)行
        {   
        IP=10.0.1.$i
        ping -c1 $IP &>/dev/null
        if [ $? -eq 0 ];then
        echo "$IP" >>ip.txt
        fi
        }&
done
   wait 
   echo "獲取在線IP完成"

1.1.4 并行執(zhí)行

&和wait組合可以并行處理,提升效率
串行

[root@shell ~]# cat ping.sh
#!/bin/
#循環(huán)主機(jī)
for i in {1..3}
do       
        IP=10.0.1.$i
        ping -c1 $IP &>/dev/null
        if [ $? -eq 0 ];then
        echo "$IP" >>ip.txt
        fi
done 
   echo "獲取在線IP完成"
======================================
[root@shell ~]# sh -x ping.sh
+ for i in '{1..3}'
+ IP=10.0.1.1
+ ping -c1 10.0.1.1
+ '[' 1 -eq 0 ']'
+ for i in '{1..3}'
+ IP=10.0.1.2
+ ping -c1 10.0.1.2
+ '[' 0 -eq 0 ']'
+ echo 10.0.1.2
+ for i in '{1..3}'
+ IP=10.0.1.3
+ ping -c1 10.0.1.3
+ '[' 1 -eq 0 ']'
+ echo $'\350\216\267\345\217\226\345\234\250\347\272\277IP\345\256\214\346\210\220'
獲取在線IP完成

并行--使用&和wait

[root@shell ~]# cat ping.sh
#!/bin/
#循環(huán)主機(jī)
for i in {1..3}
do       #并發(fā)執(zhí)行
        {   
        IP=10.0.1.$i
        ping -c1 $IP &>/dev/null
        if [ $? -eq 0 ];then
        echo "$IP" >>ip.txt
        fi
        }&
done
   wait 
   echo "獲取在線IP完成"
========================
[root@shell ~]# sh -x ping.sh
+ for i in '{1..3}'
+ for i in '{1..3}'
+ for i in '{1..3}'
+ wait
+ IP=10.0.1.1
+ ping -c1 10.0.1.1
+ IP=10.0.1.2
+ ping -c1 10.0.1.2
+ IP=10.0.1.3
+ ping -c1 10.0.1.3
+ '[' 0 -eq 0 ']'
+ echo 10.0.1.2
+ '[' 1 -eq 0 ']'
+ '[' 1 -eq 0 ']'
+ echo $'\350\216\267\345\217\226\345\234\250\347\272\277IP\345\256\214\346\210\220'
獲取在線IP完成

1.2 while循環(huán)語(yǔ)句

1.2.1 while循環(huán)基礎(chǔ)語(yǔ)法

//當(dāng)條件測(cè)試成立(條件測(cè)試為真),執(zhí)行循環(huán)體
while 條件測(cè)試 
do 
    循環(huán)體 
done
image.png

1.2.2 簡(jiǎn)單練習(xí)

打印10到1 再打印1到10

i=1
while [ $i -le 10 ] 
do
    echo $i
    ((i++))
done
a=10
while [ $a -gt 0 ]
do
    echo $a
    let a-=1                                                                                                             
done 

1.2.3 while讀文件的三種方法

方式1:在while循環(huán)結(jié)尾done通過(guò)輸入重定向指定讀取的文件(推薦)。
while read line
do
    cmd
done<FILE
方式2:使用cat讀取文件內(nèi)容,然后通過(guò)管道進(jìn)入while循環(huán)處理。
cat FILE_PATH|while read line
do
    cmd
done
方式3:采用exec讀取文件后,然后進(jìn)入while循環(huán)處理。
exec <FILE
sum=0
while read line
do
    cmd
done

1.2.4 猜數(shù)游戲

需要用while true死循環(huán)

首先讓系統(tǒng)隨機(jī)生成一個(gè)數(shù)字,給這個(gè)數(shù)字定一個(gè)范圍(1-60),讓用戶輸入猜的數(shù)字,對(duì)輸入進(jìn)行判斷,如果不符合要求,就給予高或低的提示,猜對(duì)后則給出猜對(duì)用的次數(shù),請(qǐng)用while語(yǔ)句實(shí)現(xiàn)。

分析:
1)隨機(jī)數(shù)字定一個(gè)范圍(1-60)
echo $((RANDOM%60)) 執(zhí)行腳本后是固定的,例如;50

2)read -p "輸入猜數(shù)字:" num
把用戶輸入的數(shù)字和已知的隨機(jī)數(shù)比較。

3)連續(xù)猜就需要用while true
random="$((RANDOM%60))"
count=0
while true
do
    read -p "請(qǐng)輸入你猜的數(shù)字: " num
    let count+=1
    if [ $random -gt $num ]
    then
        echo "哥們,猜低了,請(qǐng)繼續(xù)。"
    elif [ $random -eq $num ]
    then
          if [ $count -le 3 ]
          then
              echo "一共用了$count 次,太牛逼了。"
          elif  [ $count -gt 3 ]
          then
            echo "這智商,該學(xué)習(xí)了,一共猜了$count 次"
        fi
        exit 0
    else
        echo "哥們,猜高了,繼續(xù)。"
    fi
done 

用while批量創(chuàng)建用戶

文件中每行只有用戶名
[root@shell scripts]# cat while.sh
#!/bin/bash
while read line
do
        id $line &>/dev/null
        if [ $? -eq 0 ];then
           echo "useradd: user $line already exists"
        else
           useradd $line
           if [ $? -eq 0 ];then
                echo "create $line success"
           fi
        fi
done<user.txt


文件中存在用戶名和密碼
[root@shell scripts]# cat user.txt 
haoge  123
huage  456
zhage  000

第一種
[root@shell scripts]# cat while.sh
#!/bin/bash
#!/bin/sh
while read user
do
        u=$(echo $user|awk '{print $1}')
        p=$(echo $user|awk '{print $2}')
        id $u &>/dev/null
        if [ $? -ne 0 ];then
             useradd $u
             echo $p|passwd --stdin $u &>/dev/null
             echo "Create $u is ok"
        else
             echo "useradd: $u already exists"
        fi
done<user.txt
第二種
[root@shell scripts]# cat while.sh
#!/bin/bash
#!/bin/sh
while read user passwd
do
        id $user &>/dev/null
        if [ $? -ne 0 ];then
             useradd $user
             echo $passwd|passwd --stdin $user &>/dev/null
             echo "Create $user is ok"
        else
             echo "useradd: $user already exists"
        fi
done<user.txt

文件中每行想分成多個(gè)變量,如果文件中的分隔符不是空格建議使用第一個(gè)awk制定分隔符的辦法,
如果是空格分開(kāi)使用第二種比較方便,因?yàn)槁?lián)系的user.txt中用戶和密碼是空格分開(kāi)的,所以兩種都可以。

第二種講解一下
while讀取的文件中每行中每列分隔符是空格可以在while read后面進(jìn)行多個(gè)變量指定

[root@shell scripts]# cat user.txt 
haoge  123
huage  456
zhage  000
[root@shell scripts]# cat test.sh 
#!/bin/sh
while read user passwd
do 
 echo $user
 echo $passwd
done<user.txt
[root@shell scripts]# sh test.sh
haoge
123
huage
456
zhage
000

1.3 循環(huán)控制命令

exit 退出整個(gè)程序
break 結(jié)束當(dāng)前循環(huán),或跳出本層循環(huán)
continue 忽略本次循環(huán)剩余的代碼,直接進(jìn)行下一次循環(huán)


image.png
例如:剛才上面的猜數(shù)游戲就是用到了exit
[root@shell scripts]# cat test.sh 
while true
do
  echo "123"
  exit
  echo "456"
done
echo "done..."
執(zhí)行后的結(jié)果
[root@shell scripts]# sh test.sh 
123

break示例=======================
[root@shell scripts]# cat test.sh 
while true
do
  echo "123"
  break
  echo "456"
done
echo "done..."
執(zhí)行后的結(jié)果
[root@shell scripts]# sh test.sh 
123
done...
continue 示例====================  
[root@shell scripts]# cat test.sh
#!/bin/sh
for i in `seq 5`
do
     if [ $i -eq 2 ]
     then
     echo $i
     else
     continue 
     fi
     echo 'next'
done
[root@shell scripts]# sh test.sh
2
next

1.4 日常練習(xí)題

分析Apache訪問(wèn)日志(access_2010-12-8.log),把日志中每行的訪問(wèn)字節(jié)數(shù)對(duì)應(yīng)字段數(shù)字相加,計(jì)算出總的訪問(wèn)量。給出實(shí)現(xiàn)程序,請(qǐng)用while循環(huán)實(shí)現(xiàn)。

sum=0
while read line
do
    size=`echo $line|awk '{print $10}'|grep -v -`
    let sum+=size
done<$1
echo $sum 

2 expect免交互

2.1 介紹

expect是一款自動(dòng)化的腳本解釋型的工具
腳本開(kāi)頭
expect腳本一般以#!/usr/bin/expect 開(kāi)頭,類似bash腳本。
執(zhí)行腳本不用sh用expect
expect腳本常常以.exp或者.ex結(jié)束。
expect主要命令
?   spawn 新建一個(gè)進(jìn)程,這個(gè)進(jìn)程的交互由expect控制
?   expect 等待接受進(jìn)程返回的字符串,直到超時(shí)時(shí)間,根據(jù)規(guī)則決定下一步操作
?   send 發(fā)送字符串給expect控制的進(jìn)程
?   set 設(shè)定變量為某個(gè)值
?   exp_continue 重新執(zhí)行expect命令分支
?   [lindex $argv 0] 獲取expect腳本的第1個(gè)參數(shù)
?   [lindex $argv 1] 獲取expect腳本的第2個(gè)參數(shù)
?   set timeout -1 設(shè)置超時(shí)方式為永遠(yuǎn)等待
?   set timeout 30 設(shè)置超時(shí)時(shí)間為30秒
?   interact 將腳本的控制權(quán)交給用戶,用戶可繼續(xù)輸入命令
?   expect eof 等待spawn進(jìn)程結(jié)束后退出信號(hào)eof
cat test.sh
#!/usr/bin/expect
spawn ssh root@10.0.1.50

expect {
    "yes/no" { send "yes\r"; exp_continue }
    "password:" { send "123456\r" };
} 
interact

\r 回車符
執(zhí)行
expect test.sh
2.expect定義變量實(shí)現(xiàn)交互方式
#!/usr/bin/expect
set ip 10.0.1.50
set user root
set password 123456
set timeout 5

spawn ssh $user@$ip

expect {
    "yes/no" { send "yes\r"; exp_continue }
    "password:" { send "$password\r" };
} 

密鑰登陸腳本(常用)

#!/bin/bash
pass_word=123456
for IP in `cat $1|grep -v ^#`
do
/usr/bin/expect << EOF
set timeout 15
spawn ssh-copy-id -i $IP
expect {
        "yes/no" { send "yes\r" }
        "password" { send "$pass_word\r" }
        "Password" { send "$pass_word\r" }
        }
        expect eof
EOF
if [ `echo $?` -eq 0 ];
then
        echo "$IP 免密配置成功"
        echo "$IP 免密配置成功" >> $2
else
        echo "$IP 免密配置失敗"
        echo "$IP 免密配置失敗" >> $3
fi
done

這個(gè)使用的是expect<<EOF的方法 所以按正常腳本的格式操作就可以
Paword  paword兩個(gè)匹配的密碼防止有的主機(jī)是大寫帶頭或者小寫開(kāi)頭
$1 表示ip的文件    $2成功的ip    $3失敗的ip

免密登錄(詳細(xì))

#交互方式
interact
案例
批量獲取在線主機(jī), 進(jìn)行秘鑰批量分發(fā)
cat for_ip.sh 
#!/usr/bin/bash
#setup1 拿到IP地址
>ip.txt
for i in {1..10}
do
        ip=10.0.0.$i
        {
        ping -c1 $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo "$ip" >> ip.txt
        fi
        }&
done
#2.生成對(duì)應(yīng)的密鑰
        if [ ! -f ~/.ssh/id_rsa ];then
                ssh-keygen -P "" -f ~/.ssh/id_rsa
        fi

#3.批量分發(fā)密鑰
        while read line
        do
                /usr/bin/expect <<-EOF
                        set pass 1
                        set timeout 2
                        spawn ssh-copy-id  $line -f 
                        expect {
                                "yes/no" { send "yes\r"; exp_continue}
                                "password:" { send "$pass\r"}
                        }
                        expect eof 
                EOF
        done<ip.txt
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容