流程控制
#!/bin/bash
for ((i=1;i
echo $i
done
#cat
cat
while read 读取文件每一行,read a b 可以截取位置变量的列读取 很常用
EOF
cat ./test.txt | while read a b
do
echo $a
echo $b
done
cat
break跳出整个while整个大循环,只能伴随while使用,别的地方无法用break
EOF
i=0
while true
do
let i++
#let i++ c语言风格,每次都给i变量加1
#let i– 每次给变量减1
#let i+=2 每次给变量加2
if [ $i -eq 6 ]
then
break
fi
echo $i
done
cat
跳出当前循环continue,while肯定有多次循环只要满足条件,continue就是跳出其中某一次的当前循环
EOF
#比如打印1235,跳出第四次循环
i=0
while [ $i -lt 6 ]
do
let i++
if [ $i -eq 4 ]
then
continue
fi
echo $i
done
#打印1-20,6不打印
i=0
while true
do
let i+=2
if [ $i -gt 20 ]
then
break
elif [ $i -eq 6 ]
then
continue
fi
echo $i
done
cat
当一个脚本很大,有很多模块脚本集组成,或者有人工交互的不同选择时候,可以选择 case in esac选择性执行部分块命令,实际上就是if的高级功能,但是通过模式传参提供了高级选择的功能,适用于大脚本
linux下很多服务启动脚本安装脚本都是这样写的
case moudle in
moudle1)
脚本集1
;;
moudle2)
脚本集2
;;
*)
不符合以上模式执行的命令
;;
esac
bash 脚本名称 moudle1
EOF
#根据shell的位置参数匹配不同的模式
#$0就是shell脚本自身名字
#$1就是给shell传的第一个位置参数
#$$就是当前进程pid
#$! 上一条运行后台进程的pid
#$? 返上一条命令是否执行正常,0成功 非0失败
case $1 in
moudle1)
模式1脚本”
当前进程为$$”
;;
moudle2)
模式2脚本”
当前进程为$$”
;;
*)
不符合以上模式执行的命令 一般exit给个提示”
echo “USage: $0 {modle1|moudle2}”
;;
esac
cat
select 是一个类似于for循环的语句,传入变量赋值给多个值,提供输入编号对应变量的值.结合case可以做出菜单模式
select 变量 in 选项1 选项2
do
break
done
EOF
#示范1
#select mysql_version in 5.6 5.7
#do
#echo $mysql_version
#done
#示范2 用户输入编号会直接赋值给mysql_version这个变量,假设作为菜单,每个模式执行命令时间很长,循环第二次的时候就不在显示菜单了,不能满足需求,可以写个死循环 每次select一次,就break跳出一次,这样就能每次显示菜单了
cat
while true
do
select mysql_version in 5.6 5.7 8.0
do
echo $mysql_version
break
done
done
EOF
#示范3,结合case形成真正的可视化菜单脚本集,对用户输入的编号执行相应的命令,不用位置变量传参
PS3=”选择执行编号:” #PS3替代select中的#?提示符,更友好
while true
do
select moudle in moudle1 moudle2 quit
do
case $moudle in
moudle1)
执行模块1″
break
;;
moudle2)
执行模块2″
break
;;
quit)
退出”
exit
;;
*)
输入错误,请重新输入”
break
;;
esac
done
done
函数数组
cat
function是shell的函数,和py中函数一样,主要是一个模块的功能方便调用,不用重复编写 也可以进行传参
定义一个函数:
func_函数名(){
命令块
}
执行:直接写函数名func_函数名即可直接调用,不需要加()小括号
EOF
#示例1:
func_demo1(){
echo “这是一个funciton函数”
}
func_demo1
#示例2:函数返回值,return在函数中定义状态返回值,返回并终止函数,类似于exit,但是返回的只能是0-255的数字
func_demo2(){
a=$((1+2))
return $a
}
func_demo2
echo $?
#示例3:通过位置变量给自己传参
func_demo3(){
echo “hellp $1”
}
func_demo3 world
示例4: 函数自己调自己,也就是递归调用.用的比较少
#func_demo4(){
# echo $1
# sleep 1
# func_demo4 hello
#}
#func_demo4
cat
数组是相同类型的元素按一定顺序排列的集合。相当于一个集合
格式:
array=(元素1 元素2 元素3)
定义方法 1:初始化数组,默认以空格分割
array=(a b c)
定义方法 2:新建数组并添加元素
array[下标]=元素
定义方法 3:将命令输出作为数组元素
array=($(command))
EOF
#————————-shell数组之增删改查———————-
array=(aa bb cc) #定义一个数组,array可以是任何一个名字
echo ${array[*]} #*和@都是代表所有元素,获取数组所有元素
echo ${!array[@]} #获取数组所有元素的下标
echo ${#array[*]} #获取数组的长度
echo ${array[0]} #通过下标获取数组的第1个元素
echo ${array[1]} #通过下标获取数组的第2个元素
array[3]=nn #通过下标给数组添加元素
echo ${array[*]}
array+=(dd ee ff) #批量添加数组元素
echo ${array[*]}
unset array[0] #通过下标删除元祖中元素
echo ${array[*]}
unset array #删除整个元祖
#示例1:将seq生成的数字序列放到数组里面
for i in $(seq 1 10)
do
array_demo+=($i)
done
echo ${array_demo[*]}
for i in $(seq 1 10)
do
array_demo1[a]=$i
let a++
done
echo ${array_demo1[*]}
#示例2:遍历数组元素
IP=(192.168.1.1 192.168.1.2 192.168.1.3)
for i in ${IP[*]}
do
echo $i
done
cat
trap命令定义shell脚本在运行时根据接受的信号做相应的处理
trap “arg” single
arg:捕捉信号后执行的命令或者函数
single:信号编号
一般tarp适用的场景如下
1、清除临时文件
2、询问用户是否终止脚本比如按了ctrl+C
3、让用户选择是否终止一些循环
常见的linux进程信号编号 kill命令同样适用
1 SIGHUP 终止 终止进程,挂起
2 SIGINT 终止 键盘输入中断命令,一般是 CTRL+C
9 SIGKILL 终止 立即停止进程,不能捕获,不能忽略
15 SIGTERM 终止 终止信号,进程会先关闭正在运行的任务或打开的文件再终止,有时候有的进程在运行任务会忽略此信号。不能捕捉
18 SIGCONT 可忽略 让终止的进程继续执行
19 SIGSTOP 停止 停止进程,不能忽略,不能捕获
20 SIGSTP 停止 停止进程,一般是 CTRL+Z
EOF
#:
:
#示例1:
trap “” 2 不指定arg命令就是接受信号不执行任何操作,这里就是你按住了ctrl+C也终止不了,直到下面运行结束
for i in {1..5}
do
echo $i
sleep 1
done
#示例2:按住crtl+C退出,并且打印退出提示
trap “echo “您已按住ctrl+C,程序退出”;exit” 2
for i in {1..10}
do
echo $i
sleep 1
done
!
#示例3:在执行一段代码时候 让用户自己选择是否终止循环
trap “func” 2
func() {
read -p “Terminate the process? (Y/N): ” input
if [ $input == “Y” ]; then
exit
fi
}
for i in {1..10}; do
echo $i
sleep 1
done
常用高阶命令
cat
列出常用的一些linux命令都是30年老运维的经验总结
EOF
cat
echo换行
功能:打印一行
常用选项:
-n 不加换行符
-e 解释转义符
EOF
echo -e “1n2n44n555”
cat
rev反向打印每一行
EOF
echo “1234” | rev
cat
tac倒序打印文件每一行
EOF
tac a.txt
cat
dirname:去除文件路径最后一个名字,就是显示上层目录
basename: 打印路径的最后一个名字
EOF
dirname /usr/bin
basename /uar/bin
cat
cut 截取字符串处理
功能:选取文件的每一行数据
常用选项:
-b 选中第几个字符
-c 选中多少个字符
-d 指定分隔符分字段,默认是空格
-f 显示选中字段
EOF
#打印abc的b字符
echo “abc” | cut -b 2
#截取abcdef中的abcd字符
echo “abcdef” | cut -c 1-4
#以冒号分割,显示第二个字符
echo “ab:cd:ef” | cut -d: -f2
cat
tr:替换或者删除字符,很常用
可以对来自标准输入的字符进行替换,删除以及压缩。它可以将一组字符变成另一组字符,因而通常也被称为转换(translate)命令。
格式:Usage: tr [OPTION]… SET1 [SET2]
常用选项:
-c 替换 SET1 没有 SET2 的字符
-d 删除 SET1 中字符
-s 压缩 SET1 中重复的字符
-t 将 SET1 用 SET2 转换,默认
EOF
#去重字符
echo “aaaaabbbbccccdddd” | tr -s ‘[a-z]’
#删除字符
echo “aaaaabbbbcccc” | tr -d bbbb
#转换字符大小写
echo “aaaaaaoooffff” | tr -t ‘[a-z]’ ‘[A-Z]’
cat
seq:序列化打印数字
常用选项:
-f 使用 printf 样式格式
-s 指定换行符,默认是n
-w 等宽,用 0 填充
EOF
#数字序列
seq 3
#范围数字序列
seq 5 9
#步长序列
seq 1 2 5 #2是步长
#以:号分割序列
seq -s “:” 5
cat
shuf:生成随机序列
-i 输出数字范围
-o 结果写入文件
EOF
#输出范围随机数
seq 5 | shuf
shuf -i 5-10
cat
xargs:从标准输入执行命令 很常用很常用
常用选项:
-a file 从指定文件读取数据作为标准输入
-0 处理包含空格的文件名,print0
-d delimiter 分隔符,默认是空格分隔显示
-i 标准输入的结果以{}代替
-I 标准输入的结果以指定的名字代替
-t 显示执行命令
-p 交互式提示是否执行命令
-n 选项多行输出,后面更行数
–show-limits 查看系统命令行长度限制
EOF
#删除/tmp目录下名字是core的文件
find /tmp -name core -type f -print | xargs /usr/bin/rm -rf
#列转行(去除换行符)
cut -d: -f1
#行转列
echo “1 2 3 4 5” | xargs -n1
#最长两列显示
echo “1 2 3 4 5” | xargs -n2
#创建未来十天时间
#清空所有以log结尾的文件中内容,但是保留文件名
find /tmp -name “*.log” |xargs -i tee {} # echo “”> {} 这样不行,>把命令中断了
#删除大量文件
#rm 在删除大量的文件时,会提示参数过长,那么可以使用 xargs 删除:
# ls |xargs rm –rf
#或分配删除 rm [a-n]* -rf # getconf ARG_MAX 获取系统最大参数限制
cat
https://www.cnblogs.com/L-NaNa/p/16495599.html
https://blog.51cto.com/u_15688254/5854536
更好的理解get post这几种请求方法
功能:发送数据到 URL,类似于 HTTP 客户端
常用选项:
-k, –insecure 允许 HTTPS 连接网站
-C, –continue-at 断点续传
-b, –cookie STRING/FILE 从文件中读取 cookie
-c, –cookie-jar 把 cookie 保存到文件
-d, –data 使用 POST 方式发送数据
–data-urlencode POST 的数据 URL 编码
-F, –form 指定 POST 数据的表单
-D, –dump-header 保存头信息到文件
–ftp-pasv 指定 FTP 连接模式 PASV/EPSV
-P, –ftp-port 指定 FTP 端口
-L, –location 遵循 URL 重定向,默认不处理
-l, –list-only 指列出 FTP 目录名
-H, –header 自定义头信息发送给服务器
-I, –head 查看 HTTP 头信息
-o, –output FILE 输出到文件
-#, –progress-bar 显示 bar 进度条
-x, –proxy [PROTOCOL://]HOST[:PORT] 使用代理
-U, –proxy-user USER[:PASSWORD] 代理用户名和密码
-e, –referer 指定引用地址 referer
-O, –remote-name 使用远程服务器上名字写到本地
–connect-timeout 连接超时时间,单位秒
–retry NUM 连接重试次数
–retry-delay 两次重试间隔等待时间
-s, –silent 静默模式,不输出任何内容
-Y, –speed-limit 限制下载速率
-u, –user USER[:PASSWORD] 指定 http 和 ftp 用户名和密码
-T, –upload-file 上传文件
-A, –user-agent 指定客户端信息
EOF
badu.html http://www.baidu.com
不输出下载信息:
# curl -s -o baidu.html http://www.baidu.com
伪装客户端,指定 user-agent 和 referer 下载:
# curl -A “Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/44.0.2403.157 Safari/537.36″ -e “baike.baidu.com” http://127.0.0.1
模拟用户登录,并保存 cookies 到文件:
# curl -c ./cookies.txt -F NAME=user -F PWD=123 http://www.example.com/login.html
使用 cookie 访问:
# curl -b cookies.txt http://www.baidu.com
访问 HTTP 认证页面:
# curl -u user:pass http://www.example.com
FTP 上传文件:
# curl -T filename ftp://user:pass@ip/a.txt
# curl ftp://ip -u user:pass-T filename
FTP 下载文件:
# curl -O ftp://user:pass@ip/a.txt
# curl ftp://ip/filename -u user:pass -o filename
FTP 下载多个文件:
# curl ftp://ip/img/[1,3,5].jpg
查看 HTTP 头信息:
# curl -I http://www.baidu.com
cat
netstat:打印一些socket连接 tcp udp的:
#netstat -anltu
显示所有 TCP 连接:
# netstat -antp
显示所有 UDP 连接:
# netstat -anup
显示路由表:
# netstat -r
显示所有 TCP 连接:
# ss -t -a
显示所有 UDP 连接:
# ss -u –a
显示 socket 使用汇总:
# ss -s
显示所有建立的连接:
# ss -o state established
显示所有的 TIME-WAIT 状态:
# ss -o state TIME-WAIT
搜索所有本地进程连接到 X Server:
# ss -x src /tmp/.X11-unix/*
EOF
常用脚本
看pdf文件即可
————————– 检查网站可用性————————
1)检查 URL 可用性
方法 1:
check_url() {
HTTP_CODE=$(curl -o /dev/null –connect-timeout 3 -s -w “%{http_code}” $1)
if [ $HTTP_CODE -ne 200 ]; then
echo “Warning: $1 Access failure!”
fi
}
方法 2:
check_url() {
if ! wget -T 10 –tries=1 –spider $1 >/dev/null 2>&1; then
#-T 超时时间,–tries 尝试 1 次,–spider 爬虫模式
echo “Warning: $1 Access failure!”
fi
}
使用方法:check_url www.baidu.com
2)判断三次 URL 可用性
思路与上面检查主机存活状态一样。
方法 1:利用循环技巧,如果成功就跳出当前循环,否则执行到最后一行
#!/bin/bash
check_url() {
HTTP_CODE=$(curl -o /dev/null –connect-timeout 3 -s -w “%{http_code}” $1)
if [ $HTTP_CODE -eq 200 ]; then
continue
fi
}
URL_LIST=”www.baidu.com www.agasgf.com”
for URL in $URL_LIST; do
check_url $URL
check_url $URL
check_url $URL
echo “Warning: $URL Access failure!”
done
方法 2:错误次数保存到变量
#!/bin/bash
URL_LIST=”www.baidu.com www.agasgf.com”
for URL in $URL_LIST; do
FAIL_COUNT=0
for ((i=1;i
作者:阿良
HTTP_CODE=$(curl -o /dev/null –connect-timeout 3 -s -w “%{http_code}” $URL)
if [ $HTTP_CODE -ne 200 ]; then
let FAIL_COUNT++
else
break
fi
done
if [ $FAIL_COUNT -eq 3 ]; then
echo “Warning: $URL Access failure!”
fi
done
方法 3:错误次数保存到数组
#!/bin/bash
URL_LIST=”www.baidu.com www.agasgf.com”
for URL in $URL_LIST; do
NUM=1
while [ $NUM -le 3 ]; do
HTTP_CODE=$(curl -o /dev/null –connect-timeout 3 -s -w “%{http_code}” $URL)
if [ $HTTP_CODE -ne 200 ]; then
创建数组,以$NUM 下标,$IP 元素
let NUM++
else
break
fi
done
if [ ${#FAIL_COUNT[*]} -eq 3 ]; then
echo “Warning: $URL Access failure!”
清空数组
fi
done
—————————-检查 MySQL 主从同步状态—————–
#!/bin/bash
USER=bak
PASSWD=123456
IO_SQL_STATUS=$(mysql -u$USER -p$PASSWD -e ‘show slave statusG’ |awk -F:
‘/Slave_.*_Running/{gsub(“: “,”:”);print $0}’) #gsub 去除冒号后面的空格
for i in $IO_SQL_STATUS; do
THREAD_STATUS_NAME=${i%:*}
THREAD_STATUS=${i#*:}
if [ “$THREAD_STATUS” != “Yes” ]; then
echo “Error: MySQL Master-Slave $THREAD_STATUS_NAME status is
$THREAD_STATUS!”
fi
done
———————1 屏蔽网站访问频繁的 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}’)
#先 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:通过建立连接数
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 获取登录状态:
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:通过日志获取登录状态
DATE=$(date +”%b %d %H”)
ABNORMAL_IP=”$(tail -n10000 /var/log/auth.log |grep “$DATE” |awk ‘/Failed/{a[$(NF3)]++}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-loginlimit.log
fi
done
———找出包含关键字的文件 —————-
DIR=$1
KEY=$2
for FILE in $(find $DIR -type f); do
if grep $KEY $FILE &>/dev/null; then
echo “–> $FILE”
fi
done
——–检查mysql数据库备份———–
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=192.168.1.120
DB=test
USER=bak
PASS=123456
MAIL=”zhangsan@example.com lisi@example.com”
BACKUP_DIR=/data/db_backup
SQL_FILE=${DB}_full_$DATE.sql
BAK_FILE=${DB}_full_$DATE.zip
cd $BACKUP_DIR
if mysqldump -h$HOST -u$USER -p$PASS –single-transaction –routines –triggers -B
$DB > $SQL_FILE; then
zip $BAK_FILE $SQL_FILE && rm -f $SQL_FILE
if [ ! -s $BAK_FILE ]; then
内容” | mail -s “主题” $MAIL
fi
else
内容” | mail -s “主题” $MAIL
fi
find $BACKUP_DIR -name ‘*.zip’ -ctime +14 -exec rm {} ;
https://www.cnblogs.com/ollieroad/p/5121719.html反爬虫