Shell腳本實戰分享:讓你的工作效率翻倍
在工作中,我們經常需要使用一些自動化工具來提高工作效率。其中,Shell腳本是一種非常實用的工具,可以幫助我們快速完成各種任務。今天,我來分享一些常用的Shell腳本,希望對大家有所幫助。
1.檢測兩臺服務器指定目錄下的文件一致性
這個腳本可以用于比較兩個服務器上的指定目錄是否一致。通過比較文件的文件的MD5值,可以快速發現兩個服務器之間的差異。
#!/bin/bash
######################################
檢測兩臺服務器指定目錄下的文件一致性
#####################################
#通過對比兩臺服務器上文件的md5值,達到檢測一致性的目的
dir=/data/web
b_ip=192.168.88.10
#將指定目錄下的文件全部遍歷出來并作為md5sum命令的參數,進而得到所有文件的md5值,并寫入到指定文件中
find $dir -type f|xargs md5sum > /tmp/md5_a.txt
ssh $b_ip"find $dir -type f|xargs md5sum > /tmp/md5_b.txt"
scp $b_ip:/tmp/md5_b.txt /tmp
#將文件名作為遍歷對象進行一一比對
for f in `awk '{print 2} /tmp/md5_a.txt'`do
#以a機器為標準,當b機器不存在遍歷對象中的文件時直接輸出不存在的結果
if grep -qw "$f" /tmp/md5_b.txt
then
md5_a=`grep -w "$f" /tmp/md5_a.txt|awk '{print 1}'`
md5_b=`grep -w "$f" /tmp/md5_b.txt|awk '{print 1}'`
#當文件存在時,如果md5值不一致則輸出文件改變的結果
if [ $md5_a != $md5_b ]then
echo"$f changed."
fi
else
echo"$f deleted."
fi
done
2.檢測網卡流量,并按規定格式記錄在日志中
該腳本是通過執行sar命令,把服務器的網卡信息收集起來,可以通過該腳本把網卡的流量做成圖表可視化的界面:
#!/bin/bash
#######################################################
#檢測網卡流量,并按規定格式記錄在日志中#規定一分鐘記錄一次
#日志格式如下所示:
#2019-08-12 20:40
#ens33 input: 1234bps
#ens33 output: 1235bps
######################################################3
while :
do
#設置語言為英文,保障輸出結果是英文,否則會出現bug
LANG=en
logfile=/tmp/`date +%d`.log
#將下面執行的命令結果輸出重定向到logfile日志中
exec >> $logfile
date +"%F %H:%M"
#sar命令統計的流量單位為kb/s,日志格式為bps,因此要*1000*8
sar -n DEV 1 59|grep Average|grep ens33|awk '{print $2,"\t","input:","\t",$5*1000*8,"bps","\n",$2,"\t","output:","\t",$6*1000*8,"bps"}'
echo"####################"
#因為執行sar命令需要59秒,因此不需要sleep
done
3.監測 Nginx 訪問日志 502 情況,并做相應動作
假設服務器環境為 lnmp,近期訪問經常出現 502 現象,且 502 錯誤在重啟 php-fpm 服務后消失,因此需要編寫監控腳本,一旦出現 502,則自動重啟 php-fpm 服務。
#場景:
#1.訪問日志文件的路徑:/data/log/access.log
#2.腳本死循環,每10秒檢測一次,10秒的日志條數為300條,出現502的比例不低于10%(30條)則需要重啟php-fpm服務
#3.重啟命令為:/etc/init.d/php-fpm restart
#!/bin/bash
###########################################################
#監測Nginx訪問日志502情況,并做相應動作
###########################################################
log=/data/log/access.log
N=30 #設定閾值
while :do
#查看訪問日志的最新300條,并統計502的次數
err=`tail -n 300 $log |grep -c '502" '`
if [ $err -ge $N ]
then
/etc/init.d/php-fpm restart 2> /dev/null
#設定60s延遲防止腳本bug導致無限重啟php-fpm服務
sleep 60
fi
sleep 10
done
4.掃描主機端口狀態
在日常的工作中,通常需要掃描主機開放了哪些端口,進而作出合理的安全規劃,通過以下的腳本,可以大大提高效率
#!/bin/bash
# 檢查參數數量
if [ "$#" -ne 2 ]; then
echo"用法:$0 <IP地址> <端口號>"
exit 1
fi
IP="$1"
PORT="$2"
# 使用nc (netcat) 命令掃描端口
nc -z -v -w5 "$IP""$PORT" > /dev/null 2>&1
# 根據nc命令的返回值判斷端口狀態
if [ $? -eq 0 ]; then
echo"端口 $PORT 是開放的"
else
echo"端口 $PORT 是關閉的"
fi
將此腳本保存為scan_port.sh,并確保它具有可執行權限(使用chmod +x scan_port.sh)。然后,您可以通過提供目標IP地址和端口號來運行此腳本,例如:
./scan_port.sh 192.168.1.1 80
5.Expect 實現 SSH 免交互執行命令
Expect是一個自動交互式應用程序的工具,如telnet,ftp,passwd等。
需先安裝expect軟件包
方法1:EOF標準輸出作為expect標準輸入
#!/bin/bash
USER=root
PASS=123.com
IP=192.168.1.120
expect << EOFset timeout 30spawn ssh $USER@$IP expect { "(yes/no)" {send "yes\r"; exp_continue} "password:" {send "$PASS\r"}
}
expect "$USER@*" {send "$1\r"}
expect "$USER@*" {send "exit\r"}
expect eof
EOF
方法2:
#!/bin/bash
USER=root
PASS=123.com
IP=192.168.1.120
expect -c "
spawn ssh $USER@$IP
expect {
\"(yes/no)\" {send \"yes\r\"; exp_continue}
\"password:\" {send \"$PASS\r\"; exp_continue}
\"$USER@*\" {send \"df -h\r exit\r\"; exp_continue}
}"
將expect腳本獨立出來
登錄腳本:
# cat login.exp
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set passwd [lindex $argv 2]
set cmd [lindex $argv 3]
if { $argc != 4 } {
puts "Usage: expect login.exp ip user passwd"
exit 1
}
set timeout 30
spawn ssh $user@$ip
expect {
"(yes/no)" {send "yes\r"; exp_continue}
"password:" {send "$passwd\r"}
}
expect "$user@*" {send "$cmd\r"}
expect "$user@*" {send "exit\r"}
expect eof
執行命令腳本:寫個循環可以批量操作多臺服務器:
#!/bin/bash
HOST_INFO=user_info.txt
for ip in $(awk '{print $1}'$HOST_INFO)
do
user=$(awk -v I="$ip"'I==$1{print $2}'$HOST_INFO)
pass=$(awk -v I="$ip"'I==$1{print $3}'$HOST_INFO)
expect login.exp $ip$user$pass$1
done
user_info.txt的內容格式如下:192.168.1.120 root 123456
6.iptables 自動屏蔽訪問網站頻繁的IP
場景:惡意訪問,安全防范
(1) 屏蔽每分鐘訪問超過200的IP
方法1:根據訪問日志(Nginx為例)
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
ABNORMAL_IP=$(tail -n5000 access.log |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>100)print i}')
#先tail防止文件過大,讀取慢,數字可調整每分鐘最大的訪問量。awk不能直接過濾日志,因為包含特殊字符。
for IP in$ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
方法2:通過TCP建立的連接
#!/bin/bash
ABNORMAL_IP=$(netstat -an |awk '$4~/:80$/ && $6~/ESTABLISHED/{gsub(/:[0-9]+/,"",$5);{a[$5]++}}END{for(i in a)if(a[i]>100)print i}')
#gsub是將第五列(客戶端IP)的冒號和端口去掉
for IP in$ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
(2) 屏蔽每分鐘SSH嘗試登錄超過10次的IP
方法1:通過lastb獲取登錄狀態:
#!/bin/bash
DATE=$(date +"%a %b %e %H:%M") #星期月天時分 %e單數字時顯示7,而%d顯示07
ABNORMAL_IP=$(lastb |grep "$DATE" |awk '{a[$3]++}END{for(i in a)if(a[i]>10)print i}')for IP in$ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done
方法2:通過日志獲取登錄狀態
#!/bin/bash
DATE=$(date +"%b %d %H")
ABNORMAL_IP="$(tail -n10000 /var/log/auth.log |grep "$DATE" |awk '/Failed/{a[$(NF-3)]++}END{for(i in a)if(a[i]>5)print i}')"
for IP in$ABNORMAL_IP; do
if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
iptables -A INPUT -s $IP -j DROP
echo"$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log
fi
done
anyway,以上是關于日常工作中常用的腳本分享。