1、检测两台服务器指定目录下的文件一致性
#!/bin/bash
检测两台服务器指定目录下的文件一致性
dir = /data/web
b_ip = 192.168 .88.10
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
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 }' `
if [ $md5_a != $md5_b ] then
echo "$f changed."
fi
else
echo "$f deleted."
fi
done
2、定时清空文件内容,定时记录文件大小
#!/bin/bash
每小时执行一次脚本(任务计划),当时间为0点或12点时,将目标目录下的所有文件内
logfile = /tmp/` date +%H-%F` .log
n = ` date +%H`
if [ $n -eq 00 ] || [ $n -eq 12 ]
then
for i in ` find /data/log/ -type f`
do
true > $i
done
else
for i in ` find /data/log/ -type f`
do
du -sh $i >> $logfile
done
fi
3、检测网卡流量,并按规定格式记录在日志中
#!/bin/bash
while :
do
LANG = en
logfile = /tmp/` date +%d` .log
exec >> $logfile
date +"%F %H:%M"
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 "####################"
done
4、计算文档每行出现的数字个数,并计算整个文档的数字总数
#!/bin/bash
n = ` wc -l a.txt| awk '{print $1 }' `
sum = 0
for i in ` seq 1 $n` do
line = ` sed -n "$i " p a.txt`
n_n = ` echo $line| sed s'/[^0-9]//' g| wc -L`
echo $n_nsum = $[ $sum +$n_n ]
done
echo "sum:$sum "
#!/bin/bash
ps aux| grep 指定进程名| grep -v grep | awk '{print $2 }' | xargs kill -9
5、从 FTP 服务器下载文件
#!/bin/bash
if [ $# -ne 1 ] ; then
echo "Usage: $0 filename"
fi
dir = $( dirname $1)
file = $( basename $1)
ftp -n -v << EOF
open 192.168.1.10 # ftp服务器
user admin password
binary # 设置ftp传输模式为二进制,避免MD5值不同或.tar.gz压缩包格式错误
cd $dir
get "$file "
EOF
6、连续输入5个100以内的数字,统计和、最小和最大
#!/bin/bash
COUNT = 1
SUM = 0
MIN = 0
MAX = 100
while [ $COUNT -le 5 ] ; do
read -p "请输入1-10个整数:" INT
if [ [ ! $INT = ~ ^[ 0 -9] +$ ] ] ; then
echo "输入必须是整数!"
exit 1
elif [ [ $INT -gt 100 ] ] ; then
echo "输入必须是100以内!"
exit 1
fi
SUM = $(( $SUM+ $INT))
[ $MIN -lt $INT ] && MIN = $INT
[ $MAX -gt $INT ] && MAX = $INT
let COUNT++
done
echo "SUM: $SUM "
echo "MIN: $MIN "
echo "MAX: $MAX
#!/bin/bash # 脚本生成一个 100 以内的随机数,提示用户猜数字,根据用户的输入,提示用户猜对了,
while :
do
read -p "计算机生成了一个 1‐100 的随机数,你猜: " cai
if [ $cai -eq $num ]
then
echo "恭喜,猜对了"
exit
elif [ $cai -gt $num ]
then
echo "Oops,猜大了"
else
echo "Oops,猜小了"
fi
done
7、监测 Nginx 访问日志 502 情况,并做相应动作
假设服务器环境为 lnmp,近期访问经常出现 502 现象,且 502 错误在重启 php-fpm 服务后消失,因此需要编写监控脚本,一旦出现 502 ,则自动重启 php-fpm 服务。
log = /data/log/access.log
N = 30
while :do
err = ` tail -n 300 $log | grep -c '502" ' `
if [ $err -ge $N ]
then
/etc/init.d/php-fpm restart 2 > /dev/null
sleep 60
fi
sleep 10
done
8、将结果分别赋值给变量
for i in $( echo "4 5 6" ) ; do
eval a$i = $idone
echo $a4 $a5 $a6
num = 0
for i in $( eval echo $*) ; do
let num += 1
eval node${num} = "$i "
done
echo $node1 $node2 $node3
192.168 .1.11 192.168 .1.12
arr = ( 4 5 6 )
INDEX1 = $( echo ${ arr[ 0 ] } )
INDEX2 = $( echo ${ arr[ 1 ] } )
INDEX3 = $( echo ${ arr[ 2 ] } )
9、批量修改文件名
目的:把article改为bbs
方法1:
for file in $( ls *html) ; do
mv $file bbs_${file# *_}
方法2:
for file in $( find . -maxdepth 1 -name "*html" ) ; do
mv $file bbs_${file# *_} done
方法3:
把一个文档前五行中包含字母的行删掉,同时删除6到10行包含的所有字母
1 )准备测试文件,文件名为2.txt
第1行1234567不包含字母
第2行56789BBBBBB
第3行67890CCCCCCCC
第4行78asdfDDDDDDDDD
第5行123456EEEEEEEE
第6行1234567ASDF
第7行56789ASDF
第8行67890ASDF
第9行78asdfADSF
第10行123456AAAA
第11行67890ASDF
第12行78asdfADSF
第13行123456AAAA
2 )脚本如下:
把一个文档前五行中包含字母的行删掉,同时删除6到10行包含的所有字母
sed -n '1,5' p 2 .txt | sed '/[a-zA-Z]/' d
sed -n '6,10' p 2 .txt | sed s'/[a-zA-Z]//' g
sed -n '11,$' p 2 .txt
10、统计当前目录中以.html结尾的文件总大
方法1:
方法2:
```bash
for size in $( ls -l *.html | awk '{print $5 }' ) ; do
sum = $(( $sum+ $size))
done
echo $sum
11、扫描主机端口状态
#!/bin/bash
HOST = $1
PORT = "22 25 80 8080"
for PORT in $PORT ; do
if echo &> /dev/null > /dev/tcp/$HOST /$PORT ; then
echo "$PORT open"
else
echo "$PORT close"
fi
done
用 shell 打印示例语句中字母数小于6的单词
for s in Bash also interprets a number of multi-character options.
do
n = ` echo $s| wc -c`
if [ $n -lt 6 ]
then
echo $s
fi
done
12、输入数字运行相应命令
#!/bin/bash
echo "*cmd menu* 1-date 2-ls 3-who 4-pwd 0-exit "
while :
do
read -p "please input number :" n
n1 = ` echo $n| sed s'/[0-9]//' g`
if [ -z "$n " ]
then
continue
fi
if [ -n "$n1 " ]
then
exit 0
fi
break
done
case $n in
1 )
date
; ;
2 )
ls
; ;
3 )
who
; ;
4 )
pwd
; ;
0 )
break
; ;
*)
echo "please input number is [1-4]"
esac
13、Expect 实现 SSH 免交互执行命令
Expect是一个自动交互式应用程序的工具,如telnet,ftp,passwd等。
需先安装expect软件包。
方法1:EOF标准输出作为expect标准输入
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:
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}
}"
方法3:将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
执行命令脚本:写个循环可以批量操作多台服务器
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
Linux主机SSH连接信息:
192.168 .1.120 root 123456
创建10个用户,并分别设置密码,密码要求10位且包含大小写字母以及数字,最后需要把每个用户的密码存在指定文件中
``` bash
for u in ` seq -w 0 09` do
useradd user_$u
p = ` mkpasswd -s 0 -l 10 `
echo $p | passwd --stdin user_$u
echo -e "$p \n $p " | passwd user_$u
echo "user_$u $p " >> /tmp/userpassworddone
14、监控 httpd 的进程数,根据监控情况做相应处理
#!/bin/bash
check_service ( )
{
j = 0
for i in ` seq 1 5 `
do
/usr/local/apache2/bin/apachectl restart 2 > /var/log/httpderr.log
if [ $? -eq 0 ] then
break
else
j = $[ $j +1] fi
if [ $j -eq 5 ] then
mail.py exit
fi
done } while :do
n = ` pgrep -l httpd| wc -l`
if [ $n -gt 500 ] then
/usr/local/apache2/bin/apachectl restart
if [ $? -ne 0 ]
then
check_service
else
sleep 60
n2 = ` pgrep -l httpd| wc -l`
if [ $n2 -gt 500 ]
then
mail.py exit
fi
fi
fi
sleep 10done
15、批量修改服务器用户密码
Linux主机SSH连接信息:旧密码
192.168 .18.217 root 123456 22
192.168 .18.218 root 123456 22
内容格式:IP User Password Port
SSH远程修改密码脚本:新密码随机生成
https://www.linuxprobe.com/books
OLD_INFO = old_pass.txt
NEW_INFO = new_pass.txt
for IP in $( awk '/^[^#]/{print $1 }' $OLD_INFO) ; do
USER = $( awk -v I = $IP 'I==$1 {print $2 }' $OLD_INFO)
PASS = $( awk -v I = $IP 'I==$1 {print $3 }' $OLD_INFO)
PORT = $( awk -v I = $IP 'I==$1 {print $4 }' $OLD_INFO)
NEW_PASS = $( mkpasswd -l 8 )
echo "$IP $USER $NEW_PASS $PORT " >> $NEW_INFO
expect -c "
spawn ssh -p$PORT $USER @$IP
set timeout 2
expect {
\" (yes/no)\" {send \" yes\r \" ;exp_continue}
\" password:\" {send \" $PASS \r \" ;exp_continue}
\" $USER @*\" {send \" echo \'$NEW_PASS \' |passwd --stdin $USER \r exit\r \" ;exp_continue}
}"
done
生成新密码文件:
192.168 .18.217 root n8wX3mU% 22
192.168 .18.218 root c87; ZnnL 22
16、iptables 自动屏蔽访问网站频繁的IP
场景:恶意访问,安全防范
1 )屏蔽每分钟访问超过200的IP
方法1:根据访问日志(Nginx为例)
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}' )
for IP in $ABNORMAL_IP ; do
if [ $( iptables -vnL | grep -c "$IP " ) -eq 0 ] ; then
iptables -I INPUT -s $IP -j DROP fidone
方法2:通过TCP建立的连接
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}' )
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获取登录状态:
DATE = $( date +"%a %b %e %H:%M" )
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 fidone
方法2:通过日志获取登录状态
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
17、根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
#!/bin/bash
logfile = /data/log/access.log
d1 = ` date -d "-1 minute" +%H%M`
d2 = ` date +%M`
ipt = /sbin/iptables
ips = /tmp/ips.txt
block ( )
{
grep '$d1 :' $logfile | awk '{print $1 }' | sort -n| uniq -c| sort -n > $ips
for i in ` awk '$1 >100 {print $2 }' $ips`
do
$ipt -I INPUT -p tcp --dport 80 -s $i -j REJECT
echo "` date +%F-%T` $i " >> /tmp/badip.log
done
}
unblock ( )
{
for a in ` $ipt -nvL INPUT --line-numbers | grep '0.0.0.0/0' | awk '$2 <10 {print $1 }' | sort -nr`
do
$ipt -D INPUT $a
done
$ipt -Z
}
if [ $d2 -eq "00" ] || [ $d2 -eq "30" ]
then
unblock
block
else
block
fi
18、判断用户输入的是否为IP地址
方法1:
function check_ip ( ) {
IP = $1
VALID_CHECK = $( echo $IP| awk -F. '$1 < =255&&$2 <=255&&$3 <=255&&$4 <=255{print "yes"}' )
if echo $IP | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null; then
if [ $VALID_CHECK == "yes" ] ; then
echo "$IP available."
else
echo "$IP not available!"
fi
else
echo "Format error!"
fi
}
check_ip 192.168 .1.1
check_ip 256.1 .1.1
方法2:
function check_ip ( ) {
IP = $1
if [ [ $IP = ~ ^[ 0 -9] { 1,3 } \ .[ 0 -9] { 1,3 } \ .[ 0 -9] { 1,3 } \ .[ 0 -9] { 1,3 } $ ] ] ; then
FIELD1 = $( echo $IP| cut -d. -f1)
FIELD2 = $( echo $IP| cut -d. -f2)
FIELD3 = $( echo $IP| cut -d. -f3)
FIELD4 = $( echo $IP| cut -d. -f4)
if [ $FIELD1 -le 255 -a $FIELD2 -le 255 -a $FIELD3 -le 255 -a $FIELD4 -le 255 ] ; then
echo "$IP available."
else
echo "$IP not available!"
fi
else
echo "Format error!"
fi
}
check_ip 192.168 .1.1
check_ip 256.1 .1.1
增加版:
加个死循环,如果IP可用就退出,不可用提示继续输入,并使用awk判断。
function check_ip ( ) {
local IP = $1
VALID_CHECK = $( echo $IP| awk -F. '$1 < =255&&$2 <=255&&$3 <=255&&$4 <=255{print "yes"}' )
if echo $IP | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null; then
if [ $VALID_CHECK == "yes" ] ; then
return 0
else
echo "$IP not available!"
return 1
fi
else
echo "Format error! Please input again."
return 1
fi
}
while true ; do
read -p "Please enter IP: " IP
check_ip $IP
[ $? -eq 0 ] && break || continue
done