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