1 shell腳本基礎知識
1.1 目錄
- 函數及實戰
- 函數的語法
- 函數的執行
- 函數實戰
- for循環語句及實戰
- for循環語法結構
- for循環案例實戰
- while和until循環語句及實戰
- while循環語法結構
- until循環語法結構
- while循環和until循環的區別
- while循環按行讀取文件的方法總結
- while循環案例實戰
- select 循環語句及實戰
- select循壞語法結構
- select循壞案例實戰
- 循環控制及狀態返回值實戰
- break、continue、exit、return
- 數組及實戰
- 什麼是shell數組
- 數組的定義
- 數組的調用
- 數組的打印及輸出
- 數組案例實戰
1.2 函數及實戰
1.2.1 函數的語法
方法一:
function 函數名()
{
函數體
}
方法二:
函數名()
{
函數體
}
1.2.2 函數的執行
1.無參數函數
函數名
2.有參數函數
函數名 參數1 參數2 .....
注:函數參數類似於shell腳本的位置參數,$1-$2分別表示提供給函數的第1個參數到第n個參數
$# 參數個數
$@和$* 爲所有參數列表
$0仍爲父腳本的名稱
1.2.3 函數實戰
案例描述:編寫腳本模擬用戶密碼登錄(用戶名和密碼只能是tom/123),要求:編寫input函數:用於判斷用戶的輸入是否爲空
思路分析:
1.環境準備
2.解決思路
1)編寫輸入函數,結合while實現
2)提示輸入用戶名,如果用戶名不是tom,則提示“用戶不存在”
否則,提示用戶輸入密碼,如果密碼不是123,則提示“密碼錯誤,請重新輸入”
否則,提示“登錄成功”
3.開發腳本
#!/bin/bash
#Author:ZhangMiaomiao
#Blog:http://blog.csdn.net/moledyzhang
#Time:2017-10-10 21:27:24
#Name:login.sh
#Version:V1.0
#Description:
fun_input()
{
input=""
while [ -z $input ]
do
read -p "$1" input
done
echo $input
}
username=`fun_input 請輸入用戶名:`
if [ $username = "tom" ];then
password=`fun_input 請輸入密碼:`
if [ $password != "123" ];then
echo "密碼錯誤,請重新輸入"
else
echo "登錄成功"
fi
else
echo "該用戶不存在"
fi
執行結果:
1.3 for循環語句及實戰
1.3.1 for循環語法結構
1.第一種:變量取值型for循環
for 變量名 in 變量值列表
do
循環體
done
2.第二種:c語言型for循環
for((exp1,exp2,exp3))
do
循環體
done
1.3.2 for循環案例實戰
1.輸出數字系列 1 2 3 4 5
方法一:直接列出元素法
for i in 1 2 3 4 5
do
echo $i
done
方法二:使用{}
for i in {1..5}
do
echo $i
done
方法三:使用seq命令
注:"seq m n" 命令用於產生一個數到另一個數之間所有的整數
for i in `seq 1 5`
do
echo $i
done
2.批量創建用戶tom01到tom10,並設置隨機密碼(要求爲字母和數字的8位組合)
案例分析:
1.環境準備:無
2.思路分析
1).產生數字01到10的方法
方法一:seq -w 01 10
方法二:echo {01..10}
2).創建用戶
useradd 用戶名 3).設置無交互密碼的方法
echo 密碼|passwd --stdin 用戶名
4).產生隨機密碼的方法
echo $RANDOM|md5sum|cut -c 3-10
3.開發腳本
user="tom"
passwfile="/tmp/user.log"
for i in `seq -w 01 10`
do
useradd $user$i #創建用戶
passw=`echo $RANDOM|md5sum|cut -c 3-10 ` #因多次使用隨機數,所以定義變量保存
echo $passw|passwd $user$i --stdin &>/dev/null #設置密碼
echo -e "user:$user$i\tpasswd:$passw">>$passwfile #保存設置的賬號和密碼信息
done
cat $passwfile
執行結果:
1.4 while和until循環語句及實戰
1.4.1 while循環語法結構
while <條件表達式>
do
循環體
done
條件表達式的位置寫true表示條件永遠爲真
1.4.2 until循環語法結構
until <條件表達式>
do
循環體
done
1.4.3 while循環和until循環的區別
while循環是滿足條件進入循環
until循環是滿足條件則退出循環
1.4.4 while循環按行讀取文件的方法總結
方法一:利用for循環和cat結合
for line in `cat FILE`
do
echo $line
done
方法二:使用cat讀取文件,然後通過管道進入while循環處理
cat FILE|while read line
do
操作
done
方法三:在while循環結尾done處通過輸入重定向指定讀取的文件
while read line
do
操作
done < FILE
方法四:採用exec讀取文件,然後進入while循環處理
exec < FILE
while read line
do
echo $line
done
1.4.5 while循環案例實戰
案例描述:編寫一個案例解決防止DDoS攻擊的生產案例。請根據web日誌或系統連接數,監控某個ip的併發連接數,若短時間內pv達到100,即封掉對應的ip
防火牆命令爲:iptables -I INPUT -s IP -j DROP
案例分析:
方法一:分析web日誌(這裏按每小時爲單位進行處理)(實際應用應該根據公司網站業務)
1.環境準備
1)安裝nginx
2)日誌切割,將日誌分成不同的文件
2.分析思路-轉換對應的代碼
1)分析訪問日誌,將ip及對應的次數存入文件
awk '{print $1}' /usr/local/nginx/logs/access.log|grep -v '^$'|sort|uniq -c>/tmp/tmp.log
2)分析文件中的每一行,如果超過100次則封掉
3.開發腳本
file=$1
awk '{print $1}' $1|grep -v '^$'|sort|uniq -c>/tmp/tmp.log #分析切割後的日誌將ip及對應次數存入臨時文件
exec</tmp/tmp.log
while read line
do
ip=`echo $line|awk '{print $2}'`
num=`echo $line|awk '{print $1}'`
if [ $num -gt 100 ] && [ `iptables -L -n|grep "$ip"|wc -l` -lt 1 ];then #封掉大於100次的ip
iptables -s $ip -p tcp -I INPUT -j DROP
echo "$ip is dropped ">/tmp/drop_ip_list_$(date +%F).log #記錄處理日誌
fi
done
執行結果:
方法二:分析網絡連接數
#!/bin/bash
check_ddos(){
netstat -antu|grep ESTABLISHED|awk -F '[ :]+' '{print $6}'|sort|uniq -c > ESTABLISHED.log
[ $? -eq 0 ]&&exec < ESTABLISHED.log||exit 1
while read line
do
pv=`echo $line|awk '{print $1}'`
ip=`echo $line|awk '{print $2}'`
if [ $pv -gt 100 ]&&[ `/etc/init.d/iptables -L -n|grep $ip|wc -l` -gt 0 ];then
iptables -I INPUT -s $ip -j DROP
fi
done
}
main(){
while true
do
check_ddos
sleep 3m
done
}
main
1.5 select 循環語句及實戰
1.5.1 select循環語法結構
select 變量名 [in 菜單值列表]
do
循壞體
done
1.5.2 select循環案例實戰
案例描述:打印選擇菜單,安裝選擇一鍵安裝不同的服務,菜單效果如下:腳本:
select var in "Install lamp" "Install lnmp" "exit"
do
case $var in
"Install lamp")
echo "starting install lamp";;
"Install lnmp")
echo "starting install lnmp";;
"exit")
echo "Bye"
exit;;
*)
echo "input error,must be input {1|2|3}";;
esac
done
1.6 循環控制及狀態返回值實戰
1.6.1 break、continue、exit、return對比
1.7 數組及實戰
1.7.1 什麼是shell數組
簡單說,shell數組就是一個元素集合,它把有限個元素(變量或字符內容)用一個名字來命名,然後對它們進行區分。這個名字就是數組名,用於區分不同內容的編號就被稱爲數組的下標或索引。組成數組的每個變量或字符被稱爲數組的元素。
1.7.2 數組的定義
方法一:
數組名=(值1 值2 值3…)
例子
array=(tom jack rose)空格隔開的字符串依次賦值給數組每個元素
array=([0]=tom [1]=jack [2]=rose [6]=natasha)
方法二:
array=([1]=tom [2]=lucy [3]=alice)
方法三:(下標可以不連續)
array[0]="tom"
array[1]="jack"
array[2]="rose"
array[6]="natasha" 注:7個元素0-6,中間未賦值的爲空
1.7.3 數組的調用
${數組名[下標值]}
在數組中可以使用*或@符號來代替下標,此時*或@爲通配符,所以可以用array[*]或array[@]數組中的所有元素
數組中元素個數:${#array[*]}或者${#array[@]} 注:是非空元素個數
數組中單個元素的長度:${#array[n]},其中n爲元素下標
1.7.4 數組的打印及輸出
1.打印數組元素
3.數組中元素的刪除
4.數組內容的截取和替換 截取
刪除數組元素部分內容
5.數組的刪除
1.7.5 數組案例實戰
案例描述:使用數組方法打印下面這段話中單詞數不大於6的所有單詞
i am a bw teacher welcome to beijing bw
1.解決思路:
1).先將所有單詞存入數組 array=(i am a bw teacher welcome to beijing bw)
2).計算數組中每個元素的長度
3).如果不大於6則打印該單詞
2.開發代碼:
array=(i am a bw teacher welcome to beijing bw)
for word in ${array[*]}
do
if [ ${#word} -lt 6 ];then
echo $word
fi
done
執行結果: