虚拟主机怎么做淘客网站,微信小程序制作免费轻站平台,北京微信网站建设报价,简述网站内容如何优化高效编写Bash脚本的技巧
总结了10个实用技巧#xff0c;帮助提高脚本的效率和可靠性#xff0c;具体包括#xff1a; 多写注释#xff1a;在脚本中添加注释#xff0c;以帮助理解脚本的不同部分。 当运行失败时使脚本退出#xff1a;使用set -o errexit或set -e#x…高效编写Bash脚本的技巧
总结了10个实用技巧帮助提高脚本的效率和可靠性具体包括 多写注释在脚本中添加注释以帮助理解脚本的不同部分。 当运行失败时使脚本退出使用set -o errexit或set -e在命令失败时退出脚本。 当Bash用未声明变量时使脚本退出使用set -o nounset或set -u避免使用未声明的变量。 使用双引号来引用变量防止由于空格或通配符导致的不必要匹配。 在脚本中使用函数通过函数使代码模块化提高可读性和可重用性。 字符串比较时用而不是在Bash中和是等价的但推荐使用。 用$(command)而不是反引号command进行命令代换推荐使用$(command)因为它更清晰。 用readonly声明静态变量声明变量为只读防止其值被修改。 环境变量用大写字母命名自定义变量用小写遵循命名约定避免变量名冲突。 总是对长脚本进行调试在脚本执行前进行调试以便于修正错误。 相关例子 多写注释 举例在脚本中添加注释例如
# This script updates the system packages
update_system() {sudo apt-get updatesudo apt-get upgrade -y
} 好处增加代码的可读性便于维护和理解。 问题没有注释的脚本难以理解特别是在团队协作中其他成员可能难以快速上手。 当运行失败时使脚本退出 举例使用set -e来确保脚本在命令失败时立即退出
set -e ./some_command || true # 这个命令失败不会退出脚本 好处防止错误的累积和传播提高脚本的健壮性。 问题不立即退出可能导致后续命令基于错误的前提执行造成更严重的错误。 当Bash用未声明变量时使脚本退出 举例使用set -u来避免使用未声明的变量 set -u
echo $undeclared_var # 这将导致脚本退出 好处避免使用未初始化的变量减少潜在的bug。 问题使用未声明的变量可能导致不可预测的行为或错误的输出。 使用双引号来引用变量 举例使用双引号来防止变量展开或通配符匹配 namesTecMint FOSSMint
echo $names # 正确TecMint FOSSMint
echo $names # 错误可能分割成两个单词 好处确保变量按照预期的方式被引用防止意外的单词分割。 问题不使用双引号可能导致变量值中的空格或特殊字符被错误解释。 在脚本中使用函数 举例将重复的代码块封装成函数 check_root() {if [ $(id -u) ! 0 ]; thenecho This script must be run as root 2exit 1fi
} 好处提高代码的模块化和重用性简化脚本结构。 问题不使用函数可能导致代码重复难以维护和扩展。 字符串比较时用而不是 举例使用单等号进行字符串比较 if [ $value1 $value2 ]; thenecho Values are equal
fi 好处简化语法避免混淆。 问题使用在某些shell中可能不被识别导致语法错误。 哈哈虽然简单场景用 [ ] 和 更保证可移植性和安全性。 但是这个我还是更喜欢用 [[ ]] 和 用$(command)而不是反引号进行命令代换 举例使用$()进行命令替换
user$(whoami) # 正确
userwhoami # 错误不建议使用 好处提高代码的可读性和一致性。 问题反引号在复杂表达式中可能导致错误且不如$()易读。 用readonly声明静态变量 举例使用readonly来防止变量被修改 readonly config_path/etc/config 好处确保配置值在脚本中保持不变防止意外的修改。 问题不声明为只读可能导致变量在脚本中被错误地修改。 环境变量用大写字母命名自定义变量用小写 举例遵循命名约定 export PATH/usr/bin:/bin
local script_path$(dirname $0) 好处避免与系统环境变量冲突提高变量名的可读性。 问题不遵循命名约定可能导致变量名冲突或混淆。 总是对长脚本进行调试 举例使用bash -n script.sh来检查脚本中的语法错误 bash -n my_script.sh 好处提前发现潜在的错误避免在生产环境中出现问题。 问题不进行调试可能导致脚本在实际运行时出现未预料的错误影响系统的稳定性。
遵循这些技巧可以编写出更加健壮、可维护和易于理解的Bash脚本。
用nice指定shell脚本在运行过程中的优先级 在Linux系统中脚本、程序、命令等可能同一时刻需要运行而CPU在一个时刻只能运行其中的一个这个时候就牵扯到先后的问题换言之也就是优先级。 系统中进程的优先级一般包括实时优先级和静态优先级在任何时刻实时进程的优先级高于普通进程实时进程的优先级范围0~99普通进程的优先级范围100~139,因此数值越小优先级越高。 1 查看Linux中进程的优先级
[rootachao ~]# ps -lF S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD4 S 0 2935 2928 0 80 0 - 29180 do_wai pts/0 00:00:00 bash0 R 0 3071 2935 0 80 0 - 38328 - pts/0 00:00:00 ps ps命令能够显示当前系统中正在运行的进程并且能够显示进程的详细信息其中PRI和NI是和进程优先级相关的字段。PRI的默认取值范围是0~99进程的优先级涉及到进程调度相关的知识此处不做展开。本篇旨在使用。 2 使用nice指定优先级 NICE值是进程优先级的修正值NICE和优先级的关系如下 PRI值PRI值旧值NICE值
进程最终的优先级是PRI和NICE值的和NICE值可以是正数也可以是负数当NICE值为正时会使得进程优先级降低反之可以提高进程优先级。 NICE取值范围-20~19。 设置进程NICE值使用nice命令介绍如下
[rootachao ~]# nice --helpUsage: nice [OPTION] [COMMAND [ARG]...]Run COMMAND with an adjusted niceness, which affects process scheduling.With no COMMAND, print the current niceness. Niceness values range from-20 (most favorable to the process) to 19 (least favorable to the process).
Mandatory arguments to long options are mandatory for short options too. -n, --adjustmentN add integer N to the niceness (default 10) --help display this help and exit --version output version information and exit 3 正常执行shell脚本并查看
[rootachao libai]# lsdemo.sh[rootachao libai]# cat demo.sh #!/bin/bashwhile((1))do sleep 1done[rootachao libai]# ./demo.sh [1] 3376[rootachao libai]# ps -lF S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD4 S 0 2935 2928 0 80 0 - 29213 do_wai pts/0 00:00:00 bash0 S 0 3376 2935 0 80 0 - 28320 do_wai pts/0 00:00:00 demo.sh0 S 0 3386 3376 0 80 0 - 27014 hrtime pts/0 00:00:00 sleep0 R 0 3387 2935 0 80 0 - 38328 - pts/0 00:00:00 ps 不指定nice值执行shell脚本PID值是3376 4 使用nice指定优先级执行shell脚本
[rootachao libai]# nice -10 ./demo.sh [2] 3573[rootachao libai]# ps -elf | grep demo.sh | grep -v grep 0 S root 3376 2935 0 80 0 - 28320 do_wai 01:39 pts/0 00:00:00 /bin/bash ./demo.sh0 S root 3573 2935 0 90 10 - 28320 do_wai 01:42 pts/0 00:00:00 /bin/bash ./demo.sh 我们发现NI和PRI的值发生了变化因此使用nice命令可以直接对进程执行的优先级产生影响该影响在进行进程调度的时候会发生很大的作用不知道宝子们在生产环境中是否遇见过呢阿超第一次遇见的时候是在shell脚本中的当时也是一脸懵只能悄悄查资料学习理解。 5 renice的语法格式 renice的范围是[-20~19]
[rootachao libai]# renice --help
Usage: renice [-n] priority [-p|--pid] pid... renice [-n] priority -g|--pgrp pgid... renice [-n] priority -u|--user user...
Options: -g, --pgrp id interpret argument as process group ID -n, --priority num specify the nice increment value -p, --pid id interpret argument as process ID (default) -u, --user name|id interpret argument as username or user ID -h, --help display help text and exit -V, --version display version information and exit 在运行的过程中如果需要提高或者降低优先级也是有办法的这个时候就用renice命令就可以完成。 6 使用renice重置优先级
使用kill -9结束3376进程[rootachao libai]# kill -9 3376[1]- Killed ./demo.sh[rootachao libai]# ps -elf | grep demo.sh | grep -v grep 0 S root 3573 2935 0 90 10 - 28320 do_wai 01:42 pts/0 00:00:00 /bin/bash ./demo.sh[rootachao libai]# renice 15 -p 35733573 (process ID) old priority 10, new priority 15[rootachao libai]# ps -elf | grep demo.sh | grep -v grep 0 S root 3573 2935 0 95 15 - 28320 do_wai 01:42 pts/0 00:00:00 /bin/bash ./demo.sh 注意renice命令也是只能通过影响进程的NICE值来改变进程的优先级而不能直接改变进程的优先级。
一键生成SSL证书详解Shell脚本实现及OpenSSL应用
OpenSSL简介
OpenSSL是一个强大的开源工具包用于实现SSL和TLS协议以及提供加密功能。它广泛应用于Web服务器用于加密HTTPS通信。在本脚本中我们将使用OpenSSL来生成自签名的CA证书颁发机构证书以及服务器证书。
脚本分析
接下来我们将逐行分析这个Shell脚本了解它是如何工作的。
CERT_INFO( [00]/Oheaven/CNca.god.com [01]cakey.pem [02]cacert.pem [03]2048 [04]3650 [05]0 [10]/CCN/SThubei/Lwuhan/OCentral.Hospital/CNmaster.liwenliang.org [11]master.key [12]master.crt [13]2048 [14]365 [15]1 [16]master.csr [20]/CCN/SThubei/Lwuhan/OCentral.Hospital/CNslave.liwenliang.org [21]slave.key [22]slave.crt [23]2048 [24]365 [25]2 [26]slave.csr )
这段定义了一个名为CERT_INFO的数组包含了生成证书所需的各种信息包括证书主题、密钥文件名、证书文件名、密钥长度、有效期、序列号以及CSR证书签名请求文件名。
COLORecho -e \\E[1;32m END\\E[0m DIR/data cd $DIR
这几行定义了用于输出彩色文本的命令并设置了工作目录为/data。
for i in {0..2};do if [ $i -eq 0 ] ;then openssl req -x509 -newkey rsa:${CERT_INFO[${i}3]} -subj ${CERT_INFO[${i}0]} \ -set_serial ${CERT_INFO[${i}5]} -keyout ${CERT_INFO[${i}1]} -nodes -days ${CERT_INFO[${i}4]} \ -out ${CERT_INFO[${i}2]} /dev/null else openssl req -newkey rsa:${CERT_INFO[${i}3]} -nodes -subj ${CERT_INFO[${i}0]} \ -keyout ${CERT_INFO[${i}1]} -out ${CERT_INFO[${i}6]} /dev/null openssl x509 -req -in ${CERT_INFO[${i}6]} -CA ${CERT_INFO[02]} -CAkey ${CERT_INFO[01]} \ -set_serial ${CERT_INFO[${i}5]} -days ${CERT_INFO[${i}4]} -out ${CERT_INFO[${i}2]} /dev/null fi $COLOR**************************************生成证书信息 **************************************$END openssl x509 -in ${CERT_INFO[${i}2]} -noout -subject -dates -serial echo done
这是脚本的核心部分通过一个循环分别为CA和两个服务器生成证书。 对于CA$i -eq 0使用openssl req -x509命令直接生成自签名的X.509证书。 对于服务器证书首先使用openssl req生成CSR然后使用openssl x509根据CSR和CA证书生成最终的服务器证书。
chmod 600 *.key
这行代码将所有密钥文件的权限设置为600确保只有文件所有者可以读写密钥文件增加安全性。
action 证书生成完成
这行假设有一个名为action的函数用于显示操作结果。虽然脚本中没有定义这个函数但你可以根据需要自行实现例如通过简单的echo命令来输出完成信息。
使用脚本 保存脚本将上述脚本保存为generate_certs.sh。 赋予权限运行chmod x generate_certs.sh使脚本具有执行权限。 执行脚本运行./generate_certs.sh脚本将自动生成所需的证书和密钥。
注意事项 确保在运行脚本之前你已经安装了OpenSSL。 根据你的实际需求可能需要调整证书的有效期、密钥长度等参数。 在生产环境中建议使用受信任的CA颁发的证书而不是自签名证书。
结语
通过这个简单的Shell脚本你可以轻松地为你的服务器生成SSL证书无论是用于开发环境还是测试环境。当然对于生产环境建议使用更严格的证书管理策略并确保定期更新证书以保障通信安全。希望这篇文章对你有所帮助如果你有任何问题或建议欢迎在评论区留言。
18 个一线工作中常用 Shell 脚本 1、检测两台服务器指定目录下的文件一致性 2、定时清空文件内容定时记录文件大小 3、检测网卡流量并按规定格式记录在日志中 4、计算文档每行出现的数字个数并计算整个文档的数字总数 5、从 FTP 服务器下载文件 6、连续输入5个100以内的数字统计和、最小和最大 7、监测 Nginx 访问日志 502 情况并做相应动作 8、将结果分别赋值给变量 9、批量修改文件名 10、统计当前目录中以 .html 结尾的文件总大 11、扫描主机端口状态 12、输入数字运行相应命令 13、Expect 实现 SSH 免交互执行命令 14、监控 httpd 的进程数根据监控情况做相应处理 15、批量修改服务器用户密码 16、iptables 自动屏蔽访问网站频繁的IP 17、根据web访问日志封禁请求量异常的IP如IP在半小时后恢复正常则解除封禁 18、判断用户输入的是否为IP地址
1、检测两台服务器指定目录下的文件一致性
#!/bin/bash
#####################################
#检测两台服务器指定目录下的文件一致性
#####################################
#通过对比两台服务器上文件的md5值达到检测一致性的目的
dir/data/web
b_ip192.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.txtthenmd5_agrep -w $f /tmp/md5_a.txt|awk {print 1}md5_bgrep -w $f /tmp/md5_b.txt|awk {print 1}#当文件存在时如果md5值不一致则输出文件改变的结果if [ $md5_a ! $md5_b ]thenecho $f changed.fielseecho $f deleted.fi
done2、定时清空文件内容定时记录文件大小
#!/bin/bash
################################################################
#每小时执行一次脚本任务计划当时间为0点或12点时将目标目录下的所有文件内
#容清空但不删除文件其他时间则只统计各个文件的大小一个文件一行输出到以时#间和日期命名的文件中需要考虑目标目录下二级、三级等子目录的文件
################################################################
logfile/tmp/date %H-%F.log
ndate %H
if [ $n -eq 00 ] || [ $n -eq 12 ]
then#通过for循环以find命令作为遍历条件将目标目录下的所有文件进行遍历并做相应操作for i in find /data/log/ -type fdotrue $idone
elsefor i in find /data/log/ -type fdodu -sh $i $logfiledone
fi3、检测网卡流量并按规定格式记录在日志中
#!/bin/bash
#######################################################
#检测网卡流量并按规定格式记录在日志中
#规定一分钟记录一次
#日志格式如下所示:
#2019-08-12 20:40
#ens33 input: 1234bps
#ens33 output: 1235bps
######################################################3
while :
do#设置语言为英文保障输出结果是英文否则会出现bugLANGenlogfile/tmp/date %d.log#将下面执行的命令结果输出重定向到logfile日志中exec $logfiledate %F %H:%M#sar命令统计的流量单位为kb/s日志格式为bps因此要*1000*8sar -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
done4、计算文档每行出现的数字个数并计算整个文档的数字总数
#!/bin/bash
#########################################################
#计算文档每行出现的数字个数并计算整个文档的数字总数
########################################################
#使用awk只输出文档行数截取第一段
nwc -l a.txt|awk {print $1}
sum0
#文档中每一行可能存在空格因此不能直接用文档内容进行遍历
for i in seq 1 $n
do#输出的行用变量表示时需要用双引号linesed -n $ip a.txt#wc -L选项统计最长行的长度n_necho $line|sed s/[^0-9]//g|wc -Lecho $n_nsum$[$sum$n_n]
done
echo sum:$sum杀死所有脚本
#!/bin/bash
if [ $# -ne 1 ]; thenecho Usage: $0 filename
fi
dir$(dirname $1)
file$(basename $1)
ftp -n -v EOF # -n 自动登录
open 192.168.1.10 # ftp服务器
user admin password
binary # 设置ftp传输模式为二进制避免MD5值不同或.tar.gz压缩包格式错误
cd $dir
get $file
EOF5、从 FTP 服务器下载文件
#!/bin/bash
if [ $# -ne 1 ]; then echo Usage: $0 filename
fi
dir$(dirname $1)
file$(basename $1)
ftp -n -v EOF # -n 自动登录
open 192.168.1.10 # ftp服务器
user admin password
binary # 设置ftp传输模式为二进制避免MD5值不同或.tar.gz压缩包格式错误
cd $dir
get $file
EOF6、连续输入5个100以内的数字统计和、最小和最大
#!/bin/bash
COUNT1
SUM0
MIN0
MAX100
while [ $COUNT -le 5 ]; doread -p 请输入1-10个整数 INTif [[ ! $INT ~ ^[0-9]$ ]]; thenecho 输入必须是整数exit 1elif [[ $INT -gt 100 ]]; thenecho 输入必须是100以内exit 1fiSUM$(($SUM$INT))[ $MIN -lt $INT ] MIN$INT[ $MAX -gt $INT ] MAX$INTlet COUNT
done
echo SUM: $SUM
echo MIN: $MIN
echo MAX: $MAX用户猜数字
#!/bin/bash # 脚本生成一个 100 以内的随机数,提示用户猜数字,根据用户的输入,提示用户猜对了,
# 猜小了或猜大了,直至用户猜对脚本结束。
# RANDOM 为系统自带的系统变量,值为 0‐32767的随机数
# 使用取余算法将随机数变为 1‐100 的随机数num$[RANDOM%1001]echo $num
# 使用 read 提示用户猜数字
# 使用 if 判断用户猜数字的大小关系:‐eq(等于),‐ne(不等于),‐gt(大于),‐ge(大于等于),
# ‐lt(小于),‐le(小于等于)while :
doread -p 计算机生成了一个 1‐100 的随机数,你猜: caiif [ $cai -eq $num ]thenecho 恭喜,猜对了exitelif [ $cai -gt $num ]thenecho Oops,猜大了elseecho Oops,猜小了fi
done7、监测 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
N30 #设定阈值
while :
do#查看访问日志的最新300条并统计502的次数errtail -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 60fisleep 10
done8、将结果分别赋值给变量
应用场景希望将执行结果或者位置参数赋值给变量以便后续使用。
方法1
for i in $(echo 4 5 6); doeval a$i$i
done
echo $a4 $a5 $a6方法2将位置参数192.168.1.1{1,2}拆分为到每个变量
num0
for i in $(eval echo $*);do #eval将{1,2}分解为1 2let num1eval node${num}$i
done
echo $node1 $node2 $node3
# bash a.sh 192.168.1.1{1,2}
192.168.1.11 192.168.1.12方法3
arr(4 5 6)
INDEX1$(echo ${arr[0]})
INDEX2$(echo ${arr[1]})
INDEX3$(echo ${arr[2]})9、批量修改文件名
示例
# touch article_{1..3}.html
# lsarticle_1.html article_2.html article_3.html方法1
for file in $(ls *html); do mv $file bbs_${file#*_} # mv $file $(echo $file |sed -r s/.*(_.*)/bbs\1/) # mv $file $(echo $file |echo bbs_$(cut -d_ -f2)方法2
for file in $(find . -maxdepth 1 -name *html); do mv $file bbs_${file#*_}done方法3
# rename article bbs *.html把一个文档前五行中包含字母的行删掉同时删除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行123456AAAA2脚本如下
#!/bin/bash
###############################################################
把一个文档前五行中包含字母的行删掉同时删除6到10行包含的所有字母
##############################################################
sed -n 1,5p 2.txt |sed /[a-zA-Z]/d
sed -n 6,10p 2.txt |sed s/[a-zA-Z]//g
sed -n 11,$p 2.txt
#最终结果只是在屏幕上打印结果如果想直接更改文件可将输出结果写入临时文件中再替换2.txt或者使用-i选项10、统计当前目录中以 .html 结尾的文件总大
方法1
# find . -name *.html -exec du -k {} \; |awk {sum$1}END{print sum}方法2
for size in $(ls -l *.html |awk {print $5}); do sum$(($sum$size))
done
echo $sum 11、扫描主机端口状态
#!/bin/bash
HOST$1
PORT22 25 80 8080
for PORT in $PORT; doif echo /dev/null /dev/tcp/$HOST/$PORT; thenecho $PORT openelseecho $PORT closefi
done用 shell 打印示例语句中字母数小于 6 的单词
#示例语句
#Bash also interprets a number of multi-character options.
#!/bin/bash
##############################################################
#shell打印示例语句中字母数小于6的单词
##############################################################
for s in Bash also interprets a number of multi-character options.
donecho $s|wc -cif [ $n -lt 6 ]thenecho $sfi
done12、输入数字运行相应命令
#!/bin/bash
##############################################################
#输入数字运行相应命令
##############################################################
echo *cmd menu* 1-date 2-ls 3-who 4-pwd 0-exit
while :
do#捕获用户键入值read -p please input number : nn1echo $n|sed s/[0-9]//g#空输入检测if [ -z $n ]thencontinuefi#非数字输入检测if [ -n $n1 ]thenexit 0fibreak
done
case $n in1)date;;2)ls;;3)who;;4)pwd;;0)break;;#输入数字非1-4的提示*)echo please input number is [1-4]
esac13、Expect 实现 SSH 免交互执行命令
Expect是一个自动交互式应用程序的工具如telnetftppasswd等。
需先安装expect软件包。
方法1EOF 标准输出作为 expect 标准输入
#!/bin/bash
USERroot
PASS123.com
IP192.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
USERroot
PASS123.com
IP192.168.1.120
expect -c spawn ssh $USER$IPexpect {\(yes/no)\ {send \yes\r\; exp_continue}\password:\ {send \$PASS\r\; exp_continue}\$USER*\ {send \df -h\r exit\r\; exp_continue}
}方法3将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 passwdexit 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_INFOuser_info.txt
for ip in $(awk {print $1} $HOST_INFO)
douser$(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
doneLinux主机SSH连接信息
# cat user_info.txt
192.168.1.120 root 123456创建10个用户并分别设置密码密码要求10位且包含大小写字母以及数字最后需要把每个用户的密码存在指定文件中 。
#!/bin/bash
##############################################################
#创建10个用户并分别设置密码密码要求10位且包含大小写字母以及数字
#最后需要把每个用户的密码存在指定文件中
#前提条件安装mkpasswd命令
##############################################################
#生成10个用户的序列00-09
for u in seq -w 0 09
do#创建用户useradd user_$u#生成密码pmkpasswd -s 0 -l 10#从标准输入中读取密码进行修改不安全echo $p|passwd --stdin user_$u#常规修改密码echo -e $p\n$p|passwd user_$u#将创建的用户及对应的密码记录到日志文件中echo user_$u $p /tmp/userpassword
done14、监控 httpd 的进程数根据监控情况做相应处理
#!/bin/bash
###############################################################################################################################
#需求
#1.每隔10s监控httpd的进程数若进程数大于等于500则自动重启Apache服务并检测服务是否重启成功
#2.若未成功则需要再次启动若重启5次依旧没有成功则向管理员发送告警邮件并退出检测
#3.如果启动成功则等待1分钟后再次检测httpd进程数若进程数正常则恢复正常检测10s一次否则放弃重启并向管理员发送告警邮件并退出检测
###############################################################################################################################
#计数器函数
check_service()
{j0for i in seq 1 5do#重启Apache的命令/usr/local/apache2/bin/apachectl restart 2 /var/log/httpderr.log#判断服务是否重启成功if [ $? -eq 0 ]thenbreakelsej$[$j1]fi#判断服务是否已尝试重启5次if [ $j -eq 5 ]thenmail.pyexitfidone
}
while :
donpgrep -l httpd|wc -l#判断httpd服务进程数是否超过500if [ $n -gt 500 ]then/usr/local/apache2/bin/apachectl restartif [ $? -ne 0 ]thencheck_serviceelsesleep 60n2pgrep -l httpd|wc -l#判断重启后是否依旧超过500if [ $n2 -gt 500 ]thenmail.pyexitfififi#每隔10s检测一次sleep 10
done15、批量修改服务器用户密码
Linux主机SSH连接信息旧密码
# cat old_pass.txt
192.168.18.217 root 123456 22
192.168.18.218 root 123456 22内容格式IP User Password Port
SSH远程修改密码脚本新密码随机生成
#!/bin/bash
OLD_INFOold_pass.txt
NEW_INFOnew_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 生成新密码文件
# cat new_pass.txt
192.168.18.217 root n8wX3mU% 22
192.168.18.218 root c87;ZnnL 2216、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; doif [ $(iptables -vnL |grep -c $IP) -eq 0 ];theniptables -I INPUT -s $IP -j DROPfi
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; doif [ $(iptables -vnL |grep -c $IP) -eq 0 ]; theniptables -I INPUT -s $IP -j DROPfi
done2屏蔽每分钟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; doif [ $(iptables -vnL |grep -c $IP) -eq 0 ];theniptables -I INPUT -s $IP -j DROPfi
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 17、根据web访问日志封禁请求量异常的IP如IP在半小时后恢复正常则解除封禁
#!/bin/bash
####################################################################################
#根据web访问日志封禁请求量异常的IP如IP在半小时后恢复正常则解除封禁
####################################################################################
logfile/data/log/access.log
#显示一分钟前的小时和分钟
d1date -d -1 minute %H%M
d2date %M
ipt/sbin/iptables
ips/tmp/ips.txt
block()
{#将一分钟前的日志全部过滤出来并提取IP以及统计访问次数grep $d1: $logfile|awk {print $1}|sort -n|uniq -c|sort -n $ips#利用for循环将次数超过100的IP依次遍历出来并予以封禁for i in awk $1100 {print $2} $ipsdo$ipt -I INPUT -p tcp --dport 80 -s $i -j REJECTecho date %F-%T $i /tmp/badip.logdone
}
unblock()
{#将封禁后所产生的pkts数量小于10的IP依次遍历予以解封for a in $ipt -nvL INPUT --line-numbers |grep 0.0.0.0/0|awk $210 {print $1}|sort -nrdo$ipt -D INPUT $adone$ipt -Z
}
#当时间在00分以及30分时执行解封函数
if [ $d2 -eq 00 ] || [ $d2 -eq 30 ]
then#要先解再封因为刚刚封禁时产生的pkts数量很少unblockblock
elseblock
fi18、判断用户输入的是否为IP地址
方法1:
#!/bin/bash
function check_ip(){ IP$1 VALID_CHECK$(echo $IP|awk -F. $1 255$2255$3255$4255{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
#!/bin/bash
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判断。
#!/bin/bash
function check_ip(){ local IP$1 VALID_CHECK$(echo $IP|awk -F. $1 255$2255$3255$4255{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