wordpress vue 关系/凌哥seo技术博客
运维实用脚本整理
- 本文脚本仅供参考
- 运维排查问题思路
- 运维排查问题的方法和命令
- (1)尽可能搞清楚问题的前因后果
- (2)有谁在?
- (3)之前发生了什么?
- (4) 现在在运行的进程是啥?
- (5)监听的网络服务
- (6)CPU 和内存
- (7)硬件
- (8) IO 性能
- (9) 挂载点 和 文件系统
- (10) 内核、中断和网络
- (11) 系统日志和内核消息
- (12) 定时任务
- (13) 应用系统日志
- Linux运维日常巡检脚本
- 系统指标巡检脚本
- 日常命令
- 性能相关的命令
- 进程相关的命令
- javadump.sh
- 常用运维加固脚本
- 根据PID过滤进程所有信息
- 根据进程名过滤进程信息
- 常用工具一键部署安装
- 常用lib库安装
- 系统检查脚本
- SPN 日常巡查脚本
- ffmpeg脚本
- 打开进程,并判断进程数量
- 关闭进程
- java jar包启动-剔除Pom中依赖
- Java jar包通用启动脚本
- 查看centos配置信息脚本
- Jenkins项目打包发布脚本
- 注意:SQL Server以下脚本目前还不完善(AlwaysOn相关 到 Agent作业备份)
- AlwaysOn相关
- 节点切换监控
- 节点切换作业控制
- SQL Server 邮件脚本
- Mysql-使用脚本进行分库分表备份
- 数据库-数据备份
- 备份作业
- 数据一致性检查
- Agent作业备份
- 监控某个目录是否被更改
- 确保本机能连上shell脚本中指定的smtp服务器的25好端口
- 下面开始测试
- 查看邮件,就能看到/data/test目录下变动的文件或子目录信息了
- 通过crontab定时任务,每5分钟执行一次检查:
- 日志文件ERROR监控报警
- 1)第一类日志
- 2)第二类日志
- 3)第三类日志
- 基于Ping和Telnet/NC的监控脚本案例分析
- 通过shell脚本,判断172.16.60.0/24网络里,当前在线的ip有哪些?能ping通则认为在线。
- 案例一:单纯地对某些ip进行ping监控
- 案例二:对/etc/hosts列表里的ip映射关系进行ping监控报警
- 案例三:通过nc工具对/etc/hosts列表里的ip的443端口跟本机通信是否正常进行探测
- 监控磁盘的监控脚本
- 监控磁盘IO使用率的脚本,实时查看IO使用情况,防止因为磁盘IO效率低而导致MySQL查询慢的问题
- 实时监控网卡流量的通用脚本
- 检测网卡流量,并按规定格式记录在日志中
- 指定时间内网站访问次数的监控
- nginx日志监控脚本
- python报警脚本
- 写个测试脚本不停curl请求资源触发报警
- 定时任务,由于上面脚本是监控一分钟内的日志,因此每分钟执行一次
- 网站访问状态和超时时间监控报警设置
- 服务器磁盘监控脚本(含报警邮件)
- 业务日志清理脚本
- Linux下间隔多少秒 (即以秒为单位) 去执行某条命令或某个shell脚本的操作方法
- Linux下批量ping某个网段ip的脚本
- 查看系统运行情况
- 管理docker
- Shell多线程备份数据库
- 监测 Nginx 访问日志 502 情况,并做相应动作
- 检测两台服务器指定目录下的文件一致性
- 定时清空文件内容,定时记录文件大小
- 计算文档每行出现的数字个数,并计算整个文档的数字总数
- 杀死所有脚本
- 从 FTP 服务器下载文件
- 扫描主机端口状态
- 监控 httpd 的进程数,根据监控情况做相应处理
- iptables 自动屏蔽访问网站频繁的IP
- 1)屏蔽每分钟访问超过200的IP
- 2)屏蔽每分钟SSH尝试登录超过10次的IP
- 根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
- 判断用户输入的是否为IP地址
本文脚本仅供参考
运维排查问题思路
运维排查问题的方法和命令
遇到服务器故障,问题出现的原因很少可以一下就想到。基本上都会从以下步骤入手:
(1)尽可能搞清楚问题的前因后果
不要一下子就扎到服务器前面,你需要先搞明白对这台服务器有多少已知的情况,还有故障的具体情况。不然你很可能就是在无的放矢。
必须搞清楚的问题有:
-
故障的表现是什么?无响应?报错?
-
故障是什么时候发现的?
-
故障是否可重现?
-
有没有出现的规律(比如每小时出现一次)
-
最后一次对整个平台进行更新的内容是什么(代码、服务器等)?
-
故障影响的特定用户群是什么样的(已登录的, 退出的, 某个地域的…)?
-
基础架构(物理的、逻辑的)的文档是否能找到?
-
是否有监控平台可用? (比如Munin、Zabbix、 Nagios、 New Relic… 什么都可以)
-
是否有日志可以查看?. (比如Loggly、Airbrake、 Graylog…)
最后两个是最方便的信息来源,不过别抱太大希望,基本上它们都不会有。只能再继续摸索了。
(2)有谁在?
wlast
用这两个命令看看都有谁在线,有哪些用户访问过。这不是什么关键步骤,不过最好别在其他用户正干活的时候来调试系统。有道是一山不容二虎嘛。(one cook in the kitchen is enough.)
(3)之前发生了什么?
history
查看一下之前服务器上执行过的命令。看一下总是没错的,加上前面看的谁登录过的信息,应该有点用。另外作为admin要注意,不要利用自己的权限去侵犯别人的隐私哦。
到这里先提醒一下,等会你可能会需要更新 HISTTIMEFORMAT 环境变量来显示这些命令被执行的时间。对要不然光看到一堆不知道啥时候执行的命令,同样会令人抓狂的。
(4) 现在在运行的进程是啥?
pstree -aps aux
这都是查看现有进程的。 ps aux 的结果比较杂乱, pstree -a 的结果比较简单明了,可以看到正在运行的进程及相关用户。
(5)监听的网络服务
netstat -ntlpnetstat -nulpnetstat -nxlp
我一般都分开运行这三个命令,不想一下子看到列出一大堆所有的服务。netstat -nalp倒也可以。不过我绝不会用 numeric 选项 (鄙人一点浅薄的看法:IP 地址看起来更方便)。
找到所有正在运行的服务,检查它们是否应该运行。查看各个监听端口。在netstat显示的服务列表中的PID 和 ps aux 进程列表中的是一样的。
如果服务器上有好几个Java或者Erlang什么的进程在同时运行,能够按PID分别找到每个进程就很重要了。
通常我们建议每台服务器上运行的服务少一点,必要时可以增加服务器。如果你看到一台服务器上有三四十个监听端口开着,那还是做个记录,回头有空的时候清理一下,重新组织一下服务器。
(6)CPU 和内存
free -muptimetophtop
注意以下问题:
还有空余的内存吗? 服务器是否正在内存和硬盘之间进行swap?
还有剩余的CPU吗? 服务器是几核的? 是否有某些CPU核负载过多了?
服务器最大的负载来自什么地方? 平均负载是多少?
(7)硬件
lspcidmidecodeethtool
有很多服务器还是裸机状态,可以看一下:
找到RAID 卡 (是否带BBU备用电池?)、 CPU、空余的内存插槽。根据这些情况可以大致了解硬件问题的来源和性能改进的办法。
网卡是否设置好? 是否正运行在半双工状态? 速度是10MBps? 有没有 TX/RX 报错?
(8) IO 性能
iostat -kx 2vmstat 2 10mpstat 2 10dstat --top-io --top-bio
这些命令对于调试后端性能非常有用。
-
检查磁盘使用量:服务器硬盘是否已满?
-
是否开启了swap交换模式 (si/so)?
-
CPU被谁占用:系统进程? 用户进程? 虚拟机?
-
dstat 是我的最爱。用它可以看到谁在进行 IO: 是不是MySQL吃掉了所有的系统资源? 还是你的PHP进程?
(9) 挂载点 和 文件系统
mountcat /etc/fstabvgspvslvsdf -hlsof +D / /* beware not to kill your box */
-
一共挂载了多少文件系统?
-
有没有某个服务专用的文件系统? (比如MySQL?)
-
文件系统的挂载选项是什么: noatime? default? 有没有文件系统被重新挂载为只读模式了?
-
磁盘空间是否还有剩余?
-
是否有大文件被删除但没有清空?
-
如果磁盘空间有问题,你是否还有空间来扩展一个分区?
(10) 内核、中断和网络
sysctl -a | grep ...cat /proc/interruptscat /proc/net/ip_conntrack /* may take some time on busy servers */netstatss -s
-
你的中断请求是否是均衡地分配给CPU处理,还是会有某个CPU的核因为大量的网络中断请求或者RAID请求而过载了?
-
SWAP交换的设置是什么?对于工作站来说swappinness 设为 60 就很好, 不过对于服务器就太糟了:你最好永远不要让服务器做SWAP交换,不然对磁盘的读写会锁死SWAP进程。
-
conntrack_max 是否设的足够大,能应付你服务器的流量?
-
在不同状态下(TIME_WAIT, …)TCP连接时间的设置是怎样的?
-
如果要显示所有存在的连接,netstat 会比较慢, 你可以先用 ss 看一下总体情况。
你还可以看一下 Linux TCP tuning 了解网络性能调优的一些要点。
(11) 系统日志和内核消息
dmesgless /var/log/messagesless /var/log/secureless /var/log/auth
-
查看错误和警告消息,比如看看是不是很多关于连接数过多导致?
-
看看是否有硬件错误或文件系统错误?
-
分析是否能将这些错误事件和前面发现的疑点进行时间上的比对。
(12) 定时任务
ls /etc/cron* + catfor user in $(cat /etc/passwd | cut -f1 -d:); do crontab -l -u $user; done
-
是否有某个定时任务运行过于频繁?
-
是否有些用户提交了隐藏的定时任务?
-
在出现故障的时候,是否正好有某个备份任务在执行?
(13) 应用系统日志
这里边可分析的东西就多了, 不过恐怕你作为运维人员是没功夫去仔细研究它的。关注那些明显的问题,比如在一个典型的LAMP(Linux+Apache+Mysql+Perl)应用环境里:
-
Apache & Nginx; 查找访问和错误日志, 直接找 5xx 错误, 再看看是否有 limit_zone错误。
-
MySQL; 在mysql.log找错误消息,看看有没有结构损坏的表, 是否有innodb修复进程在运行,是否有disk/index/query 问题.
-
PHP-FPM; 如果设定了 php-slow 日志, 直接找错误信息 (php, mysql, memcache, …),如果没设定,赶紧设定。
-
Varnish; 在varnishlog 和 varnishstat 里, 检查 hit/miss比. 看看配置信息里是否遗漏了什么规则,使最终用户可以直接攻击你的后端?
-
HA-Proxy; 后端的状况如何?健康状况检查是否成功?是前端还是后端的队列大小达到最大值了?
Linux运维日常巡检脚本
#!/bin/bash
#author by acrossyao
#date: 2021-02-08
#巡检脚本
echo "---------------------------------------「OS系统巡检信息」---------------------------------------"
#OS_IP=`hostname -i | awk '{print $1}'`
OS_IP=""
IPLIST=`hostname -i`
for elem in $IPLIST
do
regex="\b(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\b"
ckStep2=`echo $elem | egrep $regex | wc -l`
if [ $ckStep2 -eq 0 ]
then
aa=1
else
OS_IP+=$elem", "
fi
done
OS_HOSTNAME=`hostname`
OS_RUN_TIME=`uptime |awk '{print $3,$4}'|awk -F, '{print $1}'`
echo " 系统IP地址: $OS_IP"
echo " 主机名称: $OS_HOSTNAME"
echo " 运行时间: $OS_RUN_TIME"
#内存
OS_MEM_TAL=`free -m | grep Mem | awk '{print $2}'`
OS_MEM_FREE=`free -m | grep Mem | awk '{print $7}'`
echo " 内存总量: ${OS_MEM_TAL}MB"
echo " 内存余量: ${OS_MEM_FREE}MB"
#磁盘使用占比
OS_ROOT_DISKS_USE_PRECENT=`df -h / | grep '/'| awk '{print $5}'`
OS_ROOT_DISKS_AVAIL=`df -h / | grep '/'| awk '{print $4}'`
OS_DATA_DISKS_USE_PRECENT=`df -h | grep '/data'| awk '{print $5}'`
OS_DATA_DISKS_AVAIL=`df -h | grep '/data'| awk '{print $4}'`
echo " 根卷使用占比: ${OS_ROOT_DISKS_USE_PRECENT}, 根卷空闲: ${OS_ROOT_DISKS_AVAIL}"
echo " data卷使用占比: ${OS_DATA_DISKS_USE_PRECENT}, data卷空闲: ${OS_DATA_DISKS_AVAIL}"
#CPU
CPU_LOAD=`top -bn1 | grep load | awk '{printf "CPU LOAD: %.2f\n", $(NF-2)}'`
CPU_IDLE=`top -n1 | fgrep "Cpu(s)" | awk -F ',' '{print $4}'`
echo " ${CPU_LOAD}"
echo " CPU IDLE: ${CPU_IDLE}"
echo "---------------------------------------「OS系统巡检结束」---------------------------------------"
系统指标巡检脚本
#!/bin/bash
menu(){
cat <<EOF
+---------------------------------------------+
| 日常巡检脚本 |
| 1.查看磁盘使用率 |
| 2.查看内存使用率 |
| 3.查看系统负载 |
| 4.统计系统连接数 |
| 5.统计系统进程数 |
| 6.统计当前磁盘分区信息 |
| 7.按q退出 |
| 8.按h帮助 |
+---------------------------------------------+
EOF
}
menu
while true
do
echo -en "\033[34m请输入你要查看的内容:\033[0m"
read actionif [ "$action" == "q" ];thenecho "quiting...."breakfiif [ "$action" == "h" ];thenmenuficase $action in 1)df -h ;;2)free -h ;;3)uptime ;;4)ss -tan | grep -i "estab" | wc -l ;;5)ps aux | grep -v "grep" | wc -l ;;6)fdisk -l ;; *)echo "Usage: $0 {1|2|3|4|5|6|q|h}"esac
done
日常命令
1、查找当前目录下占用为0字节的文件并删除find ./ -type f -size 0 -exec rm -rf {}\; #此命令不要用于对根目录0字节文件的操作2、将系统进程按内存占用大小排列显示出来ps -e -o “%C : %p : %z : %a”|sort -k5-nr 3、将系统进程按CPU占用大小排列显示ps -e -o “%C : %p : %z : %a”|sort -nr4、匹配某文件中某一行并进行内容替换sed -i ‘/Root/s/no/yes’/etc/ssh/sshd_config #先匹配到Root,再将此行no替换为yes5、显示所有运行级别为3并开机启动的服务ls /etc/rc3.d/S* |cut -c 15- #rc3.d中S开头即为运行级别3的服务,并用cut截取第15个字符后面的内容6、取得eth0网卡的IP地址 方法1:ifconfig | grep ‘inet addr:’| grep -v ’127.0.0.1′ | cut -d:-f2 | awk ‘{ print $1}’方法2:ifconfig eth0 |grep “inet addr:” |awk ‘{print $2}’|cut -c 6-7、TCP抓包工具分析80端口数据流tcpdump -c 10000 -i eth0 -n dst port 808、查询昨天的日期date –date=yesterday9、删除所有空目录find /data -type d -empty -exec rm -rf {}; #最好不要在/目录下执行此命令10、删除5天前的文件find /data -mtime +5 -type f -exec rm -rf{};11、强制踢出终端用户pkill -KILL -t pts/112、将来自80端口的请求转发到8080端口iptables -A PREROUTING -p tcp -m tcp –dport80 -j DNAT –to-destination 127.0.0.1:808013、Linux服务器之间传文件scp ~/test.txtroot@192.168.0.10:/data/ #将个人主目录下test.txt传到远程主机的/data目录下14、对大文件进行分割split -l 1000 message.log message #按每个文件1000行来分割split -b 5m message.log message #按每个文件5M来分割
性能相关的命令
#查看当前系统load
uptime#查看系统状态和每个进程的系统资源使用状况
top#可视化显示CPU的使用状况
htop#查看每个CPU的负载信息
mpstat -P ALL 1#每隔1秒查看磁盘IO的统计信息
iostat -xkdz 1#每隔一秒查看虚拟内存的使用信息
vmstat 1#查看内存使用统计信息
free#查看网络使用信息
nicstat -z 1#类似vmstat的显示优化的工具
dstat 1#查看系统活动状态,比如系统分页统计,块设备IO统计等
sar#网络连接状态查看
netstat -s#进程资源使用信息查看
pidstat 1
pidstat -d 1#查看某个进程的系统调用信息 -p后面是进程id,-tttT 进程系统后的系统调用时间
strace -tttT -p 12670
#统计IO设备输入输出的系统调用信息
strace -c dd if=/dev/zero of=/dev/null bs=512 count=1024k#tcpdump 查看网络数据包
tcpdump -nr /tmp/out.tcpdump#块设备的读写事件信息统计
btrace /dev/sdb #iotop查看某个进程的IO操作统计信息
iotop -bod5#slabtop 查看内核 slab内存分配器的使用信息
slabtop -sc#系统参数设置
sysctl -a#系统性能指标统计信息
perf stat gzip file1#系统cpu活动状态查看
perf record -a -g -F 997 sleep 10
进程相关的命令
## processes 进程管理##ps查看当前系统执行的线程列表,进行瞬间状态,不是连续状态,连续状态需要使用top名称查看 更多常用参数请使用 man ps查看
ps##显示所有进程详细信息
ps aux##-u 显示某个用户的进程列表
ps -f -u www-data ## -C 通过名字或者命令搜索进程
ps -C apache2## --sort 根据进程cpu使用率降序排列,查看前5个进程 -pcpu表示降序 pcpu升序
ps aux --sort=-pcpu | head -5 ##-f 用树结构显示进程的层次关系,父子进程情况下
ps -f --forest -C apache2 ##显示一个父进程的所有子进程
ps -o pid,uname,comm -C apache2
ps --ppid 2359 ##显示一个进程的所有线程 -L 参数
ps -p 3150 -L ##显示进程的执行时间 -o参数
ps -e -o pid,comm,etime ##watch命令可以用来实时捕捉ps显示进程
watch -n 1 'ps -e -o pid,uname,cmd,pmem,pcpu --sort=-pmem,-pcpu | head -15' ##jobs 查看后台运行的进程 jobs命令执行的结果,+表示是一个当前的作业,减号表是是一个当前作业之后的一个作业,jobs -l选项可显示所有任务的PID,jobs的状态可以是running, stopped, Terminated,但是如果任务被终止了(kill),shell 从当前的shell环境已知的列表中删除任务的进程标识;也就是说,jobs命令显示的是当前shell环境中所起的后台正在运行或者被挂起的任务信息
jobs##查看后台运营的进程号
jobs -p##查看现在被终止或者退出的进程号
jobs -n##kill命令 终止一个前台进程可以使用Ctrl+C键 kill 通过top或者ps获取进程id号 kill [-s 信号 | -p ] [ -a ] 进程号 ...
##发送指定的信号到相应进程。不指定型号将发送SIGTERM(15)终止指定进程。关闭进程号12的进程
kill 12##等同于在前台运行PID为123的进程时按下Ctrl+C键
kill -2 123##如果任无法终止该程序可用“-KILL” 参数,其发送的信号为SIGKILL(9) ,将强制结束进程
kill -9 123##列出所有信号名称
##HUP 1 终端断线
##INT 2 中断(同 Ctrl + C)
##QUIT 3 退出(同 Ctrl + \)
##TERM 15 终止
##KILL 9 强制终止
##CONT 18 继续(与STOP相反, fg/bg命令)
##STOP 19 暂停(同 Ctrl + Z)
kill -l##得到指定信号的数值
kill -l KILL##杀死指定用户所有进程
kill -u peidalinux
kill -9 $(ps -ef | grep peidalinux) ##将后台中的命令调至前台继续运行 将进程123调至前台执行
fg 123##将一个在后台暂停的命令,变成继续执行
bg 123##该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。nohup就是不挂起的意思 下面输出被重定向到myout.file文件中
nohup command > myout.file 2>&1 &##at:计划任务,在特定的时间执行某项工作,在特定的时间执行一次。
## 格式:at HH:MM YYYY-MM-DD //HH(小时):MM(分钟) YYYY(年)-MM(月份)-DD(日)
##HH[am pm]+D(天) days //HH(小时)[am(上午)pm(下午)]+days(天)
at 12:00(时间) //at命令设定12:00执行一项操作
#at>useradd aaa //在at命令里设定添加用户aaa
#ctrl+d //退出at命令
#tail -f /etc/passwd //查看/etc/passwd文件后十行是否增加了一个用户aaa##计划任务设定后,在没有执行之前我们可以用atq命令来查看系统没有执行工作任务。
atq##启动计划任务后,如果不想启动设定好的计划任务可以使用atrm命令删除。
atrm 1 //删除计划任务1##pstree命令:列出当前的进程,以及它们的树状结构 格式:pstree [选项] [pid|user]
pstree##nice命令:改变程序执行的优先权等级 应用程序优先权值的范围从-20~19,数字越小,优先权就越高。一般情况下,普通应用程序的优先权值(CPU使用权值)都是0,如果让常用程序拥有较高的优先权等级,自然启动和运行速度都会快些。需要注意的是普通用户只能在0~19之间调整应用程序的优先权值,只有超级用户有权调整更高的优先权值(从-20~19)。
nice [-n <优先等级>][--help][--version][命令]
nice -n 5 ls##sleep命令:使进程暂停执行一段时间
date;sleep 1m;date##renice命令 renice命令允许用户修改一个正在运行进程的优先权。利用renice命令可以在命令执行时调整其优先权。
##其中,参数number与nice命令的number意义相同。(1) 用户只能对自己所有的进程使用renice命令。(2) root用户可以在任何进程上使用renice命令。(3) 只有root用户才能提高进程的优先权
renice -5 -p 5200 #PID为5200的进程nice设为-5 ##pmap命令用于显示一个或多个进程的内存状态。其报告进程的地址空间和内存状态信息 #pmap PID
pmap 20367
javadump.sh
#!/bin/shDUMP_PIDS=`ps --no-heading -C java -f --width 1000 |awk '{print $2}'`
if [ -z "$DUMP_PIDS" ]; thenecho "The server $HOST_NAME is not started!"exit 1;
fiDUMP_ROOT=~/dump
if [ ! -d $DUMP_ROOT ]; thenmkdir $DUMP_ROOT
fiDUMP_DATE=`date +%Y%m%d%H%M%S`
DUMP_DIR=$DUMP_ROOT/dump-$DUMP_DATE
if [ ! -d $DUMP_DIR ]; thenmkdir $DUMP_DIR
fifor PID in $DUMP_PIDS ; do
#Full thread dump 用来查线程占用,死锁等问题$JAVA_HOME/bin/jstack $PID > $DUMP_DIR/jstack-$PID.dump 2>&1echo -e ".\c"
#打印出一个给定的Java进程、Java core文件或远程Debug服务器的Java配置信息,具体包括Java系统属性和JVM命令行参数。$JAVA_HOME/bin/jinfo $PID > $DUMP_DIR/jinfo-$PID.dump 2>&1echo -e ".\c"
#jstat能够动态打印jvm(Java Virtual Machine Statistics Monitoring Tool)的相关统计信息。如young gc执行的次数、full gc执行的次数,各个内存分区的空间大小和可使用量等信息。$JAVA_HOME/bin/jstat -gcutil $PID > $DUMP_DIR/jstat-gcutil-$PID.dump 2>&1echo -e ".\c"$JAVA_HOME/bin/jstat -gccapacity $PID > $DUMP_DIR/jstat-gccapacity-$PID.dump 2>&1echo -e ".\c"
#未指定选项时,jmap打印共享对象的映射。对每个目标VM加载的共享对象,其起始地址、映射大小及共享对象文件的完整路径将被打印出来, $JAVA_HOME/bin/jmap $PID > $DUMP_DIR/jmap-$PID.dump 2>&1echo -e ".\c"
#-heap打印堆情况的概要信息,包括堆配置,各堆空间的容量、已使用和空闲情况 $JAVA_HOME/bin/jmap -heap $PID > $DUMP_DIR/jmap-heap-$PID.dump 2>&1echo -e ".\c"
#-dump将jvm的堆中内存信息输出到一个文件中,然后可以通过eclipse memory analyzer进行分析
#注意:这个jmap使用的时候jvm是处在假死状态的,只能在服务瘫痪的时候为了解决问题来使用,否则会造成服务中断。$JAVA_HOME/bin/jmap -dump:format=b,file=$DUMP_DIR/jmap-dump-$PID.dump $PID 2>&1echo -e ".\c"
#显示被进程打开的文件信息
if [ -r /usr/sbin/lsof ]; then/usr/sbin/lsof -p $PID > $DUMP_DIR/lsof-$PID.dumpecho -e ".\c"fi
done
#主要负责收集、汇报与存储系统运行信息的。
if [ -r /usr/bin/sar ]; then/usr/bin/sar > $DUMP_DIR/sar.dump
echo -e ".\c"
fi
#主要负责收集、汇报与存储系统运行信息的。
if [ -r /usr/bin/uptime ]; then/usr/bin/uptime > $DUMP_DIR/uptime.dump
echo -e ".\c"
fi
#内存查看
if [ -r /usr/bin/free ]; then/usr/bin/free -t > $DUMP_DIR/free.dump
echo -e ".\c"
fi
#可以得到关于进程、内存、内存分页、堵塞IO、traps及CPU活动的信息。
if [ -r /usr/bin/vmstat ]; then/usr/bin/vmstat > $DUMP_DIR/vmstat.dump
echo -e ".\c"
fi
#报告与CPU相关的一些统计信息
if [ -r /usr/bin/mpstat ]; then/usr/bin/mpstat > $DUMP_DIR/mpstat.dump
echo -e ".\c"
fi
#报告与IO相关的一些统计信息
if [ -r /usr/bin/iostat ]; then/usr/bin/iostat > $DUMP_DIR/iostat.dump
echo -e ".\c"
fi
#报告与网络相关的一些统计信息
if [ -r /bin/netstat ]; then/bin/netstat > $DUMP_DIR/netstat.dump
echo -e ".\c"
fi
echo "OK!"
常用运维加固脚本
根据PID过滤进程所有信息
#! /bin/bash
# Function: 根据用户输入的PID,过滤出该PID所有的信息
read -p "请输入要查询的PID: " P
n=`ps -aux| awk '$2~/^'$P'$/{print $11}'|wc -l`
if [ $n -eq 0 ];thenecho "该PID不存在!!"exit
fi
echo "--------------------------------"
echo "进程PID: $P"
echo "进程命令:`ps -aux| awk '$2~/^'$P'$/{print $11}'`"
echo "进程所属用户: `ps -aux| awk '$2~/^'$P'$/{print $1}'`"
echo "CPU占用率:`ps -aux| awk '$2~/^'$P'$/{print $3}'`%"
echo "内存占用率:`ps -aux| awk '$2~/^'$P'$/{print $4}'`%"
echo "进程开始运行的时刻:`ps -aux| awk '$2~/^'$P'$/{print $9}'`"
echo "进程运行的时间:`ps -aux| awk '$2~/^'$P'$/{print $10}'`"
echo "进程状态:`ps -aux| awk '$2~/^'$P'$/{print $8}'`"
echo "进程虚拟内存:`ps -aux| awk '$2~/^'$P'$/{print $5}'`"
echo "进程共享内存:`ps -aux| awk '$2~/^'$P'$/{print $6}'`"
echo "--------------------------------"
根据进程名过滤进程信息
会显示出该进程名包含的所有线程
#! /bin/bash
# Function: 根据输入的程序的名字过滤出所对应的PID,并显示出详细信息,如果有几个PID,则全部显示
read -p "请输入要查询的进程名:" NAME
N=`ps -aux | grep $NAME | grep -v grep | wc -l` ##统计进程总数
if [ $N -le 0 ];thenecho "该进程名没有运行!"
fi
i=1
while [ $N -gt 0 ]
doecho "进程PID: `ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $2}'`"echo "进程命令:`ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $11}'`"echo "进程所属用户: `ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $1}'`"echo "CPU占用率:`ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $3}'`%"echo "内存占用率:`ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $4}'`%"echo "进程开始运行的时刻:`ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $9}'`"echo "进程运行的时间:` ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $11}'`"echo "进程状态:`ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $8}'`"echo "进程虚拟内存:`ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $5}'`"echo "进程共享内存:`ps -aux | grep $NAME | grep -v grep | awk 'NR=='$i'{print $0}'| awk '{print $6}'`"echo "***************************************************************"let N-- i++
done
常用工具一键部署安装
#!/usr/bin/env bash# ---------------------------------------------------------------------------------
# 控制台颜色
BLACK="\033[1;30m"
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
PURPLE="\033[1;35m"
CYAN="\033[1;36m"
RESET="$(tput sgr0)"
# ---------------------------------------------------------------------------------printf "${BLUE}\n"
cat << EOF
###################################################################################
# 安装常用命令工具
# 命令工具清单如下:
# 核心工具:df、du、chkconfig
# 网络工具:ifconfig、netstat、route、iptables
# IP工具:ip、ss、ping、tracepath、traceroute
# DNS工具:dig、host、nslookup、whois
# 端口工具:lsof、nc、telnet
# 下载工具:curl、wget
# 编辑工具:emacs、vim
# 流量工具:iftop、nethogs
# 抓包工具:tcpdump
# 压缩工具:unzip、zip
# 版本控制工具:git、subversion
#
###################################################################################
EOF
printf "${RESET}\n"printf "\n${GREEN}>>>>>>>>> 安装常用命令工具开始${RESET}\n"# 核心工具
printf "\n${CYAN}>>>> install coreutils(df、du)${RESET}\n"
yum install -y coreutils
printf "\n${CYAN}>>>> install chkconfig${RESET}\n"
yum install -y chkconfig# 网络工具
printf "\n${CYAN}>>>> install net-tools(ifconfig、netstat、route)${RESET}\n"
yum install -y net-tools
printf "\n${CYAN}>>>> install iptables${RESET}\n"
yum install -y iptables# IP工具
printf "\n${CYAN}>>>> install iputils(ping、tracepath)${RESET}\n"
yum install -y iputils
printf "\n${CYAN}>>>> install traceroute${RESET}\n"
yum install -y traceroute
printf "\n${CYAN}>>>> install iproute(ip、ss)${RESET}\n"
yum install -y iproute# 端口工具
printf "\n${CYAN}>>>> install lsof${RESET}\n"
yum install -y lsof
printf "\n${CYAN}>>>> install nc${RESET}\n"
yum install -y nc
printf "\n${CYAN}>>>> install netstat${RESET}\n"
yum install -y netstat# DNS工具
printf "\n${CYAN}>>>> install bind-utils(dig、host、nslookup)${RESET}\n"
yum install -y bind-utils
printf "\n${CYAN}>>>> install whois${RESET}\n"
yum install -y whois# 下载工具
printf "\n${CYAN}>>>> install curl${RESET}\n"
yum install -y curl
printf "\n${CYAN}>>>> install wget${RESET}\n"
yum install -y wget# 编辑工具
printf "\n${CYAN}>>>> install emacs${RESET}\n"
yum install -y emacs
printf "\n${CYAN}>>>> install vim${RESET}\n"
yum install -y vim# 流量工具
printf "\n${CYAN}>>>> install iftop${RESET}\n"
yum install -y iftop
printf "\n${CYAN}>>>> install nethogs${RESET}\n"
yum install -y nethogs# 抓包工具
printf "\n${CYAN}>>>> install tcpdump${RESET}\n"
yum install -y tcpdump# 压缩工具
printf "\n${CYAN}>>>> install unzip${RESET}\n"
yum install -y unzip# 版本控制工具
printf "\n${CYAN}>>>> install git${RESET}\n"
yum install -y git
printf "\n${CYAN}>>>> install subversion${RESET}\n"
yum install -y subversionprintf "\n${GREEN}<<<<<<<< 安装常用命令工具结束${RESET}\n"
常用lib库安装
lib库分为两种,一种是静态链接lib库或者叫做静态lib库,另一种叫做动态链接库dll库的lib导入库或称为lib导入库。
第一种是静态lib,包含了所有的代码实现的,是源代码文件.c或.cpp文件编译生成的,这个lib库就是文本形式的源代码编译后的二进制形式代码。
第二种就是lib导入库,这个库只是dll文件中的所有函数在dll文件中的地址的说明。
#!/usr/bin/env bash# ---------------------------------------------------------------------------------
# 控制台颜色
BLACK="\033[1;30m"
RED="\033[1;31m"
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
BLUE="\033[1;34m"
PURPLE="\033[1;35m"
CYAN="\033[1;36m"
RESET="$(tput sgr0)"
# ---------------------------------------------------------------------------------printf "${BLUE}\n"
cat << EOF
###################################################################################
# 安装常见 lib
# 如果不知道命令在哪个 lib,可以使用 yum search xxx 来查找
# lib 清单如下:
# gcc gcc-c++ kernel-devel libtool
# openssl openssl-devel
# zlib zlib-devel
# pcre
###################################################################################
EOF
printf "${RESET}\n"printf "\n${GREEN}>>>>>>>>> 安装常见 lib 开始${RESET}\n"printf "\n${CYAN}>>>> install gcc gcc-c++ kernel-devel libtool${RESET}\n"
yum -y install make gcc gcc-c++ kernel-devel libtoolprintf "\n${CYAN}>>>> install openssl openssl-devel${RESET}\n"
yum -y install make openssl openssl-develprintf "\n${CYAN}>>>> install zlib zlib-devel${RESET}\n"
yum -y install make zlib zlib-develprintf "\n${CYAN}>>>> install pcre${RESET}\n"
yum -y install pcreprintf "\n${GREEN}<<<<<<<< 安装常见 lib 结束${RESET}\n"
系统检查脚本
#!/usr/bin/env bash##############################################################################
# console color
C_RESET="$(tput sgr0)"
C_BLACK="\033[1;30m"
C_RED="\033[1;31m"
C_GREEN="\033[1;32m"
C_YELLOW="\033[1;33m"
C_BLUE="\033[1;34m"
C_PURPLE="\033[1;35m"
C_CYAN="\033[1;36m"
C_WHITE="\033[1;37m"
##############################################################################printf "${C_PURPLE}"
cat << EOF
###################################################################################
# 系统信息检查脚本
###################################################################################
EOF
printf "${C_RESET}"[[ $(id -u) -gt 0 ]] && echo "请用root用户执行此脚本!" && exit 1
sysversion=$(rpm -q centos-release | cut -d- -f3)
double_line="==============================================================="
line="----------------------------------------------"# 打印头部信息
printHeadInfo() {cat << EOF
+---------------------------------------------------------------------------------+
| 欢迎使用 【系统信息检查脚本】 |
+---------------------------------------------------------------------------------+
EOF
}# 打印尾部信息
printFootInfo() {cat << EOF
+---------------------------------------------------------------------------------+
| 脚本执行结束,感谢使用!|
+---------------------------------------------------------------------------------+
EOF
}options=( "获取系统信息" "获取服务信息" "获取CPU信息" "获取系统网络信息" "获取系统内存信息" "获取系统磁盘信息" "获取CPU/内存占用TOP10" "获取系统用户信息" "输出所有信息" "退出" )
printMenu() {printf "${C_BLUE}"printf "主菜单:\n"for i in "${!options[@]}"; doindex=`expr ${i} + 1`val=`expr ${index} % 2`printf "\t(%02d) %-30s" "${index}" "${options[$i]}"if [[ ${val} -eq 0 ]]; thenprintf "\n"fidoneprintf "${C_BLUE}请输入需要执行的指令:\n"printf "${C_RESET}"
}# 获取系统信息
get_systatus_info() {sys_os=$(uname -o)sys_release=$(cat /etc/redhat-release)sys_kernel=$(uname -r)sys_hostname=$(hostname)sys_selinux=$(getenforce)sys_lang=$(echo $LANG)sys_lastreboot=$(who -b | awk '{print $3,$4}')sys_runtime=$(uptime | awk '{print $3,$4}' | cut -d, -f1)sys_time=$(date)sys_load=$(uptime | cut -d: -f5)cat << EOF
【系统信息】
系统: ${sys_os}
发行版本: ${sys_release}
系统内核: ${sys_kernel}
主机名: ${sys_hostname}
selinux状态: ${sys_selinux}
系统语言: ${sys_lang}
系统当前时间: ${sys_time}
系统最后重启时间: ${sys_lastreboot}
系统运行时间: ${sys_runtime}
系统负载: ${sys_load}
EOF
}# 获取CPU信息
get_cpu_info() {Physical_CPUs=$(grep "physical id" /proc/cpuinfo | sort | uniq | wc -l)Virt_CPUs=$(grep "processor" /proc/cpuinfo | wc -l)CPU_Kernels=$(grep "cores" /proc/cpuinfo | uniq | awk -F ': ' '{print $2}')CPU_Type=$(grep "model name" /proc/cpuinfo | awk -F ': ' '{print $2}' | sort | uniq)CPU_Arch=$(uname -m)cat << EOF
【CPU信息】
物理CPU个数:$Physical_CPUs
逻辑CPU个数:$Virt_CPUs
每CPU核心数:$CPU_Kernels
CPU型号:$CPU_Type
CPU架构:$CPU_Arch
EOF
}# 获取服务信息
get_service_info() {port_listen=$(netstat -lntup | grep -v "Active Internet")kernel_config=$(sysctl -p 2> /dev/null)if [[ ${sysversion} -gt 6 ]]; thenservice_config=$(systemctl list-unit-files --type=service --state=enabled | grep "enabled")run_service=$(systemctl list-units --type=service --state=running | grep ".service")elseservice_config=$(/sbin/chkconfig | grep -E ":on|:启用" | column -t)run_service=$(/sbin/service --status-all | grep -E "running")ficat << EOF
【服务信息】
${service_config}${line}
运行的服务:
${run_service}${line}
监听端口:
${port_listen}${line}
内核参考配置:
${kernel_config}
EOF
}# 获取系统内存信息
get_mem_info() {check_mem=$(free -m)MemTotal=$(grep MemTotal /proc/meminfo | awk '{print $2}') #KBMemFree=$(grep MemFree /proc/meminfo | awk '{print $2}') #KBlet MemUsed=MemTotal-MemFreeMemPercent=$(awk "BEGIN {if($MemTotal==0){printf 100}else{printf \"%.2f\",$MemUsed*100/$MemTotal}}")report_MemTotal="$((MemTotal/1024))" "MB" #内存总容量(MB)report_MemFree="$((MemFree/1024))" "MB" #内存剩余(MB)report_MemUsedPercent=$(free | sed -n '2p' | gawk 'x = int(( $3 / $2 ) * 100) {print x}' | sed 's/$/%/')cat << EOF
【内存信息】
内存总容量(MB): ${report_MemTotal}
内存剩余量(MB):${report_MemFree}
内存使用率: ${report_MemUsedPercent}
EOF
}# 获取系统网络信息
get_net_info() {pri_ipadd=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}')pub_ipadd=$(curl ifconfig.me -s)gateway=$(ip route | grep default | awk '{print $3}')mac_info=$(ip link | egrep -v "lo" | grep link | awk '{print $2}')dns_config=$(egrep -v "^$|^#" /etc/resolv.conf)route_info=$(route -n)cat << EOF
【网络信息】
系统公网地址:${pub_ipadd}
系统私网地址:${pri_ipadd}
网关地址:${gateway}
MAC地址:${mac_info}
路由信息:
${route_info}
DNS 信息:
${dns_config}
EOF
}# 获取系统磁盘信息
get_disk_info() {disk_info=$(fdisk -l | grep "Disk /dev" | cut -d, -f1)disk_use=$(df -hTP | awk '$2!="tmpfs"{print}')disk_percent=$(free | sed -n '2p' | gawk 'x = int(( $3 / $2 ) * 100) {print x}' | sed 's/$/%/')disk_inode=$(df -hiP | awk '$1!="tmpfs"{print}')cat << EOF
【磁盘信息】
${disk_info}
磁盘使用: ${disk_use}
磁盘使用百分比: ${disk_percent}
inode信息: ${disk_inode}
EOF
}# 获取系统用户信息
get_sys_user() {login_user=$(awk -F: '{if ($NF=="/bin/bash") print $0}' /etc/passwd)ssh_config=$(egrep -v "^#|^$" /etc/ssh/sshd_config)sudo_config=$(egrep -v "^#|^$" /etc/sudoers | grep -v "^Defaults")host_config=$(egrep -v "^#|^$" /etc/hosts)crond_config=$(for cronuser in /var/spool/cron/*; dols ${cronuser} 2> /dev/null | cut -d/ -f5; egrep -v "^$|^#" ${cronuser} 2> /dev/null;echo "";done)cat << EOF
【用户信息】
系统登录用户:
${login_user}${line}
ssh 配置信息:
${ssh_config}${line}
sudo 配置用户:
${sudo_config}${line}
定时任务配置:
${crond_config}${line}
hosts 信息:
${host_config}
EOF
}# 获取CPU/内存占用TOP10
get_process_top_info() {top_title=$(top -b n1 | head -7 | tail -1)cpu_top10=$(top -b n1 | head -17 | tail -11)mem_top10=$(top -b n1 | head -17 | tail -10 | sort -k10 -r)cat << EOF
【TOP10】
CPU占用TOP10:
${cpu_top10}
内存占用TOP10:
${top_title}${mem_top10}
EOF
}show_dead_process() {printf "僵尸进程:\n"ps -al | gawk '{print $2,$4}' | grep Z
}get_all_info() {get_systatus_infoecho ${double_line}get_service_infoecho ${double_line}get_cpu_infoecho ${double_line}get_net_infoecho ${double_line}get_mem_infoecho ${double_line}get_disk_infoecho ${double_line}get_process_top_infoecho ${double_line}get_sys_user
}main() {while [[ 1 ]]doprintMenuread optionlocal index=$[ ${option} - 1 ]case ${options[${index}]} in"获取系统信息")get_systatus_info ;;"获取服务信息")get_service_info ;;"获取CPU信息")get_cpu_info ;;"获取系统网络信息")get_net_info ;;"获取系统内存信息")get_mem_info ;;"获取系统磁盘信息")get_disk_info ;;"获取CPU/内存占用TOP10")get_process_top_info ;;"获取系统用户信息")get_sys_user ;;"输出所有信息")get_all_info > sys.logprintf "${C_GREEN}信息已经输出到 sys.log 中。${C_RESET}\n\n";;"退出")exit ;;*)clearecho "抱歉,不支持此选项" ;;esacdone
}######################################## MAIN ########################################
printHeadInfo
main
printFootInfo
printf "${C_RESET}"
SPN 日常巡查脚本
SPN(Secret Private Network),面向业务的内网安全解决方案,即加密虚拟网络
#!/bin/bash
echo " ___ ___ ___/ /\ / /\ /__/\/ /:/_ / /::\ \ \:\/ /:/ /\ / /:/\:\ \ \:\/ /:/ /::\ / /:/~/:/ _____\__\:\/__/:/ /:/\:\ /__/:/ /:/ /__/::::::::\\ \:\/:/~/:/ \ \:\/:/ \ \:\~~\~~\/\ \::/ /:/ \ \::/ \ \:\ \__\/ /:/ \ \:\ \ \:\/__/:/ \ \:\ \ \:\\__\/ \__\/ \__\/
"
echo "SPN 日常巡查脚本输出"
# 清理屏幕
clearfunction bash_os() {# "系统基础信息"#内核信息kernel=$(uname -r)#操作系统版本release=$(cat /etc/redhat-release)#主机名称hostname=$HOSTNAME#当前时间及运行时间dateload=$(uptime | awk -F "," '{print $1}')# 当前登录用户数users=$(uptime | awk -F "," '{print $3}')echo -e "\n\033[32m############## 系统基础信息 #######\033[0m\n"echo -e "\033[32m------------------------------------\033[0m"echo -e "|内核信息:\033[31m $kernel \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|操作系统版本:\033[31m $release \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|当前时间及运行时间:\033[31m $dateload \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|当前登录用户数:\033[31m $users \033[0m"echo -e "\033[32m------------------------------------\033[0m"
}function memory() {# 内存相关数据统计`free -m`#总内存容量mem_total=$(free -m | awk '/Mem/{printf "%.2fG", $2/1024}')# 用户程序占用内存量mem_user=$(free -m | awk '/Mem/{printf "%.2fG", $3/1024}')# 多进程共享占用内存量mem_shared=$(free -m | awk '/Mem/{printf "%.2fG", $5/1024}')#缓存占用内存量mem_buff_cache=$(free -m | awk '/Mem/{printf "%.fMB", $(NF-1)}')#空闲内存容量mem_free=$(free -m | awk '/Mem/{printf "%.2fG", $4/1024 }')# 剩余可用内存容量mem_available=$(free -m | awk 'NR==2{printf "%.2fG",$NF/1024}')# 可用内存使用占比mem_percentage=$(free -m | awk '/Mem/{printf "%.2f", $NF/$2*100}')#总的交换分区容量swap_total=$(free -m | awk '/Swap/{printf "%.2fG", $2/1024}')#用户使用的交换分区容量swap_user=$(free -m | awk '/Swap/{printf "%.2fG",$3/1024}')#剩余交换分区容量swap_free=$(free -m | awk '/Swap/{printf "%.2fG",$4/1024}')#可用交换分区占比swap_percentage=$(free -m | awk '/Swap/{printf "%.2f",$4/$2*100}')#占用内存资源最多的10个进程列表top_proc_mem=$(ps --no-headers -eo rss,args | sort -k1 -n -r | head -10)echo -e "\n\033[32m################## 内存 ############\033[0m\n"echo -e "\033[32m------------------------------------\033[0m"echo -e "|总内存容量:\033[31m $mem_total \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|用户程序内存量:\033[31m $mem_user \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|多进程共享内存量:\033[31m $mem_shared \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|缓存占用内存量:\033[31m $mem_buff_cache \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|空闲内存容量:\033[31m $mem_free \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|剩余可用内存容量:\033[31m $mem_available \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|可用内存百分比:\033[31m $mem_percentage% \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "\033[32m############## 交换分区 #############\033[0m\n"echo -e "\033[32m------------------------------------\033[0m"echo -e "总的交换分区容量:\033[31m $swap_total \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|用户使用的交换分区容量:\033[31m $swap_user \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|剩余交换分区容量:\033[31m ${swap_free}"echo -e "\033[32m------------------------------------\033[0m"if [ $(free -m | awk '/Swap/{print $2}') -ne 0 ]; thenecho -e "|可用交换分区占比:\033[31m $swap_percentage% \033[0m"echo -e "\033[32m------------------------------------\033[0m"fiecho -e "|占用内存资源最多的10个进程列表:"echo -e "\033[31m$top_proc_mem% \033[0m"echo -e "\033[32m------------------------------------\033[0m"
}function cpu() {#CPU型号cpu_info=$(LANG=C lscpu | awk -F: '/Model name/ {print $2}')#CPU内核数量cpu_core=$(awk '/processor/{core++} END{print core}' /proc/cpuinfo)#CPU最近1/5/15分钟的平均负载load1515=$(uptime | sed 's/,/ /g' | awk '{for(i=NF-2;i<=NF;i++)print $i }' | xargs)#发生中断数量irq=$(vmstat 1 1 | awk 'NR==3{print $11}')#上下文切换数量cs=$(vmstat 1 1 | awk 'NR==3{print $12}')#占用CPU资源最多的10个进程列表top_proc_cpu=$(ps --no-headers -eo %cpu,args | sort -k1 -n -r | head -10)echo -e "\n\033[32m################## CPU 相关 ############\033[0m\n"echo -e "\033[32m------------------------------------\033[0m"echo -e "|CPU型号:\033[31m$cpu_info \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|CPU内核数量:\033[31m$cpu_core \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|CPU最近1/5/15分钟的平均负载:\033[31m$load1515 \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|CPU中断数量:\033[31m$irq \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|上下文切换数量:\033[31m$cs \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|占用CPU资源最多的10个进程列表:"echo -e "\033[31m$top_proc_cpu \033[0m"echo -e "\033[32m------------------------------------\033[0m"}function disk_io() {#分区挂载信息disk=$(df -h)# 磁盘总数disk_total=$(vmstat -D | awk 'NR==1{print $1}')# 分区总数disk_sub=$(vmstat -D | awk 'NR==2{print $1}')#磁盘分区信息lsblk_=$(lsblk -n)#写入磁盘的总块数bo=$(vmstat 1 1 | awk 'NR==3{print $10}')#从磁盘读出的块数bi=$(vmstat 1 1 | awk 'NR==3{print $9}')#每秒写磁盘块的速率wa=$(vmstat 1 1 | awk 'NR==3{print $16}')echo -e "\n\033[32m################## 磁盘IO 相关 ############\033[0m\n"echo -e "\033[32m------------------------------------\033[0m"echo -e "|磁盘总数:\033[31m$disk_total \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|分区总数:\033[31m$disk_sub \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|磁盘分区信息:"echo -e "\033[31m$lsblk_ \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|写入磁盘的总块数:\033[31m$bo \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|从磁盘读出的块数:\033[31m$bi \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|每秒写磁盘块的速率:\033[31m$wa \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|分区挂载信息:"echo -e "\033[31m$disk \033[0m"echo -e "\033[32m------------------------------------\033[0m"}function procs() {#进程数量procs=$(ps aux | wc -l)#用户的最大进程数ulimit_=$(ulimit -u)#内核设置的最大进程数pid_max=$(sysctl kernel.pid_max | awk '{print $3}')echo -e "\n\033[32m################## 进程 相关 ############\033[0m\n"echo -e "\033[32m------------------------------------\033[0m"echo -e "|进程数量:\033[31m$procs \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|用户的最大进程数:\033[31m$ulimit_ \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|内核设置的最大进程数:\033[31m$pid_max \033[0m"echo -e "\033[32m------------------------------------\033[0m"}function network() {#获取网卡流量信息,接收|发送的数据流量,单位为字节(bytes)net_monitor=$(cat /proc/net/dev | tail -n +3 | awk 'BEGIN{ print "网卡名称 入站数据流量(bytes) 出站数据流量(bytes)"} {print $1,$2,$10}' | column -t)#获取暴露端口信息ip_port=$(ss -ntulpa)#本地IP地址列表localip=$(ip a s | awk '/inet /{print $2}' )echo -e "\n\033[32m################## 网络 相关 ############\033[0m\n"echo -e "|本地IP地址列表:"echo -e "\033[31m$localip \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|获取网卡流量信息:"echo -e "\033[31m$net_monitor \033[0m"echo -e "\033[32m------------------------------------\033[0m"echo -e "|获取暴露端口信息:"echo -e "\033[31m$ip_port \033[0m"echo -e "\033[32m------------------------------------\033[0m"}case $1 in
all)bash_osmemorycpudisk_ioprocsnetwork;;
bash_os)bash_os;;
memory)memory;;
cpu)cpu;;
disk_io)disk_io;;
procs)procs;;
network)network;;
*)echo "Usage: bash_os|memory|cup|disk_io|procs|network|all";;
esac
ffmpeg脚本
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序
打开进程,并判断进程数量
原版本:
#!/bin/bash
ffmpegPid = $( ps -ef | grep -E 'ffmpeg.*$1$2$3' | grep -v 'grep' | awk '{print $2}')
if [ -z "$ffmpegPid" ]
thenthreadNum = $( ps -ef | grep ffmpeg | grep -v 'grep' | wc -l | awk '{print $1}')if [$threadNum -gt 10]then# 线程数大于10个,需要干掉ffmpeg线程echo threadNum too more!for thread in $threadNumdokill -9 ${thread}doneelsenohup ffmpeg -re -rtsp_transport tcp -i "rtsp://ip:port/dss/monitor/params?cameraid=$1%24$2&substream=$3" -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 1280x720 -q 10 $4 > /Users/chuxiaowei/ffmpeg$1$2$3.log 2>&1 &ps -ef | grep -E 'ffmpeg.*$1$2$3' | grep -v 'grep' | awk '{print $2}'fi
elseps -ef | grep -E 'ffmpeg.*$1$2$3' | grep -v 'grep' | awk '{print $2}'
fi
改进之后:
#!/bin/bash
ffmpegPid = $( ps -ef | grep -E 'ffmpeg.*$1$2$3' | grep -v 'grep' | awk '{print $2}')
if [ -z "$ffmpegPid" ]
thennohup ffmpeg -re -rtsp_transport tcp -i "rtsp://ip:port/dss/monitor/params?cameraid=$1%24$2&substream=$3" -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 1280x720 -q 10 $4 > /root/ffmpeg$1$2$3.log 2>&1 &ps -ef | grep -E 'ffmpeg.*$4*' | grep -v 'grep' | awk '{print $2}'
fi
关闭进程
#关闭进程
#!/bin/bash
ps -ef | grep -E 'ffmpeg.*$1*' | grep -v 'grep' | awk '{print $2}' | xargs kill
java jar包启动-剔除Pom中依赖
#!/bin/bash
pid=$(ps -ef | grep java | grep -E '*rtsptortmp.*' | awk '{print $2}')
echo "pid = $pid"
if [ $pid ];thenkill -9 $pidecho "kill the process rtsptortmp pid = $pid"
finohup java -Dloader.path=/root/rtsptortmplib -jar rtsptortmp-1.0-SNAPSHOT.jar --spring.profiles.active=prod > /root/logs/rtsptortmp.log 2>&1 &
tail -f /root/logs/rtsptortmp.log
Java jar包通用启动脚本
eg:
./start.sh java.jar
#!/bin/bash
pid=$(ps -ef | grep java | grep -E '*$1*' | awk '{print $2}')
echo "pid = $pid"
if [ $pid ];thenkill -9 $pidecho "kill the process pid = $pid"
finohup java -jar -Xms256m -Xmx256m $1 --spring.profiles.active=prod > /root/logs/$1.log 2>&1 &
tail -f /root/logs/$1.log
查看centos配置信息脚本
#!/bin/bashecho ======= cpu个数: =======
grep 'physical id' /proc/cpuinfo | sort -u | wc -lecho ======= cpu核数: =======
cat /proc/cpuinfo | grep "cpu cores" | uniqecho ======= cpu型号: =======
cat /proc/cpuinfo | grep 'model name' |uniqecho ======= cpu内核频率: =======
cat /proc/cpuinfo |grep MHz|uniqecho ======= cpu统计信息: =======
lscpuecho ======= 内存总数: =======
cat /proc/meminfo | grep MemTotalecho ======= 内核版本: =======
cat /proc/versionecho ======= 操作系统内核信息: =======
uname -aecho ======= 磁盘信息: =======
fdisk -l
Jenkins项目打包发布脚本
#!/bin/bash//传入的war包名称
name=$1
//war包所在目录
path=$2
//上传的war包位置
path_w=$3
//如果项目正在运行就杀死进程
if [ -f "$path/$name" ];thenecho "delete the file $name"rm -f $path/$name
elseecho "the file $name is not exist"
fi
//把jenkins上传的war包拷贝到我们所在目录
cp $path_w/$name $path/
echo "copy the file $name from $path_w to $path"//获取该项目正在运行的pid
pid=$(ps -ef | grep java | grep $name | awk '{print $2}')
echo "pid = $pid"
//如果项目正在运行就杀死进程
if [ $pid ];thenkill -9 $pidecho "kill the process $name pid = $pid"
elseecho "process is not exist"
fi
//要切换到项目目录下才能在项目目录下生成日志
cd $path
//防止被jenkins杀掉进程 BUILD_ID=dontKillMe
BUILD_ID=dontKillMe
//启动项目
nohup java -server -Xms256m -Xmx512m -jar -Dserver.port=20000 $name >> nohup.out 2>&1 &
//判断项目是否启动成功
pid_new=$(ps -ef | grep java | grep $name | awk '{print $2}')
if [ $? -eq 0 ];then
echo "this application $name is starting pid_new = $pid_new"
else
echo "this application $name startup failure"
fi
echo $! > /var/run/myClass.pid
echo "over"
注意:SQL Server以下脚本目前还不完善(AlwaysOn相关 到 Agent作业备份)
AlwaysOn相关
节点切换监控
节点切换作业控制
SQL Server 邮件脚本
Mysql-使用脚本进行分库分表备份
数据库-数据备份
备份作业
数据一致性检查
Agent作业备份
大部分脚本针对于中小数据库,由于工作性质涉及很多客户部署维护作业,所以力求总结出一套比较完善的脚本,一键部署。
AlwaysOn相关
节点切换监控
declare @role VARCHAR(8000); declare @email_conetent varchar(8000);--存放邮件正文 declare @name varchar(100);declare @lastsend int;
declare @subject_str varchar(100);set @name =(select @@servername)
set @subject_str = @name + 'always on 预警'set @role=(SELECT role FROM sys.dm_hadr_availability_replica_states WHERE is_local=1)set @lastsend = (select isnull(datediff(MINUTE,max(send_request_date), getdate()),6000) from [msdb].[dbo].[sysmail_mailitems] where subject = @subject_str)if @role >1 and @lastsend > 30 ----30分钟发送一次begin set @email_conetent=(@name+'当前节点不是主节点,发生故障转移')print(@email_conetent)
print(@lastsend)
--if @lastsend > 1--发送邮件 --邮件正文内容EXEC msdb.dbo.sp_send_dbmail @profile_name = 'DB-mail', --配置文件名称@recipients = 'KK_XXX@163.COM', --收件email地址@subject = @subject_str, --邮件主题@body = @email_conetent end
节点切换作业控制
作业可以采用手动控制或如下脚本,也可以修改作业在作业执行前增加节点判断
--------------------------判断当前节点是否为主节点 如果不是则禁用作业 -------
------------节点 切换为主节点则启用JOB ------------
DECLARE @ROLE tinyint
DECLARE @ENABLE tinyint
----判断是否是主节点 --1 主节点SELECT @role=role FROM sys.dm_hadr_availability_replica_states WHERE is_local=1--判断JOB状态 --0 禁用 1 启用
--以syspolicy_purge_history 为 参照 --如果 禁用或删除syspolicy_purge_history请修改 @ENABLE下段查询
SELECT @ENABLE = [ENABLED]
FROM MSDB.[dbo].[sysjobs]
WHERE NAME = 'syspolicy_purge_history'-----第一次切换 辅助节点没有创建CDC作业 job 则创建作业 [category_id] = 13 CDC LOG SCAN JOB
if not exists (select 1 from msdb.dbo.sysjobs where [category_id]= 13 or [category_id]= 16 ) and @ROLE = 1
begin
EXEC sys.sp_cdc_add_job @job_type = 'capture';
EXEC sys.sp_cdc_add_job @job_type = 'cleanup';
end---primary and job disable set job enable
IF @ROLE = 1 and @ENABLE = 0
BEGIN----如果存在原有作业为禁用,无法确定哪些JOB需要开启....所以此处最好手动维护作业的启用和禁用
EXEC msdb.dbo.sp_update_job@job_name = N'XXXXX',@enabled = 1 ;-----执行 CDC
EXEC msdb.dbo.sp_start_job @job_name = N'cdc.XX_capture'
EXEC msdb.dbo.sp_start_job @job_name = N'cdc.XX_cleanup'
end
---not primary and job enable set disable
IF @ROLE <> 1 and @ENABLE = 1
BEGIN
----如果存在原有作业为禁用,无法确定哪些JOB需要开启....所以此处最好手动维护作业的启用和禁用
EXEC msdb.dbo.sp_update_job@job_name = N'XXXXX',@enabled = 0 ;END
SQL Server 邮件脚本
邮件主要用来监控作业是否运行成功,如果您已经配置了类似zabbix等软件请忽略
配置邮件服务
--SQL Server 并没有内置邮件服务器(Mail Server),它跟我们发送邮件一样,需要用户名和密码通过 SMTP(Simple Message Transfer Protocol)去连接邮件服务器。我们想让 SQL Server 来发送邮件,首先要告诉它用户名称,密码,服务器地址,网络传送协议,邮件服务器的端口。。。等信息。
-- 以下脚本实现了数据库邮件的配置:
----下面是具体的配置邮件步骤
----在 sa 系统帐户下运行。
--
--1. 启用 SQL Server 邮件功能。
use master
go
exec sp_configure 'show advanced options',1
go
reconfigure with override
go
exec sp_configure 'Database Mail XPs',1
go
reconfigure with override
go
--2. 在 SQL Server 中添加邮件帐户(account)
exec msdb..sysmail_add_account_sp@account_name = '163yx' -- 邮件帐户名称(SQL Server 使用),@email_address = 'kk_XXXX@163.com' -- 发件人邮件地址,@display_name = null -- 发件人姓名,@replyto_address = null,@description = null,@mailserver_name = 'smtp.163.com' -- 邮件服务器地址,@mailserver_type = 'SMTP' -- 邮件协议(SQL 2005 只支持 SMTP),@port = 25 -- 邮件服务器端口,@username = 'kk_XXXX@163.com' -- 用户名,@password = 'XXXXX' -- 密码,@use_default_credentials = 0,@enable_ssl = 0,@account_id = null--3. 在 SQL Server 中添加 profile
exec msdb..sysmail_add_profile_sp @profile_name = 'dba_profile3' -- profile 名称 ,@description = 'dba mail profile' -- profile 描述 ,@profile_id = null-- 在 SQL Server 中映射 account 和 profile
exec msdb..sysmail_add_profileaccount_sp @profile_name = 'dba_profile3' -- profile 名称 ,@account_name = '163yx' -- account 名称 ,@sequence_number = 1 -- account 在 profile 中顺序 --5. 利用 SQL Server Database Mail 功能发送邮件。
exec msdb..sp_send_dbmail @profile_name = 'dba_profile3' -- profile 名称 ,@recipients = 'kk_XXXX@163.com;kk2_XXXX@163.com' -- 收件人邮箱 ,@subject = 'SQL Server Mail 测试' -- 邮件标题 ,@body = 'Hello Mail!测试' -- 邮件内容 ,@body_format = 'TEXT' -- 邮件格式 ,@file_attachments = 'c:\a.txt' --邮件附件--6. 查看邮件发送情况:
use msdb
go
select * from sysmail_allitems
select * from sysmail_mailitems
select * from sysmail_event_log --如果不是以 sa 帐户发送邮件,则可能会出现错误:
--
--Msg 229, Level 14, State 5, Procedure sp_send_dbmail, Line 1
--EXECUTE permission denied on object 'sp_send_dbmail', database 'msdb', schema 'dbo'.
--
--这是因为,当前 SQL Server 登陆帐户(login),在 msdb 数据库中没有发送数据库邮件的权限,需要加入 msdb 数据库用户,并通过加入 sp_addrolemember 角色赋予权限。假设该SQL Server 登陆帐户名字为 “dba”
--
--use msdb
--go
--
--create user dba for login dba
--go
--
--exec dbo.sp_addrolemember @rolename = 'DatabaseMailUserRole',
-- @membername = 'dba'
--go
--
--此时,再次发送数据库邮件,仍可能有错误:
--
--Msg 14607, Level 16, State 1, Procedure sp_send_dbmail, Line 119
--profile name is not valid
--
--虽然,数据库用户 “dba” 已经在 msdb 中拥有发送邮件的权限了,但这还不够,他还需要有使用 profile:“dba_profile” 的权限。
--
--use msdb
--go
--
--exec sysmail_add_principalprofile_sp @principal_name = 'dba'
-- ,@profile_name = 'dba_profile'
-- ,@is_default = 1
--
--从上面的参数 @is_default=1 可以看出,一个数据库用户可以在多个 mail profile 拥有发送权限。--EXEC msdb.dbo.sysmail_configure_sp 'MaxFileSize', 100000000 (字节)设置邮件.note
配置操作员
USE [msdb]
GO
EXEC msdb.dbo.sp_add_operator @name=N'mail_user2', @enabled=1, @pager_days=0, @email_address=N'KK_XXXX.163.COM'
GO
Mysql-使用脚本进行分库分表备份
[root@ctos3 ~]# cat bak.sh
#!/bin/bashMYUSER="root"
MYPASS="guoke123"
MYLOG="mysql -u$MYUSER -p$MYPASS -e"
MYDUMP="mysqldump -u$MYUSER -p$MYPASS -x -F"
DBLIST=$($MYLOG "show databases;" | sed 1d | grep -Ev 'info|mysq|per|sys')
DIR=/backup
[ ! -d $DIR ] && mkdir $DIR
cd $DIRfor dbname in $DBLIST
doTABLIST=$($MYLOG "show tables from $dbname;" | sed 1d)
for tabname in $TABLIST
domkdir -p $DIR/$dbname$MYDUMP $dbname $tabname --events |gzip > $DIR/${dbname}/${tabname}_$(date +%F_%T).sql.gz
done
done
数据库-数据备份
备份方案:每天全备份、6小时一次差异备份、一小时一次日志备份。
备份存储过程
存储过程创建后会保留在master库中,存储过程主要控制备份逻辑,备份路径等。
存储过程中只有一个类型参数,用于控制全备/差异/日志备份,可根据需要修改。
USE [master]
GO/****** Object: StoredProcedure [dbo].[sp_BackupDatabase] Script Date: 01/22/2015 13:52:46 ******/
SET ANSI_NULLS ON
GOSET QUOTED_IDENTIFIER ON
GO-- Author: KK-- Create date: 2016-09-27-- Description: 备份数据库,备份路径F:\KK_BackUp\ 可自行修改-- http://www.cnblogs.com/double-K/-- Parameter1: 备份类型 F=全部, D=差异, L=日志alter PROCEDURE [dbo].[sp_BackupDatabase]
@backupType CHAR(1)
AS
BEGIN
SET NOCOUNT ON;declare @filepath_backup varchar(100)
declare @dateTime varchar(30),@del_time_stamp varchar(50)
DECLARE @sqlCommand NVARCHAR(1000)---创建数据库对应文件夹
EXECUTE master.dbo.xp_create_subdir N'F:\KK_BackUp\Full\'
EXECUTE master.dbo.xp_create_subdir N'F:\KK_BackUp\Difference\'
EXECUTE master.dbo.xp_create_subdir N'F:\KK_BackUp\Log_Bak\'IF @backupType = 'F'
set @filepath_backup='F:\KK_BackUp\Full\'
IF @backupType = 'D'
set @filepath_backup='F:\KK_BackUp\Difference\'
IF @backupType = 'L'
set @filepath_backup='F:\KK_BackUp\Log_Bak\'SET ANSI_WARNINGS OFF
SET @dateTime = replace(convert(varchar,current_timestamp, 112)+'_'+convert(varchar,current_timestamp, 108),':','')----删除超过3天的备份文件
DECLARE @delete_time datetime
set @delete_time = getdate() - 3EXECUTE master.dbo.xp_delete_file 0,N'F:\kk_backup',N'trn',@delete_time,1
EXECUTE master.dbo.xp_delete_file 0,N'F:\kk_backup',N'bak',@delete_time,1SELECT @dateTime = replace(convert(varchar,current_timestamp, 112)+'_'+convert(varchar,current_timestamp, 108),':','')declare db_info cursor for
SELECT NAME,recovery_model FROM MASTER.SYS.databases
where state = 0 ---只处理online的数据库
and name not in ('tempdb','ReportServerTempDB','ReportServer') ----填写不需要备份的数据库declare @databaseName nvarchar(128)
declare @recovery_model int
OPEN db_info
fetch next from db_info into @databaseName,@recovery_model
while @@fetch_status=0
Begin ---recovery_model 1 : FULL 2 : BULK_LOGGED 3:SIMPLE
---系统数据库只全备IF @backupType = 'F' SET @sqlCommand = 'BACKUP DATABASE '+ @databaseName +' TO DISK = '''+ @filepath_backup + ''+ @databaseName +'_Full_'+@dateTime+'.BAK'' with STATS = 10, INIT, COMPRESSION, CHECKSUM 'IF @backupType = 'D' and @databaseName not in ('master','msdb','model')SET @sqlCommand = 'BACKUP DATABASE '+ @databaseName +' TO DISK = '''+ @filepath_backup + ''+ @databaseName + '_Diff_' + @dateTime + '.BAK '' WITH DIFFERENTIAL, STATS = 10, INIT, COMPRESSION'IF @backupType = 'L' and @recovery_model <> 3 and @databaseName not in ('master','msdb','model')
SET @sqlCommand = 'BACKUP LOG '+ @databaseName +' TO DISK = '''+ @filepath_backup + '' + @databaseName +'_Log_' + @dateTime + '.TRN'' with STATS = 10, INIT, COMPRESSION'
print @sqlCommandEXECUTE sp_executesql @sqlCommand fetch next from db_info into @databaseName,@recovery_model
End close db_info
deallocate db_info PRINT '-- Backup completed successfully at '+convert(varchar, getdate(), 120) SET ANSI_WARNINGS ON
END
GO
备份作业
备份作业很简单,就是调用存储过程用计划控制备份频率
-- Author: KK-- Create date: 2016-09-27-- Description: 备份数据库,全备份每天一次 0点执行,差异备份6小时一次,日志备份1小时一次-- http://www.cnblogs.com/double-K/--需要备份的数据库未使用参数传递,而是选择在存储过程中指定,当添加新库时不需要修改任何脚本-- Parameter1: 备份类型 F=全部, D=差异, L=日志-------------------完整备份作业-----------------
USE [msdb]
GO/****** Object: Job [FULL_BACKUP] Script Date: 2016/9/30 12:13:12 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object: JobCategory [[Uncategorized (Local)]]] Script Date: 2016/9/30 12:13:12 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackENDDECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'FULL_BACKUP', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @delete_level=0, @description=N'系统全备份', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object: Step [FULL_STEP1] Script Date: 2016/9/30 12:13:12 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'FULL_STEP1', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N'[dbo].[sp_BackupDatabase] ''F''', @database_name=N'master', @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'EVERY_1d_zero', @enabled=1, @freq_type=4, @freq_interval=1, @freq_subday_type=1, @freq_subday_interval=0, @freq_relative_interval=0, @freq_recurrence_factor=0, @active_start_date=20160930, @active_end_date=99991231, @active_start_time=0, @active_end_time=235959, @schedule_uid=N'813653e1-4128-4f47-b378-5a26b49085d0'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:GO-------------------日志备份作业------------------
USE [msdb]
GO/****** Object: Job [LOG_BACKUP] Script Date: 2016/9/30 12:13:25 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object: JobCategory [[Uncategorized (Local)]]] Script Date: 2016/9/30 12:13:25 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackENDDECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'LOG_BACKUP', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @delete_level=0, @description=N'系统日志备份', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object: Step [LOG_STEP1] Script Date: 2016/9/30 12:13:25 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'LOG_STEP1', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N'[dbo].[sp_BackupDatabase] ''L''', @database_name=N'master', @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'EVERY_1h', @enabled=1, @freq_type=4, @freq_interval=1, @freq_subday_type=8, @freq_subday_interval=1, @freq_relative_interval=0, @freq_recurrence_factor=0, @active_start_date=20160930, @active_end_date=99991231, @active_start_time=0, @active_end_time=235959, @schedule_uid=N'3d5ad87e-4f1d-46ef-9a24-e0f99c7d5c20'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:GO----------------------差异备份作业
USE [msdb]
GO/****** Object: Job [DIFF_BACKUP] Script Date: 2016/9/30 12:13:19 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object: JobCategory [[Uncategorized (Local)]]] Script Date: 2016/9/30 12:13:19 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackENDDECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'DIFF_BACKUP', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @delete_level=0, @description=N'无描述。', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object: Step [DIFF_STEP1] Script Date: 2016/9/30 12:13:19 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'DIFF_STEP1', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N'[dbo].[sp_BackupDatabase] ''D''', @database_name=N'master', @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'EXERY_6h', @enabled=1, @freq_type=4, @freq_interval=1, @freq_subday_type=8, @freq_subday_interval=6, @freq_relative_interval=0, @freq_recurrence_factor=0, @active_start_date=20160930, @active_end_date=99991231, @active_start_time=0, @active_end_time=235959, @schedule_uid=N'f7514c1b-128f-4ae4-8361-9dbcbbff66c6'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:GO
数据一致性检查
-- Author: KK-- Create date: 2016-09-27-- Description: 数据库一致性检查,每周运行及时发现数据库损坏-- 本脚本针对于中小型数据库,当数据库达到一定规模超过T级或有大表使用计算列等,可适当拆分或调整,以免checkdb时间超过维护时间窗口而影响业务-- E:\checkdb_report.txt , 输出文件的路径,检查出的错误信息或被记录进去,或直接通过作业记录查看-- http://www.cnblogs.com/double-K/--需要备份的数据库未使用参数传递,而是选择在存储过程中指定,当添加新库时不需要修改任何脚本--脚本针对中小数据库,如果数据库超过1T甚至更大,CHECKDB也是必要操作,但需要拆分文件组或更精细化检查以降低每次检查的时间,保证在指定的维护窗口完成任务。USE [msdb]
GO/****** Object: Job [CHECKDB] Script Date: 09/30/2016 15:16:01 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object: JobCategory [[Uncategorized (Local)]]] Script Date: 09/30/2016 15:16:01 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackENDDECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'CHECKDB', @enabled=1, @notify_level_eventlog=0, @notify_level_email=0, @notify_level_netsend=0, @notify_level_page=0, @delete_level=0, @description=N'数据库一致性检查,可以发现数据库是否有损坏。', @category_name=N'[Uncategorized (Local)]', @owner_login_name=N'sa', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object: Step [CHECKDB] Script Date: 09/30/2016 15:16:01 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'CHECKDB', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'TSQL', @command=N'
declare db_info cursor for
SELECT NAME FROM MASTER.SYS.databases
where state = 0 ---只处理online的数据库
and name not in (''tempdb'',''ReportServerTempDB'',''ReportServer'') ----填写不需要检查的数据库declare @databaseName nvarchar(128)
declare @recovery_model int
DECLARE @sqlCommand NVARCHAR(1000)
OPEN db_info
fetch next from db_info into @databaseName
while @@fetch_status=0
Begin
SET @sqlCommand = ''DBCC CHECKDB(N''''''+ @databaseName + '''''') WITH NO_INFOMSGS''
print @sqlCommandEXECUTE sp_executesql @sqlCommand
fetch next from db_info into @databaseName
End
close db_info
deallocate db_info ', @database_name=N'master', @output_file_name=N'E:\checkdb_report.txt', --输出文件的路径,检查出的错误信息或被记录进去,或直接通过作业记录查看@flags=4
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'sunday_2am', @enabled=1, @freq_type=8, @freq_interval=1, @freq_subday_type=1, @freq_subday_interval=0, @freq_relative_interval=0, @freq_recurrence_factor=1, @active_start_date=20160930, @active_end_date=99991231, @active_start_time=20000, @active_end_time=235959, @schedule_uid=N'3ade533f-5ce1-434f-98ff-b4509b2ca582'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:GO
Agent作业备份
备份作业可以通过备份MSDB完成,但是保留一份脚本还是不错的,脚本为存储过程,建议一个周或一个月备份一次,可使用JOB 调用存储过程。
USE [master]
GO/****** Object: StoredProcedure [dbo].[DumpJobsql] Script Date: 02/07/2014 11:38:46 ******/
SET ANSI_NULLS ON
GOSET QUOTED_IDENTIFIER ON
GOalter PROCEDURE [dbo].[usp_DumpJobsql]
AS
BEGIN-- Author: KK-- Create date: 2016-09-27-- Description: 备份JOB,目前不支持邮件-- 生成数据一份保留在master的zzz_temp_JOB_bcp表中,另外会在目标位置生成一个 job_日期.sql-- http://www.cnblogs.com/double-K/SET NOCOUNT ONDECLARE @SV nvarchar(4)DECLARE @i_enabled TINYINTDECLARE @sql VARCHAR(max)DECLARE @i_job_name VARCHAR(1000)DECLARE @i_notify_level_eventlog INTDECLARE @i_notify_level_email INTDECLARE @i_notify_level_netsend INTDECLARE @i_notify_level_page INTDECLARE @i_delete_level INTDECLARE @i_description VARCHAR(1000)DECLARE @i_category_name VARCHAR(1000)DECLARE @i_owner_login_name VARCHAR(1000)DECLARE @i_category_class INTDECLARE @i_start_step_id INT DECLARE @i_step_name VARCHAR(1000) DECLARE @i_step_id INT DECLARE @i_cmdexec_success_code INT DECLARE @i_on_success_action INT DECLARE @i_on_success_step_id INT DECLARE @i_on_fail_action INT DECLARE @i_on_fail_step_id INT DECLARE @i_retry_attempts BIGINT DECLARE @i_retry_interval INT DECLARE @i_os_run_priority INT DECLARE @i_subsystem VARCHAR(1000) DECLARE @i_command VARCHAR(8000)DECLARE @i_database_name VARCHAR(100) DECLARE @i_flags INT DECLARE @i_class VARCHAR(10) ,@i_type VARCHAR(10)DECLARE @c_jobid UNIQUEIDENTIFIER ,@c_categoryid INTDECLARE @loop_stepid INTDECLARE @m_stepid INT DECLARE @loop_scheduleid INTDECLARE @m_scheduleid INTDECLARE @i_schedule_enabled TINYINTDECLARE @i_freq_type INTDECLARE @i_schedule_name VARCHAR(1000) DECLARE @i_freq_interval INT DECLARE @i_freq_subday_type INTDECLARE @i_freq_subday_interval INTDECLARE @i_freq_relative_interval INTDECLARE @i_freq_recurrence_factor INTDECLARE @i_active_start_date BIGINT DECLARE @i_active_end_date BIGINT DECLARE @i_active_start_time BIGINT DECLARE @i_active_end_time BIGINT DECLARE @i_schedule_uid VARCHAR(1000)SET @i_class = 'JOB'SET @i_type = 'LOCAL'if exists (select 1 from sys.objects where name = 'zzz_temp_JOB_bcp')begin delete from master..zzz_temp_JOB_bcpendelsebegin create table zzz_temp_JOB_bcp(name nvarchar(100),text nvarchar(max),sv nvarchar(4),Bak_date nvarchar(10))endDECLARE job CURSOR FOR SELECT a.job_id ,a.category_id,'服务器XX' as SV FROM msdb.dbo.sysjobs a , msdb.dbo.syscategories cWHERE a.category_id = c.category_id AND c.name NOT LIKE '%Database Maintenance%' AND c.name NOT LIKE '%REPL%'AND c.name <> 'Log Shipping'AND a.name <> 'syspolicy_purge_history'----如果需要可多服务器备份--union all--select a.job_id ,a.category_id,'服务器XXX' --from --opendatasource('SQLOLEDB','Data Source=XX.XX.XX.XX;User ID=XX;Password=XX').msdb.dbo.sysjobs a,--opendatasource('SQLOLEDB','Data Source=XX.XX.XX.XX;User ID=XX;Password=XX').msdb.dbo.syscategories c--WHERE a.category_id = c.category_id -- AND c.name NOT LIKE '%Database Maintenance%' -- AND c.name NOT LIKE '%REPL%'-- AND c.name <> 'Log Shipping'-- AND a.name <> 'syspolicy_purge_history'OPEN jobFETCH job INTO @c_jobid ,@c_categoryid,@SVWHILE @@FETCH_STATUS = 0BEGINSET @sql = ''SELECT @i_job_name = a.name ,@i_enabled = [enabled] ,@i_notify_level_eventlog = notify_level_eventlog ,@i_notify_level_email = notify_level_email ,@i_notify_level_netsend = notify_level_netsend ,@i_notify_level_page = notify_level_page ,@i_delete_level = delete_level ,@i_description = [description] ,@i_category_name = c.name ,@i_owner_login_name = ISNULL(SUSER_SNAME(a.owner_sid), N'''') ,@i_category_class = category_class FROM msdb.dbo.sysjobs a ,msdb.dbo.syscategories cWHERE a.category_id=c.category_id AND a.job_id=@c_jobid AND a.category_id = @c_categoryidSET @sql=@sql+CHAR(13)+CHAR(10) + 'USE [msdb]'SET @sql=@sql+CHAR(13)+CHAR(10) + 'GO'SET @sql=@sql+CHAR(13)+CHAR(10) + '/****** Object: Job ['+ @i_job_name +'] Script Date: '+CONVERT(VARCHAR,GETDATE(),22)+' ******/' SET @sql=@sql+CHAR(13)+CHAR(10) + 'BEGIN TRANSACTION' SET @sql=@sql+CHAR(13)+CHAR(10) + 'DECLARE @ReturnCode INT' SET @sql=@sql+CHAR(13)+CHAR(10) + 'SELECT @ReturnCode = 0'SET @sql=@sql+CHAR(13)+CHAR(10) + '/****** Object: JobCategory ['+ @i_category_name +'] Script Date: 08/20/2016 12:35:16 ******/'SET @sql=@sql+CHAR(13)+CHAR(10) + 'IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'''+ @i_category_name +''' AND category_class='+ CAST(@i_category_class AS VARCHAR) +' )' SET @sql=@sql+CHAR(13)+CHAR(10) + 'BEGIN' SET @sql=@sql+CHAR(13)+CHAR(10) + 'EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'''+ @i_class +''', @type=N'''+ @i_type +''', @name=N'''+ @i_category_name +'''' SET @sql=@sql+CHAR(13)+CHAR(10) + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback'SET @sql=@sql+CHAR(13)+CHAR(10) + '' SET @sql=@sql+CHAR(13)+CHAR(10) + 'END'SET @sql=@sql+CHAR(13)+CHAR(10) + ''SET @sql=@sql+CHAR(13)+CHAR(10) + 'DECLARE @jobId BINARY(16)' SET @sql=@sql+CHAR(13)+CHAR(10) + 'EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'''+ @i_job_name +''',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @enabled='+ CAST(@i_enabled AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @notify_level_eventlog='+ CAST(@i_notify_level_eventlog AS VARCHAR) +','SET @sql=@sql+CHAR(13)+CHAR(10) + ' @notify_level_email='+ CAST(@i_notify_level_email AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @notify_level_netsend='+ CAST(@i_notify_level_netsend AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @notify_level_page='+ CAST(@i_notify_level_page AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @delete_level='+ CAST(@i_delete_level AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @description=N'''+ @i_description +''',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @category_name=N'''+ @i_category_name +''',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @owner_login_name=N'''+ @i_owner_login_name +''', @job_id = @jobId OUTPUT' SET @sql=@sql+CHAR(13)+CHAR(10) + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback' IF EXISTS ( SELECT TOP 1 1 FROM msdb.dbo.sysjobsteps WHERE job_id = @c_jobid )BEGINSELECT @loop_stepid = MIN(step_id) ,@m_stepid = MAX(step_id) FROM msdb.dbo.sysjobsteps WHERE job_id = @c_jobid WHILE (@loop_stepid < = @m_stepid) BEGIN SELECT @i_start_step_id = start_step_id,@i_step_name = step_name ,@i_step_id = step_id,@i_cmdexec_success_code = cmdexec_success_code ,@i_on_success_action = on_success_action ,@i_on_success_step_id = on_success_step_id ,@i_on_fail_action = on_fail_action ,@i_on_fail_step_id = on_fail_step_id ,@i_retry_attempts = retry_attempts ,@i_retry_interval = retry_interval ,@i_os_run_priority = os_run_priority ,@i_subsystem = subsystem ,@i_command = command ,@i_database_name = database_name ,@i_flags = flagsFROM msdb.dbo.sysjobs a ,msdb.dbo.sysjobsteps b WHERE a.job_id = b.job_id AND step_id = @loop_stepid AND a.job_id = @c_jobid SET @sql=@sql+CHAR(13)+CHAR(10) + '/****** Object: Step ['+ @i_step_name +'] Script Date: '+CONVERT(VARCHAR,GETDATE(),22)+' ******/' SET @sql=@sql+CHAR(13)+CHAR(10) + 'EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'''+ @i_step_name +''','SET @sql=@sql+CHAR(13)+CHAR(10) + ' @step_id='+ CAST(@i_step_id AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @cmdexec_success_code='+ CAST(@i_cmdexec_success_code AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @on_success_action='+ CAST(@i_on_success_action AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @on_success_step_id='+ CAST(@i_on_success_step_id AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @on_fail_action='+ CAST(@i_on_fail_action AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @on_fail_step_id='+ CAST(@i_on_fail_step_id AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @retry_attempts='+ CAST(@i_retry_attempts AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @retry_interval='+ CAST(@i_retry_interval AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @os_run_priority='+ CAST(@i_os_run_priority AS VARCHAR) +', @subsystem=N'''+ @i_subsystem +''',' SET @sql=@sql+CHAR(13)+CHAR(10) + ISNULL(' @command=N''' + REPLACE(@i_command ,'''' ,'''''') + ''',' ,'') SET @sql=@sql+CHAR(13)+CHAR(10) + ISNULL(' @database_name=N'''+ @i_database_name +''',' ,'') SET @sql=@sql+CHAR(13)+CHAR(10) + ' @flags='+ CAST(@i_flags AS VARCHAR) SET @sql=@sql+CHAR(13)+CHAR(10) + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback' SET @loop_stepid = ( SELECT TOP 1 step_id FROM msdb.dbo.sysjobsteps WHERE job_id = @c_jobid AND step_id > @loop_stepid ORDER BY step_id )ENDENDSET @sql=@sql+CHAR(13)+CHAR(10) + 'EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = '+ CAST(@i_start_step_id AS VARCHAR) SET @sql=@sql+CHAR(13)+CHAR(10) + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback' IF EXISTS ( SELECT TOP 1 1 FROM msdb.dbo.sysschedules c ,msdb.dbo.sysjobschedules d WHERE c.schedule_id = d.schedule_id AND job_id = @c_jobid )BEGINSELECT @loop_scheduleid= MIN(c.schedule_id) ,@m_scheduleid = MAX(c.schedule_id) FROM msdb.dbo.sysschedules c ,msdb.dbo.sysjobschedules dWHERE c.schedule_id = d.schedule_id AND job_id = @c_jobid WHILE ( @loop_scheduleid <= @m_scheduleid ) BEGINSELECT @i_schedule_enabled = [enabled] ,@i_freq_type = freq_type ,@i_schedule_name = name,@i_freq_interval = freq_interval ,@i_freq_subday_type = freq_subday_type ,@i_freq_subday_interval = freq_subday_interval ,@i_freq_relative_interval = freq_relative_interval ,@i_freq_recurrence_factor = freq_recurrence_factor ,@i_active_start_date = active_start_date ,@i_active_end_date = active_end_date ,@i_active_start_time = active_start_time ,@i_active_end_time = active_end_time ,@i_schedule_uid = schedule_uid FROM msdb.dbo.sysschedules c LEFT JOIN msdb.dbo.sysjobschedules dON c.schedule_id = d.schedule_id WHERE d.job_id = @c_jobid AND c.schedule_id = @loop_scheduleid SET @sql=@sql+CHAR(13)+CHAR(10) + 'EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'''+ @i_schedule_name +''',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @enabled='+ CAST(@i_schedule_enabled AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @freq_type='+ CAST(@i_freq_type AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @freq_interval='+ CAST(@i_freq_interval AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @freq_subday_type='+ CAST(@i_freq_subday_type AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @freq_subday_interval='+ CAST(@i_freq_subday_interval AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @freq_relative_interval='+ CAST(@i_freq_relative_interval AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @freq_recurrence_factor='+ CAST(@i_freq_recurrence_factor AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @active_start_date='+ CAST(@i_active_start_date AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @active_end_date='+ CAST(@i_active_end_date AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @active_start_time='+ CAST(@i_active_start_time AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @active_end_time='+ CAST(@i_active_end_time AS VARCHAR) +',' SET @sql=@sql+CHAR(13)+CHAR(10) + ' @schedule_uid=N'''+ @i_schedule_uid +'''' SET @sql=@sql+CHAR(13)+CHAR(10) + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback' SET @loop_scheduleid = ( SELECT TOP 1 c.schedule_id FROM msdb.dbo.sysschedules c ,msdb.dbo.sysjobschedules dWHERE c.schedule_id = d.schedule_id AND job_id = @c_jobid AND c.schedule_id > @loop_scheduleid ) ENDENDSET @sql=@sql+CHAR(13)+CHAR(10) + 'EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N''(local)''' SET @sql=@sql+CHAR(13)+CHAR(10) + 'IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback' SET @sql=@sql+CHAR(13)+CHAR(10) + 'COMMIT TRANSACTION' SET @sql=@sql+CHAR(13)+CHAR(10) + 'GOTO EndSave' SET @sql=@sql+CHAR(13)+CHAR(10) + 'QuitWithRollback:' SET @sql=@sql+CHAR(13)+CHAR(10) + ' IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION' SET @sql=@sql+CHAR(13)+CHAR(10) + 'EndSave:' SET @sql=@sql+CHAR(13)+CHAR(10) + '' SET @sql=@sql+CHAR(13)+CHAR(10) + 'GO'PRINT @sqlinsert into master..zzz_temp_JOB_bcpSELECT @i_job_name,@sql,@SV,CONVERT(nvarchar(10),getdate(),112)FETCH NEXT FROM job INTO @c_jobid ,@c_categoryid ,@SVENDCLOSE jobDEALLOCATE jobdeclare @a nvarchar(17),@c nvarchar(1000),@name nvarchar(100),@d nvarchar(100)set @a = CONVERT (nvarchar(17),GETDATE(),112)set @name = 'F:\kk_backup\job_'+@a+'.sql'set @d = 'del ' + @name set @c = 'bcp "select text from master..zzz_temp_JOB_bcp where bak_date = CONVERT(nvarchar(10),getdate(),112)" queryout "'+ @name +'" -c -S"服务名称" -U"sa" -P"sa123456" 'print @dprint @cexec sp_configure 'show advanced options',1reconfigure with overrideexec sp_configure 'xp_cmdshell',1reconfigure with overrideEXEC master..xp_cmdshell @dEXEC master..xp_cmdshell @cexec sp_configure 'xp_cmdshell',0reconfigure with overrideexec sp_configure 'show advanced options',0reconfigure with overrideend
GO
监控某个目录是否被更改
需求:对一个目录(比如/data/test)进行监控,当这个目录下文件或子目录出现变动(如修改、创建、删除、更名等操作)时,就发送邮件!
针对上面的需求,编写shell脚本如下:
[root@centos6-vm01 opt]# vim file_monit.sh
#!/bin/bash
#此脚本用于检测linux系统重要文件是否被改动,如果改动则用邮件报警
#建议用定时任务执行此脚本,如每5分钟执行一次,也可修改此脚本用于死循环检测
#Ver:1.0
#http://www.cnblogs.com/kevingrace#定义验证文件所在目录
FileDir='/var/CheckFile'#获取主机名或自己定义
HostName=$(hostname)#定义邮件参数:xmtp地址,发送邮件帐号,发送邮件密码,接收邮件地址,邮件主题,邮件内容
Mail_Smtp="smtp.wangshibo.com"
Mail_User="notice@wangshibo.com"
Mail_Pass="notice@123"
Mail_From="notice@wangshibo.com"
Mail_To="wangshibo@wangshibo.com"
Mail_Subject="${HostName}:There are changes to system files"
Mail_Conntent="${HostName}:There are changes to system files"#定义需要验证的文件目录。这里我监控的是/data/test目录
CheckDir=(
/data/test
)#生成所定义需验证的文件样本日志函数
OldFile () {
for i in ${CheckDir[@]}
do
/bin/find ${i} -type f |xargs md5sum >> ${FileDir}/old.log
done
}
NewFile () {
for i in ${CheckDir[@]}
do
/bin/find ${i} -type f |xargs md5sum >> ${FileDir}/new.log
done
}#生成所定义文件新日志函数(注意后面发送邮件内容,\n表示换行)
SendEMail () {
/usr/local/bin/sendEmail -f $Mail_From -t $Mail_To -s $Mail_Smtp -u $Mail_Subject -xu $Mail_User -xp $Mail_Pass -m "$Mail_Conntent"\n
}
if [ ! -d ${FileDir} ]
then
mkdir ${FileDir}
fi#假如验证文件目录不存在则创建
if [ ! -f ${FileDir}/old.log ]
then
OldFile
fi#假如没有安装sendEmail则安装
if [ ! -f /usr/local/bin/sendEmail ]
then
cd /usr/local/src/
wget http://caspian.dotconf.net/menu/Software/SendEmail/sendEmail-v1.56.tar.gz
tar -xf sendEmail-v1.56.tar.gz
cd sendEmail-v1.56
cp sendEmail /usr/local/bin
chmod 0755 /usr/local/bin/sendEmail
fi#生成新验证日志
NewFile#新验证日志与样本日志进行比较
/usr/bin/diff ${FileDir}/new.log ${FileDir}/old.log >${FileDir}/diff.log
Status=$?#假如比较结果有变化,则发送邮件报警
if [ ${Status} -ne 0 ]
then
Mail_Conntent="$(grep '<' ${FileDir}/diff.log |awk '{print $3}')"
SendEMail
fi#清除新旧日志,把比较结果进行备份
/bin/mv -f ${FileDir}/diff.log ${FileDir}/diff$(date +%F__%T).log
cat /dev/null > ${FileDir}/old.log
cat /dev/null > ${FileDir}/new.log#重新生成样本日志
OldFile#删除目录内30天以前的比较结果备份文件
/bin/find ${FileDir} -type f -mtime +30 |xargs rm -f
确保本机能连上shell脚本中指定的smtp服务器的25好端口
[root@centos6-vm01 opt]# telnet smtp.wangshibo.com 25
Trying 223.252.214.65...
Connected to smtp.wangshibo.com.
Escape character is '^]'.
220 icoremail.net Anti-spam GT for Coremail System (icoremail-gateway-smtp[20170531])
下面开始测试
[root@centos6-vm01 test]# cd /opt/
[root@centos6-vm01 opt]# cd /data/test/
[root@centos6-vm01 test]# ll
total 0
[root@centos6-vm01 test]# mkdir haha
[root@centos6-vm01 test]# echo "123456" > haha/heihei
[root@centos6-vm01 test]# ll
total 4
drwxr-xr-x. 2 root root 4096 Jan 10 01:42 haha
[root@centos6-vm01 test]# echo "abcdef" > test.txt
[root@centos6-vm01 test]# ll
total 8
drwxr-xr-x. 2 root root 4096 Jan 10 01:42 haha
-rw-r--r--. 1 root root 7 Jan 10 01:42 test.txt执行监控脚本
[root@centos6-vm01 test]# sh -x /opt/file_monit.sh注意:当首次执行脚本的时候,由于所监控的目录下的文件没有变动,所以不会发送邮件!查看对比后的日志
[root@centos6-vm01 test]# ll -d /var/CheckFile/
drwxr-xr-x. 2 root root 4096 Jan 10 01:44 /var/CheckFile/
[root@centos6-vm01 test]# ll /var/CheckFile/
total 4
-rw-r--r--. 1 root root 0 Jan 10 01:44 diff2018-01-10__01:44:30.log
-rw-r--r--. 1 root root 0 Jan 10 01:44 new.log
-rw-r--r--. 1 root root 166 Jan 10 01:44 old.log[root@centos6-vm01 test]# cat /var/CheckFile/diff2018-01-10__01\:44\:30.log
[root@centos6-vm01 test]# cat /var/CheckFile/new.log
[root@centos6-vm01 test]# cat /var/CheckFile/old.log
237267ea7fefa88360c22ab6fd582d7e /data/test/.hhhh.swp
5ab557c937e38f15291c04b7e99544ad /data/test/test.txt
f447b20a7fcbf53a5d5be013ea0b15af /data/test/haha/heihei==============================================================================================================================
现在开始对/data/test目录下的文件做下变动
[root@centos6-vm01 test]# echo "aaaaaa" >> test.txt
[root@centos6-vm01 test]# touch haha/bobo
[root@centos6-vm01 test]# mkdir heihei
[root@centos6-vm01 test]# ll
total 12
drwxr-xr-x. 2 root root 4096 Jan 10 01:47 haha
drwxr-xr-x. 2 root root 4096 Jan 10 01:47 heihei
-rw-r--r--. 1 root root 14 Jan 10 01:47 test.txt执行监控脚本
[root@centos6-vm01 test]# sh -x /opt/file_monit.sh查看对比后的日志
[root@centos6-vm01 test]# ll /var/CheckFile/
total 8
-rw-r--r--. 1 root root 0 Jan 10 01:44 diff2018-01-10__01:44:30.log
-rw-r--r--. 1 root root 179 Jan 10 01:47 diff2018-01-10__01:47:41.log
-rw-r--r--. 1 root root 0 Jan 10 01:47 new.log
-rw-r--r--. 1 root root 221 Jan 10 01:47 old.log
[root@centos6-vm01 test]# cat /var/CheckFile/diff2018-01-10__01\:47\:41.log
2,3c2
< 4533551682ca49b2f9b1f2829bf3b29d /data/test/test.txt
< d41d8cd98f00b204e9800998ecf8427e /data/test/haha/bobo
---
> 5ab557c937e38f15291c04b7e99544ad /data/test/test.txt[root@centos6-vm01 test]# cat /var/CheckFile/old.log
237267ea7fefa88360c22ab6fd582d7e /data/test/.hhhh.swp
4533551682ca49b2f9b1f2829bf3b29d /data/test/test.txt
d41d8cd98f00b204e9800998ecf8427e /data/test/haha/bobo
f447b20a7fcbf53a5d5be013ea0b15af /data/test/haha/heihei通过上面的diff日志,可以看到新变动的文件或子目录已经记录到日志里了。
查看邮件,就能看到/data/test目录下变动的文件或子目录信息了
通过crontab定时任务,每5分钟执行一次检查:
[root@centos6-vm01 test]# crontab -e
*/5 * * * * /bin/bash -x /opt/file_monit.sh > /dev/null 2>&1
以上脚本也可以用于检测linux系统重要文件是否被更改,只需将检查的目录由脚本中的/data/test改为/etc即可!
日志文件ERROR监控报警
即对日志文件中的error进行监控,当日志文件中出现error关键字时,即可报警!(grep -i error 不区分大小写进行搜索"error"关键字,但是会将包含error大小写字符的单词搜索出来)
1)第一类日志
在每天的日志目录下生产的error日志,此日志文件每天都会自动生成,里面有没有error日志内容不一定,日志内容写入不频繁,日志文件比较小。
举例说明:
[root@fk-databus01 ~]# ll /data/log/sedsb/20180628/DEJ_0001_error_20180628.0.log
-rw-rw-r-- 1 zquser zquser 63059 Jun 28 15:32 /data/log/sedsb/20180628/DEJ_0001_error_20180628.0.log采用sendemail发送告警邮件,sendemail安装参考:http://www.cnblogs.com/kevingrace/p/5961861.html监控脚本路径:
[root@fk-databus01 ~]# cd /opt/log_error_script/
[root@fk-databus01 log_error_script]# ll
total 20
-rw-r--r-- 1 root root 3782 Jun 29 12:13 DEJ_0001_error.log
-rwxr-xr-x 1 root root 4274 Jun 29 11:38 prcc_log_error.sh
-rwxr-xr-x 1 root root 1142 Feb 13 10:51 sendemail.sh监控脚本内容
[root@fk-databus01 log_error_script]# cat prcc_log_error.sh
#!/bin/sh
ERROR_LOG=`/bin/ls /data/log/sedsb/$(date +%Y%m%d)/DEJ_0001_error*`
ERROR_NEW_LOG=/opt/log_error_script/DEJ_0001_error.log
DATE=`date +%Y年%m月%d日%H时%M分%S秒`
HOST=`/bin/hostname`
IP=`/sbin/ifconfig|grep "inet addr"|grep "Bcast"|cut -d":" -f2|awk -F" " '{print $1}'`
ERROR_MESSAGE=$(/bin/grep -A20 "$(grep "ERROR" $ERROR_LOG|tail -1|awk '{print $1,$2,$3,$4}')" $ERROR_LOG)DIR=/data/log/sedsb/$(date +%Y%m%d)
FILE=/data/log/sedsb/$(date +%Y%m%d)/DEJ_0001_error_$(date +%Y%m%d).0.logif [ ! -d $DIR ];then/bin/mkdir $DIR
fiif [ ! -f $FILE ];then/bin/touch $FILE
fi/bin/chown -R zquser.zquser $DIRsleep 3if [ ! -f $ERROR_NEW_LOG ];then
/bin/touch $ERROR_NEW_LOG
fiNUM1=$(/bin/cat $ERROR_LOG|wc -l)
NUM2=$(/bin/cat $ERROR_NEW_LOG|wc -l)if [ -f $ERROR_LOG ] && [ $NUM1 -ne 0 ] && [ $NUM2 -eq 0 ];then
/bin/bash /opt/log_error_script/sendemail.sh wangshibo@kevin.com "风控系统${HOSTNAME}机器prcc服务日志的error监控" "告警主机:${HOSTNAME} \n告警IP:${IP} \n告警时间:${DATE} \n告警等级:严重,抓紧解决啊! \n告警人员:王士博 \n告警详情:prcc服务日志中出现error了! \n告警日志文件:${ERROR_LOG} \n当前状态: PROBLEM \n \nerror信息:\n$ERROR_MESSAGE"
/bin/cat $ERROR_LOG > $ERROR_NEW_LOG
fi/usr/bin/cmp $ERROR_LOG $ERROR_NEW_LOG >/dev/null 2>&1
if [ $? -ne 0 ];then
/bin/bash /opt/log_error_script/sendemail.sh wangshibo@kevin.com "风控系统${HOSTNAME}机器prcc服务日志的error监控" "告警主机:${HOSTNAME} \n告警IP:${IP} \n告警时间:${DATE} \n告警等级:严重,抓紧解决啊! \n告警人员:王士博 \n告警详情:prcc服务日志中出现error了! \n告警日志文件:${ERROR_LOG} \n当前状态: PROBLEM \n \nerror信息:\n$ERROR_MESSAGE"
/bin/cat $ERROR_LOG > $ERROR_NEW_LOG
fi结合crontab进行定时监控(每15秒执行一次)
[root@fk-databus01 ~]# crontab -l
#监控pcrr日志的error
* * * * * /bin/bash -x /opt/log_error_script/prcc_log_error.sh >/dev/null 2>&1
* * * * * sleep 15;/bin/bash -x /opt/log_error_script/prcc_log_error.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/prcc_log_error.sh >/dev/null 2>&1
* * * * * sleep 45;/bin/bash -x /opt/log_error_script/prcc_log_error.sh >/dev/null 2>&1==================================================================================
针对上面脚本中的某些变量说明
[root@fk-databus01 ~]# /bin/ls /data/log/sedsb/$(date +%Y%m%d)/DEJ_0001_error*
/data/log/sedsb/20180629/DEJ_0001_error_20180629.0.log[root@fk-databus01 ~]# grep "ERROR" /data/log/sedsb/20180629/DEJ_0001_error_20180629.0.log
ERROR DEJ 2018-06-29 12:13:29.191 [pool-4-thread-10] n.s.p.r.thread.OuterCheThdInterface - cx201806291213288440016车300接口异常!
ERROR DEJ 2018-06-29 12:13:29.196 [nioEventLoopGroup-3-12] n.s.p.r.c.MessageControllerImpl - cx201806291213288440016:[root@fk-databus01 ~]# grep "ERROR" /data/log/sedsb/20180629/DEJ_0001_error_20180629.0.log |tail -1|awk '{print $1,$2,$3,$4}'
ERROR DEJ 2018-06-29 12:13:29.196[root@fk-databus01 ~]# /bin/grep -A20 "$(grep "ERROR" /data/log/sedsb/20180629/DEJ_0001_error_20180629.0.log |tail -1|awk '{print $1,$2,$3,$4}')" /data/log/sedsb/20180629/DEJ_0001_error_20180629.0.log
ERROR DEJ 2018-06-29 12:13:29.196 [nioEventLoopGroup-3-12] n.s.p.r.c.MessageControllerImpl - cx201806291213288440016:
net.sinocredit.pre.rcc.utils.exception.OuterDataException: 外部数据:cheFixPrice:mile里程 is null;at net.sinocredit.pre.rcc.datafactory.OuterDataProcess.execute(OuterDataProcess.java:51)at net.sinocredit.pre.rcc.datafactory.OuterDataProcess.execute(OuterDataProcess.java:23)at net.sinocredit.pre.rcc.service.getOtherDataService.MessageServiceImpl.getOrderData(MessageServiceImpl.java:34)at net.sinocredit.pre.rcc.controller.MessageControllerImpl.divMessage(MessageControllerImpl.java:110)at net.sinocredit.pre.rcc.handler.ServerHandler.channelRead(ServerHandler.java:28)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:373)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:351)at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:373)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:351)at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:373)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:359)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:351)at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:373)
报警邮件效果如下:
2)第二类日志
此日志是固定文件,日志内容写入频繁,日志文件比较大。对于此文件的监控,通过采用tail -1000方式获取日志文件的最新1000行的方式进行error监控!
举例说明:
[root@fk-zqjcweb01 ~]# ll /data/log/decision/decision.log
-rw-rw-r-- 1 zquser zquser 5108 Jun 28 16:02 /data/log/decision/decision.log采用sendemail发送告警邮件,sendemail安装参考:http://10.0.8.50/software/sendemail_install.sh监控脚本路径:
[root@fk-zqjcweb01 ~]# cd /opt/log_error_script/
[root@fk-zqjcweb01 log_error_script]# ls
decision sendemail.sh
[root@fk-zqjcweb01 log_error_script]# ls decision/
decision.log_diff_error.log decision.log_error.log decision.log_monit.sh脚本内容:
[root@fk-zqjcweb01 log_error_script]# cat decision/decision.log_monit.sh
#!/bin/sh
ERROR_LOG=/data/log/decision/decision.log
ERROR_NEW_LOG=/opt/log_error_script/decision/decision.log_error.log
ERROR_DIFF_LOG=/opt/log_error_script/decision/decision.log_diff_error.log
DATE=`date +%Y年%m月%d日%H时%M分%S秒`
HOST=`/bin/hostname`
IP=`/sbin/ifconfig|grep "inet addr"|grep "Bcast"|cut -d":" -f2|awk -F" " '{print $1}'`if [ ! -f $ERROR_NEW_LOG ];then
/bin/touch $ERROR_NEW_LOG
fiNUM1=$(/usr/bin/tail -1000 $ERROR_LOG|grep error|wc -l)
NUM2=$(/bin/cat $ERROR_NEW_LOG|wc -l)if [ -f $ERROR_LOG ] && [ $NUM1 -ne 0 ] && [ $NUM2 -eq 0 ];then
/bin/bash /opt/log_error_script/sendemail.sh wangshibo@kevin.com "风控系统${HOSTNAME}机器的decision.log日志中的error监控" "告警主机:${HOSTNAME} \n告警IP:${IP} \n告警时间:${DATE} \n告警等级:严重,抓紧解决啊! \n告警人员:王士博 \n告警详情:decision.log日志中出现error了! \n告警日志文件:${ERROR_LOG} \n当前状态: PROBLEM "
/usr/bin/tail -1000 $ERROR_LOG|grep error > $ERROR_NEW_LOG
fi/usr/bin/tail -1000 $ERROR_LOG|grep error > $ERROR_DIFF_LOG
/usr/bin/cmp $ERROR_DIFF_LOG $ERROR_NEW_LOG >/dev/null 2>&1
if [ $? -ne 0 ];then
/bin/bash /opt/log_error_script/sendemail.sh wangshibo@kevin.com "风控系统${HOSTNAME}机器的decision.log日志中的error监控" "告警主机:${HOSTNAME} \n告警IP:${IP} \n告警时间:${DATE} \n告警等级:严重,抓紧解决啊! \n告警人员:王士博 \n告警详情:decision.log日志中出现error了! \n告警日志文件:${ERROR_LOG} \n当前状态: PROBLEM "
/usr/bin/tail -1000 $ERROR_LOG|grep error > $ERROR_NEW_LOG
fi
You have new mail in /var/spool/mail/root结合crontab进行定时监控
[root@fk-zqjcweb01 log_error_script]# crontab -l
#decision.log日志的error监控
* * * * * /bin/bash -x /opt/log_error_script/decision/decision.log_monit.sh >/dev/null 2>&1
* * * * * sleep 15;/bin/bash -x /opt/log_error_script/decision/decision.log_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/decision/decision.log_monit.sh >/dev/null 2>&1
* * * * * sleep 45;/bin/bash -x /opt/log_error_script/decision/decision.log_monit.sh >/dev/null 2>&1
上面提到的sendemail.sh邮件发送脚本
[root@fk-zqjcweb01 ~]# cat /opt/log_error_script/sendemail.sh
#!/bin/bash
# Filename: SendEmail.sh
# Notes: 使用sendEmail
#
# 脚本的日志文件
LOGFILE="/tmp/Email.log"
:>"$LOGFILE"
exec 1>"$LOGFILE"
exec 2>&1
SMTP_server='smtp.kevin.com'
username='monit@kevin.com'
password='monit@123'
from_email_address='monit@kevin.com'
to_email_address="$1"
message_subject_utf8="$2"
message_body_utf8="$3"
# 转换邮件标题为GB2312,解决邮件标题含有中文,收到邮件显示乱码的问题。
message_subject_gb2312=`iconv -t GB2312 -f UTF-8 << EOF
$message_subject_utf8
EOF`
[ $? -eq 0 ] && message_subject="$message_subject_gb2312" || message_subject="$message_subject_utf8"
# 转换邮件内容为GB2312,解决收到邮件内容乱码
message_body_gb2312=`iconv -t GB2312 -f UTF-8 << EOF
$message_body_utf8
EOF`
[ $? -eq 0 ] && message_body="$message_body_gb2312" || message_body="$message_body_utf8"
# 发送邮件
sendEmail='/usr/local/bin/sendEmail'
set -x
$sendEmail -s "$SMTP_server" -xu "$username" -xp "$password" -f "$from_email_address" -t "$to_email_address" -u "$message_subject" -m "$message_body" -o message-content-type=text -o message-charset=gb2312
3)第三类日志
日志规则说明:
- 在etl服务器下的EXP、MDB、MID、ODB、PDB、PUS、SDB系统里有很多任务日志,日志都存放在当天的日期目录下。
- 现在需要对这些任务日志的error进行监控,当出现error报错信息时立刻发出报警!
- 当这些任务日志文件里有出现error报错信息的,那么该任务日志文件就不会被写入了。也就是说一个任务日志文件只会出现一次error报错。
- 出现error报错信息的任务日志不能删除和更改,因为这些任务日志会被其他程序调用展示。
[root@bigdata-etl01 ~]# ll /data/etluser/LOG/
drwxrwx--- 33 etluser etluser 4096 Jul 6 02:00 EXP
drwxrwx--- 33 etluser etluser 4096 Jul 6 02:00 MDB
drwxrwx--- 33 etluser etluser 4096 Jul 6 02:00 MID
drwxrwx--- 33 etluser etluser 4096 Jul 6 02:00 ODB
drwxrwx--- 33 etluser etluser 4096 Jul 6 02:00 PDB
drwxrwx--- 32 etluser etluser 4096 Jul 6 00:47 PUS
drwxrwx--- 33 etluser etluser 4096 Jul 6 02:00 SDB
[root@bigdata-etl01 ~]# ls /data/etluser/LOG/EXP/
20180606 20180609 20180612 20180615 20180618 20180621 20180624 20180627 20180630 20180703 20180706
20180607 20180610 20180613 20180616 20180619 20180622 20180625 20180628 20180701 20180704
20180608 20180611 20180614 20180617 20180620 20180623 20180626 20180629 20180702 20180705
[root@bigdata-etl01 ~]# ls /data/etluser/LOG/EXP/20180706/
EXP_EXP_V_CUST_CRDT_SITU_20180705[1][1].54.log exp_v_opr_size_curr_stats_0010601[1].pl.56.log
EXP_EXP_V_DAILY_BIZ_AMT_SITU_20180705[1][1].45.log exp_v_opr_size_curr_stats_0010602[1].pl.56.log
EXP_EXP_V_MATR_RMND_INTFC_QG6_001_20180705[1][1].83.log exp_v_prvs_provs_int_intfc_f0_0010600[1].pl.103.log
EXP_EXP_V_OPR_SIZE_CURR_STATS_001_20180705[1][1].56.log exp_v_prvs_provs_int_intfc_f0_0010601[1].pl.103.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F0_001_20180705[1][1].103.log exp_v_prvs_provs_int_intfc_f0_0020600[1].pl.98.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F0_002_20180705[1][1].98.log exp_v_prvs_provs_int_intfc_f0_0020601[1].pl.98.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F0_003_20180705[1][1].90.log exp_v_prvs_provs_int_intfc_f0_0030600[1].pl.90.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F0_007_20180705[1][1].48.log exp_v_prvs_provs_int_intfc_f0_0030601[1].pl.90.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F0_008_20180705[1][1].78.log exp_v_prvs_provs_int_intfc_f0_0070600[1].pl.48.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F0_009_20180705[1][1].15.log exp_v_prvs_provs_int_intfc_f0_0070601[1].pl.48.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F0_010_20180705[1][1].48.log exp_v_prvs_provs_int_intfc_f0_0080600[1].pl.78.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F1_004_20180705[1][1].16.log exp_v_prvs_provs_int_intfc_f0_0080601[1].pl.78.log
EXP_EXP_V_PRVS_PROVS_INT_INTFC_F1_006_20180705[1][1].8.log exp_v_prvs_provs_int_intfc_f0_0090600[1].pl.15.log
EXP_EXP_V_QRY_FACT_AGT_INTFC_20180705[1][1].47.log exp_v_prvs_provs_int_intfc_f0_0090601[1].pl.15.log
exp_v_cust_crdt_situ0600[1].pl.54.log exp_v_prvs_provs_int_intfc_f0_0100600[1].pl.48.log
exp_v_cust_crdt_situ0601[1].pl.54.log exp_v_prvs_provs_int_intfc_f0_0100601[1].pl.48.log
exp_v_cust_crdt_situ0602[1].pl.54.log exp_v_prvs_provs_int_intfc_f1_0040600[1].pl.16.log
exp_v_daily_biz_amt_situ0600[1].pl.45.log exp_v_prvs_provs_int_intfc_f1_0040601[1].pl.16.log
exp_v_daily_biz_amt_situ0601[1].pl.45.log exp_v_prvs_provs_int_intfc_f1_0060600[1].pl.8.log
exp_v_daily_biz_amt_situ0602[1].pl.45.log exp_v_prvs_provs_int_intfc_f1_0060601[1].pl.8.log
exp_v_matr_rmnd_intfc_qg6_0010600[1].pl.83.log exp_v_qry_fact_agt_intfc0600[1].pl.47.log
exp_v_matr_rmnd_intfc_qg6_0010601[1].pl.83.log exp_v_qry_fact_agt_intfc0601[1].pl.47.log
exp_v_matr_rmnd_intfc_qg6_0010602[1].pl.83.log exp_v_qry_fact_agt_intfc0602[1].pl.47.log
exp_v_opr_size_curr_stats_0010600[1].pl.56.log监控脚本思路:
1)对这些任务日志进行批量搜索error关键字(不区分大小写)
2)将出现error关键字的任务日志拷贝到一个专门的目录下(error日志文件的列表目录)。
3)对搜索到error关键字的任务日志做判断,判断它是否存在于那个列表目录下:如果不存在,说明是新出现error的日志文件,就立刻报警!如果存在,说明出现的error是之前的信息,不报警!监控脚本编写情况如下:
error_log为error日志文件的列表目录;
sendemail.sh为邮件发送脚本(上面介绍过)
[root@bigdata-etl01 log_error_script]# ls
EXP MDB MID ODB PDB PUS SDB sendemail.sh
[root@bigdata-etl01 log_error_script]# ls EXP/
error_log EXP_error_monit.sh
[root@bigdata-etl01 log_error_script]# ls MDB/
error_log MDB_error_monit.sh
[root@bigdata-etl01 log_error_script]# ls MID/
error_log MID_error_monit.sh
[root@bigdata-etl01 log_error_script]# ls ODB/
error_log ODB_error_monit.sh
[root@bigdata-etl01 log_error_script]# ls PDB/
error_log PDB_error_monit.sh
[root@bigdata-etl01 log_error_script]# ls PUS/
error_log PUS_error_monit.sh
[root@bigdata-etl01 log_error_script]# ls SDB/
error_log SDB_error_monit.sh
[root@bigdata-etl01 log_error_script]#这里贴出SDB系统的任务日志的error监控报警脚本(其他几个系统的监控脚本与这个一样,只需要将脚本中的SDB替换成对应的系统名称即可!)
[root@bigdata-etl01 log_error_script]# cat /opt/log_error_script/SDB/SDB_error_monit.sh
#!/bin/sh
DATE_DIR=$(date +%Y%m%d)
DATE=`date +%Y年%m月%d日%H时%M分%S秒`
HOST=`/bin/hostname`
IP=`/sbin/ifconfig|grep "inet addr"|grep "Bcast"|cut -d":" -f2|awk -F" " '{print $1}'`cd /data/etluser/LOG/SDB
if [ ! -d $DATE_DIR ];then
/bin/mkdir $DATE_DIR
/bin/chown -R etluser.etluser $DATE_DIR
ficd /data/etluser/LOG/SDB/$DATE_DIR
for FILE in $(/bin/ls *.log)
doNUM=$(/bin/grep -i "error" /data/etluser/LOG/SDB/$DATE_DIR/$FILE|wc -l)ERROR_MESSAGE=$(/bin/grep -i "error" /data/etluser/LOG/SDB/$DATE_DIR/$FILE)if [ $NUM -ne 0 ];then/bin/ls /opt/log_error_script/SDB/error_log/$FILEa=$?if [ $a -ne 0 ];then/opt/log_error_script/sendemail.sh wangshibo@test.com "大数据平台etl服务器${HOSTNAME}的SDB任务日志里出现error了" "告警主机:${HOSTNAME} \n告警IP:${IP} \n告警时间:${DATE} \n告警等级:严重 \n告警人员:王士博 \n告警详情:SDB的任务日志里出现error了,抓紧解决啊! \n当前状态: PROBLEM \n告警日志文件:/data/etluser/LOG/SDB/$DATE_DIR/$FILE \n\n\n------请看下面error报错信息------- \nerror信息:\n$ERROR_MESSAGE"cp /data/etluser/LOG/SDB/$DATE_DIR/$FILE /opt/log_error_script/SDB/error_log/elseecho "$FILE日志中error报错信息是之前发生的,无需报警!"fielseecho "$FILE 日志里没有error报错啦"fi
done给脚本赋予执行权限
[root@bigdata-etl01 log_error_script]# chmod 755 /opt/log_error_script/SDB/SDB_error_monit.sh
[root@bigdata-etl01 log_error_script]# sh /opt/log_error_script/SDB/SDB_error_monit.sh
qbl_biz_cst_bsc_inf0100[1].pl.73.log 日志里没有error报错啦
qbl_biz_cst_bsc_inf0101[1].pl.73.log 日志里没有error报错啦
qbl_biz_fnc_bsc_inf0100[1].pl.73.log 日志里没有error报错啦
qbl_biz_fnc_bsc_inf0101[1].pl.73.log 日志里没有error报错啦
qbl_biz_fnc_mod_inf0100[1].pl.73.log 日志里没有error报错啦
qbl_biz_fnc_mod_inf0101[1].pl.73.log 日志里没有error报错啦
qbl_biz_pd_bsc_inf0100[1].pl.73.log 日志里没有error报错啦
qbl_biz_pd_bsc_inf0101[1].pl.73.log 日志里没有error报错啦
qbl_biz_pre_ctr_bsc_inf0100[1].pl.73.log 日志里没有error报错啦
qbl_biz_pre_ctr_bsc_inf0101[1].pl.73.log 日志里没有error报错啦
qbl_biz_repy_base_inf0100[1].pl.73.log 日志里没有error报错啦
qbl_biz_repy_base_inf0101[1].pl.73.log 日志里没有error报错啦
qbl_biz_repy_pl_dtl0100[1].pl.78.log 日志里没有error报错啦
qbl_biz_repy_pl_dtl0101[1].pl.78.log 日志里没有error报错啦
qbl_biz_repy_pl_inf0100[1].pl.78.log 日志里没有error报错啦
qbl_biz_repy_pl_inf0101[1].pl.78.log 日志里没有error报错啦
qbl_biz_repy_rcrd_jrnl0100[1].pl.73.log 日志里没有error报错啦
qbl_biz_repy_rcrd_jrnl0101[1].pl.73.log 日志里没有error报错啦
.......
.......结合crontab指定脚本定时执行任务(每30秒执行一次)
[root@bigdata-etl01 ~]# crontab -l
#etl相关任务日志的error监控报警
* * * * * /bin/bash -x /opt/log_error_script/EXP/EXP_error_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/EXP/EXP_error_monit.sh >/dev/null 2>&1* * * * * /bin/bash -x /opt/log_error_script/MDB/MDB_error_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/MDB/MDB_error_monit.sh >/dev/null 2>&1* * * * * /bin/bash -x /opt/log_error_script/MID/MID_error_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/MID/MID_error_monit.sh >/dev/null 2>&1* * * * * /bin/bash -x /opt/log_error_script/ODB/ODB_error_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/ODB/ODB_error_monit.sh >/dev/null 2>&1* * * * * /bin/bash -x /opt/log_error_script/PDB/PDB_error_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/PDB/PDB_error_monit.sh >/dev/null 2>&1* * * * * /bin/bash -x /opt/log_error_script/PUS/PUS_error_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/PUS/PUS_error_monit.sh >/dev/null 2>&1* * * * * /bin/bash -x /opt/log_error_script/SDB/SDB_error_monit.sh >/dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /opt/log_error_script/SDB/SDB_error_monit.sh >/dev/null 2>&1
邮件报警效果如下:
如上可以看出,SDB系统的任务日志里发现了error信息,现在去日志列表目录里查看下,发现出现error信息的任务日志已经拷贝到列表目录里了。
当下次脚本执行,搜索到这些日志发现error时就会去做判断,判断这些日志是否存在列表目录里,如果出现,就不会再次发出报警。
[root@bigdata-etl01 ~]# ll /opt/log_error_script/SDB/error_log/
total 12
-rw-r--r-- 1 root root 1978 Jul 6 10:36 SDB_QCX_CUSTOMER_INFO_20180705[1][1].73.log
-rw-r--r-- 1 root root 1939 Jul 6 10:19 SDB_QCX_FTTYPE_STC_20180705[1][1].51.log
-rw-r--r-- 1 root root 1939 Jul 6 10:19 SDB_QCX_SETTLE_STC_20180705[1][1].17.log
基于Ping和Telnet/NC的监控脚本案例分析
通过shell脚本,判断172.16.60.0/24网络里,当前在线的ip有哪些?能ping通则认为在线。
[root@python2 ~]# cat /tmp/ip.sh
#!/bin/bashfor i in $(seq 1 254) #这一行或者换成"for i in {1..254}"
doIP=172.16.60.${i}ping -c2 ${IP} >/dev/null 2>&1if [ $? = 0 ];thenecho "${IP} is online!"elseecho "${IP} is failed"fi
done执行脚本:
[root@python2 ~]# sh /tmp/ip.sh
172.16.60.1 is online!
172.16.60.2 is failed
172.16.60.3 is failed
172.16.60.4 is failed
......
案例一:单纯地对某些ip进行ping监控
[root@test opt]# cat /opt/hosts_ip_list
192.168.10.10
192.168.10.11
192.168.10.12
192.168.10.13
192.168.10.14
192.168.10.15
192.168.10.16
192.168.10.17[root@test opt]# cat /opt/hosts_ip_monit.sh
#!/bin/bash
for ip in $(cat /opt/hosts_ip_list) doping -c 1 $ip &>/dev/null #ping 3次,当3次ping都失败时,则判定此ip网络通信失败。a=$?sleep 2ping -c 1 $ip &>/dev/nullb=$?sleep 2ping -c 1 $ip &>/dev/nullc=$?sleep 2DATE=$(date +%F" "%H:%M)if [ $a -ne 0 -a $b -ne 0 -a $c -ne 0 ];thenecho -e "Date : $DATE\nHost : $ip\nProblem : Ping is failed."/bin/sed -i 's/^'$ip'/'#$ip'/g' /etc/hostselseecho "$ip ping is successful."/bin/sed -i 's/^'#$ip'/'$ip'/g' /etc/hostsfi
done[root@test opt]# chmod 755 /opt/hosts_ip_monit.sh[root@test opt]# sh /opt/hosts_ip_monit.sh
Date : 2018-04-24 15:49
Host : 192.168.10.10
Problem : Ping is failed.
Date : 2018-04-24 15:50
Host : 192.168.10.11
Problem : Ping is failed.
192.168.10.12 ping is successful.
192.168.10.13 ping is successful.
192.168.10.14 ping is successful.
192.168.10.15 ping is successful.
192.168.10.16 ping is successful.
Date : 2018-04-24 15:51
Host : 192.168.10.17
Problem : Ping is failed.
案例二:对/etc/hosts列表里的ip映射关系进行ping监控报警
测试系统服务器需要访问域名www.test.com,该域名解析的DNS地址有很多个,需要在测试系统服务器上的做host绑定。在/etc/hosts文件了做了www.test.com域名的很多绑定,
在域名解析时,会从host绑定配置里从上到下匹配,如果上面绑定的ip不通,则域名解析就会失败,不会主动去解析到下一个绑定的地址,除非将这个不通的ip绑定注释掉或删除掉。现在要求:
当/etc/hosts文件里绑定的ip出现故障,ping不通的时候,将该ip的绑定自动注释,并发出邮件报警;如果该ip恢复了正常通信,将自动打开该ip的绑定设置。[root@cx-app01 ~]# cat /etc/hosts
#192.168.10.10 www.test.com
#192.168.10.11 www.test.com
192.168.10.12 www.test.com
192.168.10.13 www.test.com
192.168.10.14 www.test.com
192.168.10.15 www.test.com
192.168.10.16 www.test.com
#192.168.10.17 www.test.com[root@cx-app01 ~]# ping www.test.com
PING www.test.com (192.168.10.12) 56(84) bytes of data.
64 bytes from www.test.com (192.168.10.12): icmp_seq=1 ttl=50 time=31.1 ms
64 bytes from www.test.com (192.168.10.12): icmp_seq=2 ttl=50 time=30.7 ms
64 bytes from www.test.com (192.168.10.12): icmp_seq=3 ttl=50 time=30.8 ms
.......[root@cx-app01 ~]# cat /opt/hosts_ip_list
192.168.10.10
192.168.10.11
192.168.10.12
192.168.10.13
192.168.10.14
192.168.10.15
192.168.10.16
192.168.10.17[root@cx-app01 ~]# cat /opt/hosts_ip_monit.sh
#!/bin/bash
for ip in $(cat /opt/hosts_ip_list) doping -c 1 $ip &>/dev/null a=$?sleep 2ping -c 1 $ip &>/dev/nullb=$?sleep 2ping -c 1 $ip &>/dev/nullc=$?sleep 2DATE=$(date +%F" "%H:%M)if [ $a -ne 0 -a $b -ne 0 -a $c -ne 0 ];thenecho -e "Date : $DATE\nHost : $ip\nProblem : Ping is failed."cat /etc/hosts|grep "^#$ip"d=$?if [ $d -ne 0 ];then/bin/bash /opt/sendemail.sh zhangsan@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip连接失败,现已在/etc/hosts文件里注释掉该ip的映射关系"/bin/bash /opt/sendemail.sh lisi@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip连接失败,现已在/etc/hosts文件里注释掉该ip的映射关系"/bin/bash /opt/sendemail.sh liuwu@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip连接失败,现已在/etc/hosts文件里注释掉该ip的映射关系"/bin/sed -i 's/^'$ip'/'#$ip'/g' /etc/hostselseecho "$ip is not conneted,and it has been done"fielseecho "$ip ping is successful."cat /etc/hosts|grep "^#$ip"f=$?if [ $f -eq 0 ];then/bin/bash /opt/sendemail.sh zhangsan@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip连接成功,现已在/etc/hosts文件里恢复该ip的映射关系"/bin/bash /opt/sendemail.sh lisi@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip连接成功,现已在/etc/hosts文件里恢复该ip的映射关系"/bin/bash /opt/sendemail.sh liuwu@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip连接成功,现已在/etc/hosts文件里恢复该ip的映射关系"/bin/sed -i 's/^'#$ip'/'$ip'/g' /etc/hostselseecho "$ip connection has been restored"fifi
done采用sendemail进行邮件告警发送,sendemail部署参考:http://www.cnblogs.com/kevingrace/p/5961861.html
[root@cx-app01 ~]# cat /opt/sendemail.sh
#!/bin/bash
# Filename: SendEmail.sh
# Notes: 使用sendEmail
#
# 脚本的日志文件
LOGFILE="/tmp/Email.log"
:>"$LOGFILE"
exec 1>"$LOGFILE"
exec 2>&1
SMTP_server='smtp.test.com'
username='monit@test.com'
password='monit@123'
from_email_address='monit@test.com'
to_email_address="$1"
message_subject_utf8="$2"
message_body_utf8="$3"
# 转换邮件标题为GB2312,解决邮件标题含有中文,收到邮件显示乱码的问题。
message_subject_gb2312=`iconv -t GB2312 -f UTF-8 << EOF
$message_subject_utf8
EOF`
[ $? -eq 0 ] && message_subject="$message_subject_gb2312" || message_subject="$message_subject_utf8"
# 转换邮件内容为GB2312,解决收到邮件内容乱码
message_body_gb2312=`iconv -t GB2312 -f UTF-8 << EOF
$message_body_utf8
EOF`
[ $? -eq 0 ] && message_body="$message_body_gb2312" || message_body="$message_body_utf8"
# 发送邮件
sendEmail='/usr/local/bin/sendEmail'
set -x
$sendEmail -s "$SMTP_server" -xu "$username" -xp "$password" -f "$from_email_address" -t "$to_email_address" -u "$message_subject" -m "$message_body" -o message-content-type=text -o message-charset=gb2312每10分钟定时执行该监控脚本
[root@cx-app01 ~]# crontab -l
*/10 * * * * /bin/bash -x /opt/hosts_ip_monit.sh > /dev/null 2>&1
案例三:通过nc工具对/etc/hosts列表里的ip的443端口跟本机通信是否正常进行探测
案例二是针对ping编写的监控脚本,下面介绍下利用nc探测端口通信是否正常的脚本:探测本机对下面/etc/hosts文件里的ip地址的443端口通信是否正常,如果通信失败,则发出报警,并在/etc/hosts文件里注释掉该ip地址的绑定关系。
如果注释掉的ip的443端口跟本机恢复了通信,则去掉/etc/hosts文件里该ip的注释![root@cx-app01 ~]# cat /etc/hosts
192.168.10.201 www.test.com
192.168.10.205 www.test.com
192.168.10.17 www.test.com
192.168.10.85 www.test.com
192.168.10.176 www.test.com
192.168.10.245 www.test.com
192.168.10.25 www.test.com
192.168.10.47 www.test.com[root@cx-app01 ~]# cat /opt/hosts_ip_list
192.168.10.201
192.168.10.205
192.168.10.17
192.168.10.85
192.168.10.176
192.168.10.245
192.168.10.25
192.168.10.47采用nc工具去探测端口是否正常通信(yum install -y nc)
[root@cx-app01 ~]# /usr/bin/nc -z -w 10 192.168.10.201 443
Connection to 192.168.10.201 443 port [tcp/https] succeeded!针对上面ip列表里的地址,进行批量ip的443端口通信的探测。脚本如下:
[root@cx-app01 ~]# cat /opt/host_ip_nc_monit.sh
#!/bin/bash
for ip in $(cat /opt/hosts_ip_list)
doecho -e "Date : $DATE\nHost : $ip\nProblem : Port 443 is connected."cat /etc/hosts|grep "^#$ip"a=$?if [ $a -ne 0 ];then/usr/bin/nc -z -w 10 $ip 443b=$?if [ $b -ne 0 ];then/bin/bash /opt/sendemail.sh wangshibo@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip的443端口连接失败,现已在/etc/hosts文件里注释掉该ip的映射关系"/bin/bash /opt/sendemail.sh linan@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip的443端口连接失败,现已在/etc/hosts文件里注释掉该ip的映射关系"/bin/sed -i 's/^'$ip'/'#$ip'/g' /etc/hostselseecho "$HOSTNAME跟$ip的443端口正常连接"fielse/usr/bin/nc -z -w 10 $ip 443c=$?if [ $c -eq 0 ];then/bin/bash /opt/sendemail.sh wangshibo@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip的443端口连接成功,现已在/etc/hosts文件里恢复该ip的映射关系"/bin/bash /opt/sendemail.sh linan@test.com "测试系统跟www.test.com通信情况" "$HOSTNAME跟$ip的443端口连接成功,现已在/etc/hosts文件里恢复该ip的映射关系"/bin/sed -i 's/^'#$ip'/'$ip'/g' /etc/hostselseecho "$HOSTNAME跟$ip的443端口连接失败"fifi
done给脚本赋权
[root@cx-app01 ~]# chmod 755 /opt/host_ip_nc_monit.sh执行脚本:
[root@cx-app01 ~]# sh /opt/host_ip_nc_monit.sh
Date :
Host : 192.168.10.201
Problem : Port 443 is connected.
Connection to 192.168.10.201 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.201的443端口正常连接
Date :
Host : 192.168.10.205
Problem : Port 443 is connected.
Connection to 192.168.10.205 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.205的443端口正常连接
Date :
Host : 192.168.10.17
Problem : Port 443 is connected.
Connection to 192.168.10.17 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.17的443端口正常连接
Date :
Host : 192.168.10.85
Problem : Port 443 is connected.
Connection to 192.168.10.85 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.85的443端口正常连接
Date :
Host : 192.168.10.176
Problem : Port 443 is connected.
Connection to 192.168.10.176 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.176的443端口正常连接
Date :
Host : 192.168.10.245
Problem : Port 443 is connected.
Connection to 192.168.10.245 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.245的443端口正常连接
Date :
Host : 192.168.10.25
Problem : Port 443 is connected.
Connection to 192.168.10.25 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.25的443端口正常连接
Date :
Host : 192.168.10.47
Problem : Port 443 is connected.
Connection to 192.168.10.47 443 port [tcp/https] succeeded!
cx-app01.veredholdings.cn跟192.168.10.47的443端口正常连接结合crontab进行计划任务
[root@cx-app01 ~]# crontab -l
*/10 * * * * /bin/bash -x /opt/host_ip_nc_monit.sh > /dev/null 2>&1
监控磁盘的监控脚本
[root@ceph-node1 ~]# cat disk_monit.sh
#!/bin/bash
#filename:Monitor_Disk
Monitor_Disk(){
mkdir -p /mnt/Monitor_Disk
fdisk -l|grep "Disk /dev/" | awk '{print $2,$3$4}'|tr -d ',:'>/mnt/Monitor_Disk/device_list.log
N=1;ECHO 90
while read device_line
do
Device=`echo $device_line|awk '{print $1}'`
Sum=`echo $device_line|awk '{print $2}'`
df -h |grep "$Device"|sort>/mnt/Monitor_Disk/${N}_partitions.log
echo
echo "** 第$N块硬盘($Device):${Sum} **"| grep -E "$Device|$Sum|$N" --color=yes
echo "------------------------------------"
echo -e "linux分区 挂载目录 总大小 已用 剩余 已用百分比 文件系统 ID system \
块大小 预留空间 ">/mnt/Monitor_Disk/${N}_Over.log
echo -e "========= ======== ===== === === ========== ======= == ====== \
====== ======== ">>/mnt/Monitor_Disk/${N}_Over.log
Num_Partition=`cat /mnt/Monitor_Disk/${N}_partitions.log|wc -l`
n=0
while read partition_line
doPartition_Name=`echo $partition_line|awk '{print $1}'`Mount_Dir=`echo $partition_line|awk '{print $6}'`Partition_Sum=`echo $partition_line|awk '{print $2}'`Partition_Used=`echo $partition_line|awk '{print $3}'`Partition_Leave=`echo $partition_line| awk '{print $4}'`Partition_Percent=`echo $partition_line|awk '{print $5}'`Partition_Type=`mount|grep $Partition_Name|awk '{print $5$6}'`Partition_Id=`fdisk -l | grep $Partition_Name|tr -d '\*'|awk '{print $5}'`Partition_System=`fdisk -l | grep $Partition_Name|tr -d '\*'|awk '{print $6}'`Part_Block_Size_B=`tune2fs -l $Partition_Name|grep "Block size"|awk '{print $3}'`Part_Lift_For_Root_Blocks=`tune2fs -l $Partition_Name|grep "Reserved block count:"|\awk '{print $4}'`Part_Block_Size=`echo $Part_Block_Size_B/1024|bc`Part_Lift_For_Root=`echo ${Part_Lift_For_Root_Blocks}*${Part_Block_Size}/1024|bc`echo -e "$Partition_Name $Mount_Dir $Partition_Sum $Partition_Used $Partition_Leave \
$Partition_Percent $Partition_Type $Partition_Id $Partition_System \
${Part_Block_Size}K ${Part_Lift_For_Root}M">>/mnt/Monitor_Disk/${N}_Over.loglet n++[ $n -eq $Num_Partition ]&&(cat /mnt/Monitor_Disk/${N}_Over.log|column -t;echo)
done</mnt/Monitor_Disk/${N}_partitions.log
let N++
done</mnt/Monitor_Disk/device_list.log
ECHO 90
rm -fr /mnt/Monitor_Disk
}
ECHO(){
for ((i=1;i<=$1;i++))
do
echo -n "#"
[ $i -eq $1 ]&&(echo;echo)
done
}
Monitor_Disk[root@ceph-node1 ~]# chmod 755 disk_monit.sh
[root@ceph-node1 ~]# sh disk_monit.sh
##########################################################################################** 第1块硬盘(/dev/sdb):577.4GB **
------------------------------------
linux分区 挂载目录 总大小 已用 剩余 已用百分比 文件系统 ID system 块大小 预留空间
========= ======== ===== === === ========== ======= == ====== ====== ========
/dev/sdb1 /data 530G 42G 461G 9% ext4(rw) 83 Linux 4K 27532M** 第2块硬盘(/dev/sda):322.1GB **
------------------------------------
linux分区 挂载目录 总大小 已用 剩余 已用百分比 文件系统 ID system 块大小 预留空间
========= ======== ===== === === ========== ======= == ====== ====== ========
/dev/sda1 /boot 283M 76M 193M 29% ext4(rw) 83 Linux 1K 15M
/dev/sda3 / 265G 3.1G 248G 2% ext4(rw) 83 Linux 4K 13744M##########################################################################################
监控磁盘IO使用率的脚本,实时查看IO使用情况,防止因为磁盘IO效率低而导致MySQL查询慢的问题
#!/bin/bash
#监控磁盘IO使用率并告警#定义收件人邮箱
mail="/usr/local/sbin/mail.py"
mail_user=admin@admin.comif ! which iostat &>/dev/null
thenyum install -y sysstat
fiif ! which iotop &>/dev/null
thenyum install -y iotop
filogdir=/data/iologdt=`date +%F` #以日期作为日志名字#获取IO,取5次平均值
get_io()
{iostat -dx 1 5 > $logdir/iostat.logsum=0for ut in `grep "^$1" $logdir/iostat.log |awk '{print $NF}' |cut -d '.' -f 1`dosum=$[$sum+$ut]doneecho $[$sum/5]
}while ture
dofor d in `iostat -dx |egrep -v '^$|Device:|CPU\}' |awk '{print $1}'doio=`get_io $d`if [ $io -gt 90 ]thendate >> $logdir/$dtcat $logdir/iostat.log >> $logdir/$dtiotop -obn2 >> $logdir/$dtecho "###################" >> $logdir/$dtpython $mail $mail_user "磁盘IO使用率超过90%" "`cat $logdir/$dt`" 2>/dev/nullfidonesleep 10
done
实时监控网卡流量的通用脚本
[root@ceph-node1 ~]# cat /root/net_monit.sh
#!/bin/bash
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin;
export PATH
function traffic_monitor {OS_NAME=$(sed -n '1p' /etc/issue)eth=$1if [ ! -d /sys/class/net/$eth ];thenecho -e "Network-Interface Not Found"echo -e "You system have network-interface:\n`ls /sys/class/net`"exit 5fiwhile [ "1" ]doSTATUS="fine"RXpre=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $2}')TXpre=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $10}')sleep 1RXnext=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $2}')TXnext=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $10}')clearRX=$((${RXnext}-${RXpre}))TX=$((${TXnext}-${TXpre}))if [[ $RX -lt 1024 ]];thenRX="${RX}B/s"elif [[ $RX -gt 1048576 ]];thenRX=$(echo $RX | awk '{print $1/1048576 "MB/s"}')$STATUS="busy"elseRX=$(echo $RX | awk '{print $1/1024 "KB/s"}')fiif [[ $TX -lt 1024 ]];thenTX="${TX}B/s"elif [[ $TX -gt 1048576 ]];thenTX=$(echo $TX | awk '{print $1/1048576 "MB/s"}')elseTX=$(echo $TX | awk '{print $1/1024 "KB/s"}')fiecho -e "==================================="echo -e "Welcome to Traffic_Monitor stage"echo -e "version 1.0"echo -e "Since 2018.7.2"echo -e "Created by wangshibo"echo -e "BLOG: http://www.cnblogs.cn/kevingrace"echo -e "==================================="echo -e "System: $OS_NAME"echo -e "Date: `date +%F`"echo -e "Time: `date +%k:%M:%S`"echo -e "Port: $1"echo -e "Status: $STATUS"echo -e " \t RX \tTX"echo "------------------------------"echo -e "$eth \t $RX $TX "echo "------------------------------"echo -e "Press 'Ctrl+C' to exit"done
}if [[ -n "$1" ]];thentraffic_monitor $1
elseecho -e "None parameter,please add system netport after run the script! \nExample: 'sh traffic_monitor eth0'"
fi[root@ceph-node1 ~]# chmod 755 /root/net_monit.sh
[root@ceph-node1 ~]# sh /root/net_monit.sh eth0 #eth0是网卡设备名称,如果是网卡绑定bond0,后面就跟bond0
===================================
Welcome to Traffic_Monitor stage
version 1.0
Since 2018.7.2
Created by wangshibo
BLOG: http://www.cnblogs.cn/kevingrace
===================================
System: CentOS release 6.9 (Final)
Date: 2018-07-02
Time: 15:19:34
Port: eth0
Status: fineRX TX
------------------------------
eth0 417B/s 390B/s
------------------------------
Press 'Ctrl+C' to exit
===================================
Welcome to Traffic_Monitor stage
version 1.0
Since 2018.7.2
Created by wangshibo
BLOG: http://www.cnblogs.cn/kevingrace
===================================
System: CentOS release 6.9 (Final)
Date: 2018-07-02
Time: 15:19:35
Port: eth0
Status: fineRX TX
------------------------------
eth0 1.49902KB/s 1.3252KB/s
------------------------------
Press 'Ctrl+C' to exit
检测网卡流量,并按规定格式记录在日志中
#!/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
指定时间内网站访问次数的监控
需求说明:
在日常运维工作中,为了防止一些恶意访问的行为,例如不断的请求刷流量,通过实时过滤Nginx访问日志,将单位时间内访问次数达到指定阀值的来源ip查找出来,并通过邮件报警方式及时通知运维人员!
比如针对url为http://192.168.10.202:8888的访问进行监控,当在1分钟内访问次数超过300次数,就邮件报警给运维人员。
nginx日志监控脚本
[root@Fastdfs_storage_s1 ~]# cat /opt/nginx_log_monit.sh
#!/bin/bash
#日志文件
logfile=/usr/local/nginx/logs/access.log#开始时间
start_time=`date -d"$last_minutes minutes ago" +"%H:%M:%S"`#结束时间
stop_time=`date +"%H:%M:%S"`#过滤出单位之间内的日志并统计最高ip数
tac $logfile | awk -v st="$start_time" -v et="$stop_time" '{t=substr($4,RSTART+14,21);if(t>=st && t<=et) {print $0}}' \
| awk '{print $1}' | sort | uniq -c | sort -nr > /root/log_ip_top10
ip_top=`cat /root/log_ip_top10 | head -1 | awk '{print $1}'`
# 单位时间[1分钟]内单ip访问次数超过300次,则触发邮件报警
if [[ $ip_top -gt 300 ]];then/usr/bin/python /opt/send_mail.py &
fi
python报警脚本
[root@Fastdfs_storage_s1 ~]# cat /opt/send_mail.py
# -*- coding: utf-8 -*-
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from datetime import datetime
import os
import smtplib
def _format_addr(s):name, addr = parseaddr(s)return formataddr((Header(name, 'utf-8').encode(), addr))
# 邮箱定义
smtp_server = 'smtp.kevin.com'
smtp_port = 465
from_addr = 'monit@kevin.com'
password = os.environ.get('monit@123')
to_addr = ['wangshibo@kevin.com']
# 邮件对象
msg = MIMEMultipart()
msg['From'] = _format_addr('发件人 <%s>' % from_addr)
msg['To'] = _format_addr('收件人 <%s>' % to_addr)
msg['Subject'] = Header('Warning:单ip请求次数异常', 'utf-8').encode()
# 获取系统中要发送的文本内容
with open('/root/log_ip_top10', 'r') as f:line = f.readline().strip()line = line.split(" ")
print(line)
# 邮件正文是MIMEText:
html = '<html><body><h2>一分钟内单ip请求次数超过阀值</h2>' + \'<p>ip:%s 请求次数/min:%s</p>' % (line[1],line[0]) + \'</body></html>'
msg.attach(MIMEText(html, 'html', 'utf-8'))
server = smtplib.SMTP_SSL(smtp_server, smtp_port)
server.login(from_addr, password)
server.sendmail(from_addr, to_addr, msg.as_string())
server.quit()
写个测试脚本不停curl请求资源触发报警
[root@Fastdfs_storage_s1 ~]# cat /opt/curl.sh
#!/bin/bash
#example:curl.sh http://www.kevin.com 100
usage()
{echo "usage: `basename $0` url count"
}
if [ $# -ne 2 ]; thenusageexit 1
fi
for i in `seq 1 $2`;dohttp_code=`curl -o /dev/null -s -w %{http_code} $1`echo $1 $http_code
done手动执行测试脚本
[root@Fastdfs_storage_s1 ~]# /bin/bash /opt/curl.sh http://192.168.10.202:8888 300
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
http://192.168.10.202:8888 200
...........
定时任务,由于上面脚本是监控一分钟内的日志,因此每分钟执行一次
[root@Fastdfs_storage_s1 ~]# crontab -e
* * * * * /bin/bash -x /opt/nginx_log_monit.sh >/dev/null 2>&1
这里仅仅是实现了邮件告警功能,实际上还可以实现自动屏蔽恶意访问的ip。
可以通过Nginx deny来实现,也可以通过iptables屏蔽("iptables -I INPUT -s x.x.x.x -j DROP"方式)
网站访问状态和超时时间监控报警设置
对网站访问状态和超时时间进行监控:当code状态为5xx或者访问超时时间大于10s时进行报警。脚本脚本如下:
[root@qd-inf-logcollector01 web_monit]$ pwd
/app/script/web_monit[root@qd-inf-logcollector01 web_monit]$ ll
total 12
-rwxr-xr-x 1 root root 870 Oct 12 21:34 http_monit.sh //监控脚本
-rwxr-xr-x 1 root root 857 Oct 12 21:25 sms.py //短信报警脚本,里面有报警联系人
-rw-r--r-- 1 root root 377 Oct 12 21:27 weblist.txt //监控的网站域名列表[root@qd-inf-logcollector01 web_monit]$ cat http_monit.sh
#!/bin/sh
weblist=/app/script/web_monit/weblist.txt
for list in `cat $weblist|grep -E -v "#|^$"`
do
httpcode=`curl -o /dev/null -s -w %{http_code} "$list"`
httptime=`curl -o /dev/null -s -w "time_connect: %{time_connect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" "$list"|grep time_total|awk -F ":" '{print $2*1000}'`
if [ $httpcode = 500 ]||[ $httpcode = 502 ]||[ $httpcode = 503 ]||[ $httpcode = 504 ]
thenpython /app/script/web_monit/sms.py $list "$list 访问有误!状态码为$httpcode!请收到报警后尽快查看并处理!"
elseecho "$list is checked ok!"
fiif [ $httptime -ge 10000 ]
thenpython /app/script/web_monit/sms.py $list " $list访问超时!超时时间为$httptime毫秒!请收到报警后尽快查看并处理!"
elseecho "$list is connect ok!"
fi
done
手动检查网站访问的code状态码
[root@qd-inf-logcollector01 web_monit]$ curl -o /dev/null -s -w %{http_code} http://www.wang.com
200
手动检查网站访问的超时时间(单位:毫秒,如下网址访问的时间为0.8秒)
[root@qd-inf-logcollector01 web_monit]$ curl -o /dev/null -s -w "time_connect: %{time_connect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" http://www.wang.com |grep time_total|awk -F ":" '{print $2*1000}'
800
网站列表和脚本执行
[root@qd-inf-logcollector01 web_monit]$cat weblist.txt
http://nop.kevin.cn
http://ap.kevin.cn
http://ope.kevin.cn
http://opr.kevin.cn
http://www.kevin.cn
http://kevin.cn
http://tb.kevin.cn
http://www.wang.com
https://www.wang.comhttp://doc.kevin.cn
http://docs.kevin.cn
http://git.wang.com
http://monitor.kevin.cn
http://dash.kevin.cn[root@qd-inf-logcollector01 web_monit]$sh http_monit.sh
http://nop.kevin.cn is checked ok!
http://nop.kevin.cn is connect ok!
http://ap.kevin.cn is checked ok!
http://ap.kevin.cn is connect ok!
http://ope.kevin.cn is checked ok!
http://ope.kevin.cn is connect ok!
http://opr.kevin.cn is checked ok!
http://opr.kevin.cn is connect ok!
http://www.kevin.cn is checked ok!
http://www.kevin.cn is connect ok!
http://kevin.cn is checked ok!
http://kevin.cn is connect ok!
http://tb.kevin.cn is checked ok!
http://tb.kevin.cn is connect ok!
http://www.wang.com is checked ok!
http://www.wang.com is connect ok!
https://www.wang.com is checked ok!
https://www.wang.com is connect ok!
http://doc.kevin.cn is checked ok!
http://doc.kevin.cn is connect ok!
http://docs.kevin.cn is checked ok!
http://docs.kevin.cn is connect ok!
http://git.wang.com is checked ok!
http://git.wang.com is connect ok!
http://monitor.kevin.cn is checked ok!
http://monitor.kevin.cn is connect ok!
http://dash.kevin.cn is checked ok!
http://dash.kevin.cn is connect ok!
定时监控任务(每两分钟监控一次)
[root@qd-inf-logcollector01 web_monit]$ crontab -l
*/2 * * * * /bin/bash -x /app/script/web_monit/http_monit.sh > /dev/null 2>&1
简单注意下:比较运算符只有==和!=是用于字符串比较的,不可用于整数比较;整数比较只能使用-eq, -gt这种形式
服务器磁盘监控脚本(含报警邮件)
在日常的运维工作中,我们经常会对服务器的磁盘使用情况进行巡检,以防止磁盘爆满导致的业务故障。如果能编写一个合理完善的监控脚本,当磁盘使用率达到我们设置的阀值时,就自动发送报警邮件,以便我们及时获悉到快爆满的磁盘情况!
下面分享一个脚本:
监控本机的根磁盘和home盘,当根磁盘使用率达到90%和home磁盘使用率达到95%的时候,发报警邮件至wangshibo@kevin.cn和liugang@kevin.cn
[root@kevin ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root 50G 46G 12G 90% /
tmpfs 32G 68K 32G 1% /dev/shm
/dev/sda1 485M 40M 421M 9% /boot
/dev/mapper/VolGroup-lv_home 836G 795G 673G 95% /home取根磁盘当前利用率的百分值
[root@kevin ~]# /bin/df -h|grep /dev/mapper/VolGroup-lv_root|awk -F" " '{print $5}'|cut -d"%" -f1
90取home盘当前利用率的百分值
[root@kevin ~]# /bin/df -h|grep /dev/mapper/VolGroup-lv_home|awk -F" " '{print $5}'|cut -d"%" -f1
95编写邮件报警脚本
[root@kevin ~]# vim /root/root_disk.sh
#!/bin/bash
SERVER_IP=`ifconfig|grep 192.168.1|awk -F":" '{print $2}'|cut -d" " -f1`
ROOT_DISK=`/bin/df -h|grep /dev/mapper/VolGroup-lv_root|awk -F" " '{print $5}'|cut -d"%" -f1`
HOME_DISK=`/bin/df -h|grep /dev/mapper/VolGroup-lv_home|awk -F" " '{print $5}'|cut -d"%" -f1`if [ $ROOT_DISK -ge 90 ];then
/usr/local/bin/sendEmail -f ops@kevin.cn -t wangshibo@kevin.cn -s smtp.kevin.cn -u " The ROOT_DISK of $SERVER_IP-$HOSTNAME is warning!" -o message-content-type=html -o message-charset=utf8 -xu ops@kevin.cn -xp zh@123bj -m "The ROOT_DISK of $SERVER_IP-$HOSTNAME,now use% is 90%,please deal with it as soon as possible"
/usr/local/bin/sendEmail -f ops@kevin.cn -t liugang@kevin.cn -s smtp.kevin.cn -u " The ROOT_DISK of $SERVER_IP-$HOSTNAME is warning!" -o message-content-type=html -o message-charset=utf8 -xu ops@kevin.cn -xp zh@123bj -m "The ROOT_DISK of $SERVER_IP-$HOSTNAME,now use% is 90%,please deal with it as soon as possible"
else
echo "The ROOT_DISK of $SERVER_IP-$HOSTNAME is Enough to use"
fisleep 5if [ $HOME_DISK -ge 95 ];then
/usr/local/bin/sendEmail -f ops@kevin.cn -t wangshibo@kevin.cn -s smtp.kevin.cn -u " The HOME_DISK of $SERVER_IP-$HOSTNAME is warning!" -o message-content-type=html -o message-charset=utf8 -xu ops@kevin.cn -xp zh@123bj -m "The HOME_DISK of $SERVER_IP-$HOSTNAME,now use% is 95%,please deal with it as soon as possible"
/usr/local/bin/sendEmail -f ops@kevin.cn -t liugang@kevin.cn -s smtp.kevin.cn -u " The HOME_DISK of $SERVER_IP-$HOSTNAME is warning!" -o message-content-type=html -o message-charset=utf8 -xu ops@kevin.cn -xp zh@123bj -m "The HOME_DISK of $SERVER_IP-$HOSTNAME,now use% is 95%,please deal with it as soon as possible"
else
echo "The ROOT_DISK of $SERVER_IP-$HOSTNAME is Enough to use"
fi===============================================================
设置计划任务
[root@kevin ~]# crontab -e
*/30 * * * * /bin/bash -x /root/root_disk.sh > /dev/null 2>&1
上面脚本中的邮件报警用的是sendemail,需要提前安装sendemail环境,安装操作如下:
1)先下载安装包到本地,解压。
[root@kevin ~]# cd /usr/local/src/
[root@kevin src]# wget -c http://caspian.dotconf.net/menu/Software/SendEmail/sendEmail-v1.56.tar.gz
[root@kevin src]# tar -zvxf sendEmail-v1.56.tar.gz
[root@kevin src]# cd sendEmail-v1.56
[root@kevin sendEmail-v1.56]# cp -a sendEmail /usr/local/bin/
[root@kevin sendEmail-v1.56]# chmod +x /usr/local/bin/sendEmail
[root@kevin sendEmail-v1.56]# file /usr/local/bin/sendEmail
/usr/local/bin/sendEmail: a /usr/bin/perl -w script text executable2)安装下依赖
[root@kevin sendEmail-v1.56]# yum install perl-Net-SSLeay perl-IO-Socket-SSL -y[root@kevin sendEmail-v1.56]# /usr/local/bin/sendEmail -f from@kevin.cn -t to@kevin.cn -s smtp.kevin.cn -u "我是邮件主题" -o message-content-type=html -o message-charset=utf8 -xu from@kevin.cn -xp zh@123bj -m "我是邮件内容"命令说明:
/usr/local/bin/sendEmail #命令主程序
-f from@kevin.cn #发件人邮箱
-t to@kevin.cn #收件人邮箱
-s smtp.huanqi.cn #发件人邮箱的smtp服务器
-u "我是邮件主题" #邮件的标题
-o message-content-type=html #邮件内容的格式,html表示它是html格式
-o message-charset=utf8 #邮件内容编码
-xu from@kevin.cn #发件人邮箱的用户名
-xp zh@123bj #发件人邮箱密码
-m "我是邮件内容" #邮件的具体内容例如:
[root@kevin alertscripts]# /usr/local/bin/sendEmail -f ops@kevin.cn -t wangshibo@kevin.cn -s smtp.kevin.cn -u "我是邮件主题" -o message-content-type=html -o message-charset=utf8 -xu ops@kevin.cn -xp zh@123bj -m "我是邮件内容"
Oct 14 19:38:29 kevin sendEmail[65454]: Email was sent successfully!
登陆wangshibo@kevin.cn邮箱,发现已经收到了上面发送的邮件:
业务日志清理脚本
线上某些系统业务跑一段时间后,日志就会越来越多,考虑到业务机器磁盘有限,需要添加业务日志清理功能。根据日志所在分区磁盘使用情况来判断是否清理日志,比如当日志分区磁盘空间使用超过90%时,将一周前的日志打包转移到别处 (别的分区下或远程存储设备上)。脚本 (/opt/script/log_clear.sh) 如下:
#!/bin/bash#定义日志所在分区当前空间所占比例数(去掉%)。grep -w表示精准匹配,只匹配"/"这个分区
LOG_PARTITION=$(`which df` -h|awk '{print $5,$6}'|grep -w "/"|cut -d" " -f1|awk -F"%" '{print $1}')
#定义一周前的日期,用于日志分区空间超过设定的阈值后保留的份数(这里保留一周的日志)
KEEP_DATE=`date -d '-7 days' +%Y%m%d`
#定义日志路径
LOG_DIR=/opt/log/kevin
#定义日志备份路径(即当日志分区空间超过阈值后,将日志转移到该处。这里就转移到了本地home分区下,也可以转移到别的机器或远程存储设备上)
LOG_BACK_DIR=/home/log/kevin#确保日志备份路径存在,如果不存在,则创建该路径。
if [ ! -d ${LOG_BACK_DIR} ];then`which mkdir` -p ${LOG_BACK_DIR}
elseecho "${LOG_BACK_DIR} is exist" >/dev/null 2>&1
fi#当日志分区当前空间超过90%时执行的动作
if [ ${LOG_PARTITION} -ge 90 ];then#切换到日志路径下cd ${LOG_DIR}#截取日志文件中的日期,比如stepweb_20190915.log日志文件,则截取20190915for LOG_DATE in $(ls -l ${LOG_DIR}|awk '{print $9}'|cut -d"_" -f2|awk -F"." '{print $1}')do#当日志文件中截取的日期是一周之前的日志时执行的动作if [ ${LOG_DATE} -lt ${KEEP_DATE} ];then#打包,转移,删除#注意这里tar使用-P参数,因为tar默认为相对路径,使用绝对路径的话会报错"Removing leading `/’ from member names",使用-P参数就解决了该问题`which tar` -zvPcf ${LOG_DIR}/stepweb_${LOG_DATE}.log.tar.gz ${LOG_DIR}/stepweb_${LOG_DATE}.logmv ${LOG_DIR}/stepweb_${LOG_DATE}.log.tar.gz ${LOG_BACK_DIR}/rm -rf ${LOG_DIR}/stepweb_${LOG_DATE}.logelseecho "keep stepweb_${LOG_DATE}.log" >/dev/null 2>&1fidone
elseecho "${LOG_PARTITION} is available" >/dev/null 2>&1
fi
根据上面脚本验证下:
查看本机磁盘使用情况,日志所在分区磁盘当前使用率达到92%了
[root@yyweb kevin]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 50G 46G 4G 92% /
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 34M 3.8G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/sda1 1014M 183M 832M 19% /boot
/dev/mapper/centos-home 142G 33M 142G 1% /home日志所在路径
[root@yyweb kevin]# pwd
/opt/log/kevin日志情况
[root@yyweb kevin]# ls
stepweb_20190810.log stepweb_20190817.log stepweb_20190824.log stepweb_20190901.log stepweb_20190908.log stepweb_20190915.log
stepweb_20190811.log stepweb_20190818.log stepweb_20190825.log stepweb_20190902.log stepweb_20190909.log stepweb_20190916.log
stepweb_20190812.log stepweb_20190819.log stepweb_20190826.log stepweb_20190903.log stepweb_20190910.log stepweb_20190917.log
stepweb_20190813.log stepweb_20190820.log stepweb_20190827.log stepweb_20190904.log stepweb_20190911.log stepweb_20190918.log
stepweb_20190814.log stepweb_20190821.log stepweb_20190828.log stepweb_20190905.log stepweb_20190912.log stepweb_20190919.log
stepweb_20190815.log stepweb_20190822.log stepweb_20190829.log stepweb_20190906.log stepweb_20190913.log
stepweb_20190816.log stepweb_20190823.log stepweb_20190830.log stepweb_20190907.log stepweb_20190914.log[root@yyweb kevin]# ls /home/
[root@yyweb kevin]#执行日志清理脚本
[root@yyweb kevin]# sh /opt/script/log_clear.sh
/opt/log/kevin/stepweb_20190810.log
/opt/log/kevin/stepweb_20190811.log
/opt/log/kevin/stepweb_20190812.log
/opt/log/kevin/stepweb_20190813.log
/opt/log/kevin/stepweb_20190814.log
/opt/log/kevin/stepweb_20190815.log
/opt/log/kevin/stepweb_20190816.log
/opt/log/kevin/stepweb_20190817.log
/opt/log/kevin/stepweb_20190818.log
/opt/log/kevin/stepweb_20190819.log
/opt/log/kevin/stepweb_20190820.log
/opt/log/kevin/stepweb_20190821.log
/opt/log/kevin/stepweb_20190822.log
/opt/log/kevin/stepweb_20190823.log
/opt/log/kevin/stepweb_20190824.log
/opt/log/kevin/stepweb_20190825.log
/opt/log/kevin/stepweb_20190826.log
/opt/log/kevin/stepweb_20190827.log
/opt/log/kevin/stepweb_20190828.log
/opt/log/kevin/stepweb_20190829.log
/opt/log/kevin/stepweb_20190830.log
/opt/log/kevin/stepweb_20190901.log
/opt/log/kevin/stepweb_20190902.log
/opt/log/kevin/stepweb_20190903.log
/opt/log/kevin/stepweb_20190904.log
/opt/log/kevin/stepweb_20190905.log
/opt/log/kevin/stepweb_20190906.log
/opt/log/kevin/stepweb_20190907.log
/opt/log/kevin/stepweb_20190908.log
/opt/log/kevin/stepweb_20190909.log
/opt/log/kevin/stepweb_20190910.log
/opt/log/kevin/stepweb_20190911.log
/opt/log/kevin/stepweb_20190912.log日志清理后,日志路径下只保留了最近一周的日志
[root@yyweb kevin]# ls
stepweb_20190913.log stepweb_20190915.log stepweb_20190917.log stepweb_20190919.log
stepweb_20190914.log stepweb_20190916.log stepweb_20190918.log一周之前的日志被打包转移到/home/log/kevin下了
[root@yyweb kevin]# ls /home/log/kevin/
stepweb_20190810.log.tar.gz stepweb_20190817.log.tar.gz stepweb_20190824.log.tar.gz stepweb_20190901.log.tar.gz stepweb_20190908.log.tar.gz
stepweb_20190811.log.tar.gz stepweb_20190818.log.tar.gz stepweb_20190825.log.tar.gz stepweb_20190902.log.tar.gz stepweb_20190909.log.tar.gz
stepweb_20190812.log.tar.gz stepweb_20190819.log.tar.gz stepweb_20190826.log.tar.gz stepweb_20190903.log.tar.gz stepweb_20190910.log.tar.gz
stepweb_20190813.log.tar.gz stepweb_20190820.log.tar.gz stepweb_20190827.log.tar.gz stepweb_20190904.log.tar.gz stepweb_20190911.log.tar.gz
stepweb_20190814.log.tar.gz stepweb_20190821.log.tar.gz stepweb_20190828.log.tar.gz stepweb_20190905.log.tar.gz stepweb_20190912.log.tar.gz
stepweb_20190815.log.tar.gz stepweb_20190822.log.tar.gz stepweb_20190829.log.tar.gz stepweb_20190906.log.tar.gz
stepweb_20190816.log.tar.gz stepweb_20190823.log.tar.gz stepweb_20190830.log.tar.gz stepweb_20190907.log.tar.gz
再贴一个简单的日志处理脚本
#!/usr/bin/sh
#根据系统/服务/日志保留天数三个参数压缩日志
#usage: sh clearlog.sh sysname appname keepdays
sysName=$1
appName=$2
keepDay=$3
logDir=/var/log/${sysName}/${appName}
logFile=${appName}.log
cd ${logDir}
find ./ -name "${logFile}.*[0-9][0-9]" -mtime +${keepDay} -exec gzip {} \;
Linux下间隔多少秒 (即以秒为单位) 去执行某条命令或某个shell脚本的操作方法
在日常运维工作中, 经常会碰到以秒为单位去定时执行某些命令或监控脚本的需求。 说到定时任务就要用到crontab,通常来说,crontab的最小单位是分钟级别,要想实现秒级别的定时任务,就要进行特殊设置了。
[root@test ~]# cat /root/kevin.sh
#!/bin/bash
echo "beijing is so good!" >> /root/test.log添加脚本执行权限,并配置到crontab计划任务里(使用&& 或者 ;都是一样的效果)。思路:先过一分钟执行第一次,接着就是每隔2秒钟执行一次。
[root@test ~]# chmod 755 /root/kevin.sh
[root@test ~]# crontab -e
* * * * * /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 2 && /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 4; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 6; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 8; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 10; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 12; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 14; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 16; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 18; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 20; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 22; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 24; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 26; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 28; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 30; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 32; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 34; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 36; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 38; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 40; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 42; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 44; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 46; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 48; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 50; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 52; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 54; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 56; /bin/bash -x /root/kevin.sh >/dev/null 2>&1
* * * * * sleep 58; /bin/bash -x /root/kevin.sh >/dev/null 2>&1[root@test ~]# tail -f /root/test.log
beijing is so good!
beijing is so good!
beijing is so good!
beijing is so good!
beijing is so good!
beijing is so good!
beijing is so good!
beijing is so good!
beijing is so good!
..........
..........
Linux下批量ping某个网段ip的脚本
比如现在需要对172.16.50.0/24网段的ip进行检查,检查哪些ip现在被占用,哪些ip没有被占用,可以通过ping命令来检查,脚本如下:
[root@uatdns01 opt]# vim /opt/ping.sh
#!/bin/bash
. /etc/init.d/functions
for var in {1..254};
do
ip=172.16.50.$var
ping -c2 $ip >/dev/null 2>&1
if [ $? = 0 ];then
action "$ip" /bin/true
else
action "$ip" /bin/false
fi
done[root@uatdns01 opt]# chmod 755 /opt/ping.sh
[root@uatdns01 opt]# sh /opt/ping.sh
172.16.50.1 [ OK ]
172.16.50.2 [FAILED]
172.16.50.3 [FAILED]
172.16.50.4 [FAILED]
172.16.50.5 [FAILED]
.........
.........
172.16.50.99 [ OK ]
172.16.50.100 [ OK ]
172.16.50.101 [ OK ]
172.16.50.102 [ OK ]
172.16.50.103 [ OK ]
172.16.50.104 [ OK ]
172.16.50.105 [ OK ]
172.16.50.106 [ OK ]
172.16.50.107 [ OK ]
172.16.50.108 [ OK ]
172.16.50.109 [ OK ]
172.16.50.110 [ OK ]
172.16.50.111 [FAILED]
172.16.50.112 [ OK ]
获取172.16.60.0/24网段可用ip的shell脚本
[root@ansible-server ~]# cat ip_ping.sh
#!/bin/bash
ip=1
while [ $ip != "254" ]; do
ping 172.16.60.$ip -c 2 | grep -q "ttl=" && echo "172.16.60.$ip yes" || echo "172.16.60.$ip no"
ip=`expr "$ip" "+" "1"`
done执行:
[root@ansible-server ~]# sh ip_ping.sh
172.16.60.1 yes
172.16.60.2 no
172.16.60.3 no
.............
172.16.60.24 yes
172.16.60.25 yes
172.16.60.26 no
.............如果只打印可用ip, 则脚本修改如下:
[root@ansible-server ~]# cat ip_ping.sh
#!/bin/bash
ip=1
while [ $ip != "254" ]; do
ping 172.16.60.$ip -c 2 | grep -q "ttl=" && echo "172.16.60.$ip yes" || echo "172.16.60.$ip no" >/dev/null 2>&1
ip=`expr "$ip" "+" "1"`
done执行:
[root@ansible-server ~]# sh ip_ping.sh
172.16.60.1 yes
172.16.60.21 yes
172.16.60.22 yes
172.16.60.23 yes
172.16.60.24 yes
172.16.60.25 yes
172.16.60.31 yes
172.16.60.32 yes
172.16.60.33 yes
172.16.60.34 yes
172.16.60.35 yes
172.16.60.36 yes
172.16.60.37 yes
172.16.60.38 yes
172.16.60.39 yes获取172.16.50.0/24, 172.16.51.0/24, 172.16.60.0/24 三个网段的可用ip
[root@ansible-server ~]# cat ip_ping.sh
#!/bin/bash
ip=1
while [ $ip != "254" ]; doping 172.16.50.$ip -c 2 | grep -q "ttl=" && echo "172.16.50.$ip yes" || echo "172.16.50.$ip no" >/dev/null 2>&1
ip=`expr "$ip" "+" "1"`ping 172.16.51.$ip -c 2 | grep -q "ttl=" && echo "172.16.51.$ip yes" || echo "172.16.51.$ip no" >/dev/null 2>&1
ip=`expr "$ip" "+" "1"`ping 172.16.60.$ip -c 2 | grep -q "ttl=" && echo "172.16.60.$ip yes" || echo "172.16.60.$ip no" >/dev/null 2>&1
ip=`expr "$ip" "+" "1"`done执行:
[root@ansible-server ~]# sh ip_ping.sh
172.16.50.1 yes
172.16.51.11 yes
172.16.50.16 yes
172.16.50.19 yes
172.16.51.20 yes
172.16.60.21 yes
172.16.50.22 yes
172.16.60.24 yes
172.16.50.25 yes
172.16.50.31 yes
172.16.60.33 yes
172.16.51.35 yes
172.16.60.36 yes
172.16.60.39 yes
172.16.51.41 yes
172.16.51.44 yes
172.16.50.52 yes
172.16.51.53 yes
172.16.50.55 yes
172.16.50.58 yes
172.16.51.65 yes
..................
查看系统运行情况
#!/bin/bash
#用于查看系统运行情况#功能选择菜单
menu(){echo -e "\033[31;32m 查看系统运行情况 \033[0m"echo -e "\033[31;32m================================================================================\033[0m"echo -e "\033[34m请选择:\033[0m"echo -e "\033[33m1、查看系统负载 2、查看CPU消耗% 3、查看内存消耗% 4、查看SWAP消耗% \033[0m"echo -e "\033[33m5、查看磁盘消耗% 6、查看inode消耗% 7、查看磁盘IO 8、查看网络流量 \033[0m"echo -e "\033[33m9、一键查看所有情况 10、退出脚本 \033[0m"echo -e "\033[31;32m================================================================================\033[0m"echoread -p "请输入数字:1-8[单独查看],9[一键查看],10[退出脚本]: " num
}#(1)查看系统负载
load_average(){cpu_core=`grep 'model name' /proc/cpuinfo | wc -l`echo -e "\033[36mCPU核数: $cpu_core\033[0m"load=`uptime |awk -F ',' '{print $3 $4 $5}' |sed 's/^ *//'`echo -e "\033[36m$load\033[0m"echo ""
}#(2)查看CPU消耗%
cpu_use_percent(){cpu_idle=`vmstat |awk '{print $15}' |sed '1,2d'`cpu_use=$[100-$cpu_idle]echo -e "\033[36mCPU使用率%: $cpu_use\033[0m"echo ""
}#(3)查看内存消耗%
mem_use_percent(){mem_used=`free -m |grep Mem |awk '{print $3}'`mem_tol=`free -m |grep Mem |awk '{print $2}'`mem_use=`awk 'BEGIN{print '$mem_used'/'$mem_tol'*100}'`echo -e "\033[36m内存已使用"$mem_used"M,总内存"$mem_tol"M,内存使用率%: $mem_use\033[0m"echo ""
}#(4)查看SWAP消耗%
swap_use_percent(){swap_used=`free -m |grep Swap |awk '{print $3}'`swap_tol=`free -m |grep Swap |awk '{print $2}'`swap_use=`awk 'BEGIN{print '$swap_used'/'$swap_tol'*100}'`echo -e "\033[36mSwap已使用"$swap_used"M,总Swap"$swap_tol"M,Swap使用率%: $swap_use\033[0m"echo ""
}#(5)查看磁盘消耗%
disk_use_percent(){disk_use=`df -h |sed '1d'`echo -e "\033[36m磁盘使用情况: \n$disk_use\033[0m"echo ""
}#(6)查看inode消耗%
inode_use_percent(){inode_use=`df -i |sed '1d'`echo -e "\033[36minode使用情况: \n$inode_use\033[0m"echo ""
}#(7)查看磁盘IO
disk_io(){disk_io_bi=`vmstat |awk '{print $9}' |sed '1,2d'`echo -e "\033[36m发送到块设备的块数: "$disk_io_bi"块每秒\033[0m"disk_io_bo=`vmstat |awk '{print $10}' |sed '1,2d'`echo -e "\033[36m从块设备接收到的块数: "$disk_io_bo"块每秒\033[0m"echo ""
}#(8)查看网络流量
network_flow(){#安装所需命令sysstatif ! rpm -q sysstat > /dev/nullthenyum install -y sysstat &>/dev/nullif [ $? -ne 0 ]thenecho -e "\033[31msysstat 安装失败\033[0m"exit 1fifiexplain=`sar -n DEV |sed -n '3p'`echo -e "\033[35m网络流量使用情况: \n$explain\033[0m"network_ifs=`ifconfig |grep "<UP,BROADCAST,RUNNING,MULTICAST>" |awk -F ':' '{print $1}'`network_flow=`sar -n DEV |grep -v Average |grep $network_ifs |tail`echo -e "\033[36m$network_flow\033[0m"
}#脚本运行入口
run(){while true;domenucase $num in"1")#1、查看系统负载load_average;;"2")#2、查看CPU消耗%cpu_use_percent;;"3")#3、查看内存消耗%mem_use_percent;;"4") #4、查看SWAP消耗%swap_use_percent;;"5") #5、查看磁盘消耗%disk_use_percent;;"6") #6、查看inode消耗%inode_use_percent;;"7") #7、查看磁盘IOdisk_io;;"8") #8、查看网络流量network_flow;;"9") #9、一键查看所有情况load_averagecpu_use_percentmem_use_percentswap_use_percentdisk_use_percentinode_use_percentdisk_ionetwork_flowexit 0;;"10") #10、退出脚本exit 0;;*);;esacdone
}#调用脚本运行入口
run
管理docker
具体要求如下:
1)脚本支持启动全部容器、关闭全部容器、删除全部容器;
2)需要提示用户如何使用该脚本,需给出范例。
#!/bin/bash
#用于管理docker容器while ture
doread -p "请输入你要执行的操作:(stop/start/rm)" optif [ -z "$opt" ]thenecho "请输入你的操作"continueelsebreakfi
donedocker ps -a |awk '{print $1}' > /tmp/id.txtcase $opt instop)for id in `cat /tmp/id.txt`dodocker stop $iddone;;start)for id in `cat /tmp/id.txt`dodocker start $iddone;;rm)for id in `cat /tmp/id.txt`doread -p "将要删除容器$id,是否继续?(y|n)" ccase $c iny|Y)docker rm -f $id;;n|N)echo "容器$id不会被删除";;*)echo "你只能输入 y/Y或者n/N";;esacdone*)echo "你只能输入 start/stop/rm";;esac
Shell多线程备份数据库
本案例就是实现shell多线程备份数据库,具体要求如下:
1)公司的业务量比较大,有100个数据库需要全量备份,而每个数据库的数据量高达几十GB
(注意:每一个库都为一个独立的实例,即有着独立的ip:port);
2)预估每一个库的备份时间为30分钟左右,要求在5个小时内完成;
3)假设100个库的库名、host、port以及配置文件路径都存到一个文件里,文件名字为 /tmp/databases.list ;
4)格式为:db1 10.10.10.2 3308 /data/mysql/db1/my.cnf 。
#!/bin/bash
#多线程备份数据库
#备份数据库使用xtrabackup(由于涉及到myisam,命令为innobackupex)exec &> /tmp/mysql_bak.logif ! which inoobackupex &>/dev/null
thenecho "安装xtrabackup工具"yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpmyum install percona-xtrabackup-24if [ $? -ne 0 ]thenecho -e "\033[31m安装xtrabackup工具出错,请检查\033[0m"exit 1fi
fibakdir=/data/backup/mysql
bakuser=vyNctM
bakpass=99omeaBHhbak_data()
{db_name=$1db_host=$2db_port=$3cnf=$4[ -d $bakdir/$db_name ] || mkdir -p $bakdir/$db_nameinnobackupex --defaults-file=$4 --host=$2 --port=$3 --user=$bakuser --password=$bakpass --databases=$1 $bakdirif [ $? -ne 0 ]thenecho -e "\033[31m备份数据库$1出现问题\033[0m"fi
}fifofile=/tmp/$$
mkfifo $fifofile
exec 1000<>$fifofilen=10
for ((i=0;i<$n;i++))
doecho >&1000 # 0-9,创建10个线程
donecat /tmp/databases.list |while read line
doread -u1000{bak_data `echo $line`echo >&1000} &
donewait
exec 1000>&- #删除fd1000
rm -f $fifofile #删除命名管道
脚本中,
1、exec &> /tmp/mysql_bak.log ,将正确输出和错误输出都重定向到 /tmp/mysql_bak.log
2、$$表示本进程PID,mkfifo命令创建命名管道
3、read line ,line为变量名,将接下来的输入赋值给line
监测 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
检测两台服务器指定目录下的文件一致性
#!/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
定时清空文件内容,定时记录文件大小
#!/bin/bash
#################################################################
每小时执行一次脚本(任务计划),当时间为0点或12点时,将目标目录下的所有文件内#容清空,但不删除文件,其他时间则只统计各个文件的大小,一个文件一行,输出到以时#间和日期命名的文件中,需要考虑目标目录下二级、三级等子目录的文件
################################################################
logfile=/tmp/`date +%H-%F`.log
n=`date +%H`
if [ $n -eq 00 ] || [ $n -eq 12 ]
then
#通过for循环,以find命令作为遍历条件,将目标目录下的所有文件进行遍历并做相应操作
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
计算文档每行出现的数字个数,并计算整个文档的数字总数
#!/bin/bash
#########################################################
#计算文档每行出现的数字个数,并计算整个文档的数字总数
########################################################
#使用awk只输出文档行数(截取第一段)
n=`wc -l a.txt|awk '{print $1}'`
sum=0
#文档中每一行可能存在空格,因此不能直接用文档内容进行遍历
for i in `seq 1 $n`do
#输出的行用变量表示时,需要用双引号
line=`sed -n "$i"p a.txt`#wc -L选项,统计最长行的长度
n_n=`echo $line|sed s'/[^0-9]//'g|wc -L`
echo $n_nsum=$[$sum+$n_n]
done
echo "sum:$sum"
杀死所有脚本
#!/bin/bash
################################################################
#有一些脚本加入到了cron之中,存在脚本尚未运行完毕又有新任务需要执行的情况,
#导致系统负载升高,因此可通过编写脚本,筛选出影响负载的进程一次性全部杀死。
################################################################
ps aux|grep 指定进程名|grep -v grep|awk '{print $2}'|xargs kill -9
从 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"
EOF
扫描主机端口状态
#!/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的单词
#示例语句:
#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.
do
n=`echo $s|wc -c`
if [ $n -lt 6 ]
then
echo $s
fi
done
监控 httpd 的进程数,根据监控情况做相应处理
#!/bin/bash
###############################################################################################################################
#需求:
#1.每隔10s监控httpd的进程数,若进程数大于等于500,则自动重启Apache服务,并检测服务是否重启成功
#2.若未成功则需要再次启动,若重启5次依旧没有成功,则向管理员发送告警邮件,并退出检测
#3.如果启动成功,则等待1分钟后再次检测httpd进程数,若进程数正常,则恢复正常检测(10s一次),否则放弃重启并向管理员发送告警邮件,并退出检测
###############################################################################################################################
#计数器函数
check_service()
{
j=0
for i in `seq 1 5`
do
#重启Apache的命令/usr/local/apache2/bin/apachectl restart 2> /var/log/httpderr.log
#判断服务是否重启成功
if [ $? -eq 0 ] thenbreak
else
j=$[$j+1] fi
#判断服务是否已尝试重启5次
if [ $j -eq 5 ] thenmail.py exit
fi
done }while :do
n=`pgrep -l httpd|wc -l`
#判断httpd服务进程数是否超过500
if [ $n -gt 500 ] then/usr/local/apache2/bin/apachectl restart
if [ $? -ne 0 ]
thencheck_service
else
sleep 60
n2=`pgrep -l httpd|wc -l`
#判断重启后是否依旧超过500
if [ $n2 -gt 500 ]
then mail.py exit
fi
fi
fi
#每隔10s检测一次
sleep 10done
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 ]; theniptables -I INPUT -s $IP -j DROP fidone
方法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 ]; theniptables -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 ]; theniptables -I INPUT -s $IP -j DROP fidone
方法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 ]; theniptables -A INPUT -s $IP -j DROP
echo "$(date +"%F %T") - iptables -A INPUT -s $IP -j DROP" >>~/ssh-login-limit.log
fi
done
根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
#!/bin/bash
####################################################################################
#根据web访问日志,封禁请求量异常的IP,如IP在半小时后恢复正常,则解除封禁
####################################################################################
logfile=/data/log/access.log
#显示一分钟前的小时和分钟
d1=`date -d "-1 minute" +%H%M`
d2=`date +%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 '$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()
{
#将封禁后所产生的pkts数量小于10的IP依次遍历予以解封
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
}
#当时间在00分以及30分时执行解封函数
if [ $d2 -eq "00" ] || [ $d2 -eq "30" ]
then
#要先解再封,因为刚刚封禁时产生的pkts数量很少unblockblock
elseblock
fi
判断用户输入的是否为IP地址
方法1:
#!/bin/bash
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:
#!/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&&$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" ]; thenreturn 0
else
echo "$IP not available!"return 1
fi
else
echo "Format error! Please input again."return 1
fi
}
while true; doread -p "Please enter IP: " IPcheck_ip $IP[ $? -eq 0 ] && break || continue
done
相关文章:

运维实用脚本整理
运维实用脚本整理 本文脚本仅供参考运维排查问题思路运维排查问题的方法和命令(1)尽可能搞清楚问题的前因后果(2)有谁在?(3)之前发生了什么?(4) 现在在运行的进程是啥?࿰…...

INT8 中的稀疏性:加速的训练工作流程和NVIDIA TensorRT 最佳实践
INT8 中的稀疏性:加速的训练工作流程和NVIDIA TensorRT 最佳实践 文章目录 INT8 中的稀疏性:加速的训练工作流程和NVIDIA TensorRT 最佳实践结构稀疏量化在 TensorRT 中部署稀疏量化模型的工作流程案例研究:ResNet-34要求第 1 步:…...

隧道模式HTTP代理使用代码示例
以下是使用Python实现隧道模式HTTP代理的代码示例: python import socket def handle_client(client_socket): # 接收客户端请求 request client_socket.recv(4096) # 解析请求头,获取目标主机和端口号 host request.split(b\r\n)[1].sp…...

翻筋斗觅食海鸥优化算法-附代码
翻筋斗觅食海鸥优化算法 文章目录 翻筋斗觅食海鸥优化算法1.海鸥优化算法2. 改进海鸥优化算法2.1 非线性参数 A 策略2.2 翻筋斗觅食策略 3.实验结果4.参考文献5.Matlab代码6.python代码 摘要:针对基本海鸥优化算法(SOA)在处理复杂优化问题中存在低精度、…...

K8S常见应用场景(六)
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具广泛可用。 Kubernetes 这个名字源于希腊语,意为“…...

《不抱怨的世界》随记
*不抱怨的世界 * 1.天才只有三件事:我的事,他的事,老天的事。抱怨自己的的人,应该试着学习接纳自己;抱怨他人的人,应该试着把抱怨转成请求;抱怨老天的人么,请试着用祈祷的方式来诉求…...

2.2 利用MyBatis实现CRUD操作
一、准备工作 打开MyBatisDemo项目 二、查询表记录 1、在映射器配置文件里引入结果映射元素 在UserMapper.xml文件里创建结果映射元素 将UserMapper接口里抽象方法上的注解暂时注释掉 运行TestUserMapper测试类里的testFindAll()测试方法,查看结果 2、添加…...

自动缩放Kubernetes上的Kinesis Data Streams应用程序
想要学习如何在Kubernetes上自动缩放您的Kinesis Data Streams消费者应用程序,以便节省成本并提高资源效率吗?本文提供了一个逐步指南,教您如何实现这一目标。 通过利用Kubernetes对Kinesis消费者应用程序进行自动缩放,您可以从其…...

介绍js各种事件
目录 一、点击事件 二、鼠标移动事件 三、键盘事件 四、滚轮事件 五、拖放事件 六、窗口大小改变事件 一、点击事件 点击事件是指当用户单击页面上的某个元素时触发的事件。这是最常见和基础的事件之一,也是Web应用程序中最常用的交互之一。 以下是如何使用…...

Python 将 CSV 分割成多个文件
文章目录 使用 Pandas 在 Python 中创建 CSV 文件在 Python 中将 CSV 文件拆分为多个文件根据行拆分 CSV 文件根据列拆分 CSV 文件 总结 在本文中,我们将学习如何在 Python 中将一个 CSV 文件拆分为多个文件。 我们将使用 Pandas 创建一个 CSV 文件并将其拆分为多个…...

S32K144开发板
目录 一.S32K144开发板概述 二.产品技术和功能规格 三.开发环境 1.S32K144的开发环境主流是这么三种: 2.开发板Demo工程 四.S32K144开发板实物图 五、汽车大灯硬件架构 一.S32K144开发板概述 S32K14…...

三波混频下的相位失配原理
原理推导 在四波混频情况下,实现零相位失配是一件很困难的事情。因为在四波混频中,相位调制和增益都依赖于相同的参数,即克尔非线性 γ \gamma γ。这个问题可以用嵌入在传输线上的辅助共振元件的复杂色散工程来部分解决。 但是在三波混频中…...

软考A计划-试题模拟含答案解析-卷一
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享&am…...

Ubuntu下编译运行MicroPython Unix版本
文章目录 github拉取源码更新模块编译运行 github拉取源码 到Github(https://github.com/micropython/micropython)上下载源码 终端输入,如果提示识别不到gh命令,就sudo apt-get install gc安装一下。 再根据提示在终端里登录自己的github账号。 再次…...

实现用QCustomPlot封装的插件,放到绘图软件中可以点击和移动
首先,我们需要在绘图软件中创建一个插件,并将QCustomPlot控件添加到插件中。QCustomPlot是一个功能强大的绘图控件,可以轻松创建各种类型的图表,包括折线图、散点图、柱状图等等。 接下来,我们需要为QCustomPlot控件添加鼠标事件处理函数,以实现点击和移动的功能。QCust…...

【源码解析】Nacos配置热更新的实现原理
使用入门 使用RefreshScopeValue,实现动态刷新 RestController RefreshScope public class TestController {Value("${cls.name}")private String clsName;}使用ConfigurationProperties,通过Autowired注入使用 Data ConfigurationProperti…...

界面组件DevExpress ASP.NET Core v22.2 - UI组件升级
DevExpress ASP.NET Core Controls使用强大的混合方法,结合现代企业Web开发工具所期望的所有功能。该套件通过ASP.NET Razor标记和服务器端ASP.NET Core Web API的生产力和简便性,提供客户端JavaScript的性能和灵活性。ThemeBuilder工具和集成的Material…...

阿里系文生图(PAI+通义)
PAI-Diffusion模型来了!阿里云机器学习团队带您徜徉中文艺术海洋 - 知乎作者:汪诚愚、段忠杰、朱祥茹、黄俊导读近年来,随着海量多模态数据在互联网的爆炸性增长和训练深度学习大模型的算力大幅提升,AI生成内容(AI Gen…...

Netty概述及Hello word入门
目录 概述 Netty是什么 Netty的地位 Netty的优势 HelloWord入门程序 目标 pom依赖 服务器端 客户端 运行结果 入门把握理解 概述 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable hi…...

汇编寄存器之内存访问
1.内存中字的存储: 在CPU中用一个16位寄存器来存储一个字, 高8位存高字节,低8位存低字节 如AX寄存器存在一个字,那么AH存高字节,AL存低字节 在内存中存储字时是用两个连续的字节来存储字的, 这个字的低字节存在低单元,高字节存在高单元. 如下表示: 内存单元编号 单元中…...

C++进阶 —— lambda表达式(C++11新特性)
目录 一,模板函数sort 二,lambda表达式 一,模板函数sort 在C98中,如对一个数据集合中的元素进行排序,可使用模板函数sort,如元素为自定义类型,需定义排序时的比较规则;随着C的发展…...

数据结构04:串的存储结构与KMP算法
前言 参考用书:王道考研《2024年 数据结构考研复习指导》 参考用书配套视频:4.1_1_串的定义和基本操作_哔哩哔哩_bilibili 特别感谢: Google Bard老师[解释KMP,修改BUG]、Chat GPT老师[修改BUG]、BING老师[封面图]~ 当我请求BI…...

零基础快速搭建私人影音媒体平台
目录 1. 前言 2. Jellyfin服务网站搭建 2.1. Jellyfin下载和安装 2.2. Jellyfin网页测试 3.本地网页发布 3.1 cpolar的安装和注册 3.2 Cpolar云端设置 3.3 Cpolar本地设置 4.公网访问测试 5. 结语 转载自cpolar极点云的文章:零基础搭建私人影音媒体平台【…...

C++map和set
目录: 什么是关联式容器?键值对树形结构的关联式容器 set的概念multiset的使用pair和make_pair map的概念用“[]”实现统计水果的次数 multimap的使用 什么是关联式容器? 在初阶阶段,我们已经接触过STL中的部分容器,比…...

python接口测试之测试报告
在本文章中,主要使用jenkins和编写的自动化测试代码,来生成漂亮的测试报告,关于什么是CI这些我就不详细的介绍了,这里我们主要是实战为主。 首先搭建java的环境,这个这里不做介绍。搭建好java的环境后,在h…...

HGFormer:用于领域广义语义分割的层级式分组Transformer
文章目录 HGFormer: Hierarchical Grouping Transformer for Domain Generalized Semantic Segmentation摘要本文方法实验结果 HGFormer: Hierarchical Grouping Transformer for Domain Generalized Semantic Segmentation 摘要 目前的语义分割模型在独立同分布条件下取得了…...

async函数用法
目录 1.概念 2.本质 3.语法 4.特点 5.async基本使用 6.async里的await普通函数返回值 7.async里的await Promise函数成功返回值 8.async里的await Promise函数失败返回值 9.解决async里的await Promise函数失败后不执行下面内容 1.概念 真正意义上解决异步回调的问题&am…...

简谈软件版本周期 | Alpha、Beta、RC、Stable版本之间的区别
目录 💌 引言 ⭕ 软件版本周期 🛠️ 软件开发期 ⚖️ 软件完成期 💰 商业软件版本 💌 引言 定义好版本号,对于产品的版本发布与持续更新很重要;但是对于版本怎么定义,规则如何确定&#x…...

VS2022发布独立部署的.net程序
.net core支持依赖框架部署和独立部署两种方式,之前学习时是在VSCode中使用dotnet命令发布的。但是在VS2022中却不知道该如何设置。以获取PDF文件使用字体的项目为例,VS2022中默认编译的是依赖框架部署方式(编译的结果如下图所示)…...

5-网络初识——封装和分用
目录 1.数据封装的过程 2.数据分用的过程 PS:网络数据传输的基本流程(以QQ为例,A给B发送一个hello): 一、发送方: 二、接收方: 不同的协议层对数据包有不同的称谓,在传输层叫做…...