java实现对服务器的自动巡检邮件通知

网友投稿 296 2023-05-19


java实现对服务器的自动巡检邮件通知

1、需求

之前一直是手动的巡检,然后贴图,最近服务器数量大增,有点忙不过来了。因为一直用的java,对shell脚本不是特别了解,所以这次用java写了个小项目,实现对多服务器,多任务的巡检,巡检结果有故障的会通过邮件通知。

2、功能和效果

巡检的项目主要是服务,硬盘,内存等,命令可配置,巡检结果以日期和服务器为基准输出文件,错误信息通过邮件通知管理运维人员。

3、代码

action:

package com.save.action;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashSet;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

import com.save.pojo.Cmd;

import com.save.until.MailUtil;

import com.save.until.PropertiesUtil;

import com.save.until.SSHCommUtil;

import com.save.until.WriteUntil;

/**

* 巡检任务

* @author zhangzhuo

*

*/

public class InspAction {

final static Logger logger = LoggerFactory.getLogger(InspAction.class);

/* public static void main(String[] args) {

InspAction n = new InspAction();

try {

n.execute();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

logger.error("dd");

}

}*/

/**

* 执行巡检任务

* @param args

*/

public void execute() throws Exception{

List list = this.handlerData();

Set mail = new HashSet();

for (Cmd cmd : list) {

String ip = cmd.getIp();

int port = 22;

String localIp = null;

int localPort = 0;

int timeOut = 6000;

String userName = cmd.getUsername();

String password = cmd.getPassword();

String server = cmd.getServer();

String[] cmds = cmd.getCmds();

String[] result = null;

logger.info(ip+"执行巡检任务开始");

try {

result = SSHCommUtil.execShellCmdBySSH(ip, port, localIp, localPort, timeOut,

userName, password, cmds);

} catch (Exception e) {

e.printStackTrace();

logger.error(ip+"巡检,服务器连接不上");

mail.add(ip+" "+"巡检,服务器连接不上");

}

Date date = new Date();

SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");

String dateString = formatter.format(date);

//1、服务存活验证 2、硬盘占用验证 3、巡检结果写入文件

if (result != null) {

for (String string : result) {

if (string.contains("ps -ef|grep java")||string.contains("ps -ef|grep mongo")||string.contains("ps -ef|grep redis")) {

if (!string.contains(server)) {

mail.add(ip+" "+server+"服务不存在");

}

}

if (string.contains("df -h")) {

String patt = "^[5]\\d{1}\\%|[5-9]\\d{1}\\%|\\d{3,}\\%$";

String group = null;

Pattern p = Pattern.compile(patt);

Matcher m = p.matcher(string);

while (m.find()) {

group = m.group();

}

if (!StringUtils.isBlank(group)) {

mail.add(ip+" "+"硬盘占用超出预警线");

}

}

WriteUntil.createFile("E:\\save", dateString, "\\"+ip+".txt", string);

}

logger.info(ip+"巡检结束");

}

}

//发送故障邮件通知

if (!mail.isEmpty()||mail.size()!=0) {

MailUtil.getInstance().sendMail(mail);

}

}

/**

* 数据处理

* @return

*/

private List handlerData(){

logger.info("开始加载需要巡检的服务器数据");

Cmd cmd = null;

List list = new ArrayList();

Map map = PropertiesUtil.getInstance().getAllProperty();

Iterator> it = map.entrySet().iterator();

while (it.hasNext()) {

Map.Entry entry = it.next();

cmd =new Cmd();

cmd.setIp(entry.getKey());

Cmd cmd2 = JSON.parseObject(entry.getValue(), Cmd.class);

String[] cmds = cmd2.getShell().split(",");

cmd.setCmds(cmds);

cmd.setServer(cmd2.getServer());

cmd.setUsername(cmd2.getUsername());

cmd.setPassword(cmd2.getPassword());

list.add(cmd);

}

logger.info("数据加载完毕");

return list;

}

}

pojo:

package com.save.pojo;

public class Cmd {

private String ip;

private String username;

private String password;

private String shell;

private String[] cmds;

private String server;

public String getServer() {

return server;

}

public void setServer(String server) {

this.server = server;

}

public String getShell() {

return shell;

}

public void setShell(String shell) {

this.shell = shell;

}

public String getIp() {

return ip;

}

public void setIp(String ip) {

this.ip = ip;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String[] getCmds() {

return cmds;

}

public void setCmds(String[] cmds) {

this.cmds = cmds;

}

}

工具类:

package com.save.until;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.InetAddress;

import java.net.InetSocketAddress;

import java.net.Socket;

import java.net.UnknownHostException;

import java.util.Properties;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.jcraft.jsch.JSch;

import com.jcraft.jsch.JSchException;

import com.jcraft.jsch.Session;

import com.jcraft.jsch.SocketFactory;

/**

* SSH创建与服务器连接工具类

* @author 张卓

* 2017-4-21

*/

public class JSCHUtil {

final static Logger logger = LoggerFactory.getLogger(JSCHUtil.class);

private static JSch jsch = new JSch();

/**

* 创建Session,并打开Session连接

*

*/

public static Session createSession(String dstIp, int dstPort,

final String localIp, final int localPort, String userName,

String password, final int timeOut) throws JSchException {

//jsch.setKnownHosts("/home/foo/.ssh/known_hosts");

logger.info("开始连接:"+dstIp);

// 建立一个SSH连接

Session session = jsch.getSession(userName, dstIp, dstPort);

session.setPassword(password);

Properties sshConfig = new Properties();

sshConfig.put("StrictHostKeyChecking", "no");//跳过主机检查

session.setConfig(sshConfig);

// 此socket工厂用于创建目标主机的socket,

// 并创建我们使用的这个socket字节流

session.setSocketFactory(new SocketFactory() {

public OutputStream getOutputStream(Socket socket)

throws IOException {

return socket.getOutputStream();

}

public InputStream getInputStream(Socket socket) throws IOException {

return socket.getInputStream();

}

public Socket createSocket(String host, int port)

throws IOException, UnknownHostException {

Socket socket = new Socket();

if (localIp != null) {

socket.bind(new InetSocketAddress(InetAddress

.getByName(localIp), localPort));

}

socket.connect(

new InetSocketAddress(InetAddress.getByName(host), port),

timeOut);

return socket;

}

});

session.connect(timeOut);

return session;

}

}

package com.save.until;

import java.util.Properties;

import java.util.Set;

import javax.mail.Authenticator;

import javax.mail.Message;

import javax.mail.PasswordAuthentication;

import javax.mail.Session;

import javax.mail.Transport;

import javax.mail.internet.InternetAddress;

import javax.mail.internet.MimeMessage;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.sun.mail.util.MailSSLSocketFactory;

/**

* 邮件发送

* @author zhangzhuo

*

*/

public class MailUtil {

final static Logger logger = LoggerFactory.getLogger(MailUtil.class);

private static MailUtil instance = new MailUtil();

private MailUtil (){}

public static MailUtil getInstance() {

return instance;

}

public void sendMail(Set mail) {

String from = "XXX@qq.com";// 发件人电子邮箱

String host = "smtp.qq.com"; // 指定发送邮件的主机smtp.qq.com(QQ)|smtp.163.com(网易)

Properties properties =new Properties();

properties.setProperty("mail.smtp.host", host);// 设置邮件服务器

properties.setProperty("mail.smtp.auth", "true");// 打开认证

try {

//QQ邮箱需要下面这段代码,163邮箱不需要

MailSSLSocketFactory sf = new MailSSLSocketFactory();

sf.setTrustAllHosts(true);

properties.put("mail.smtp.ssl.enable", "true");

properties.put("mail.smtp.ssl.socketFactory", sf);

// 1.获取默认session对象

Session session = Session.getDefaultInstance(properties, new Authenticator() {

public PasswordAuthentication getPasswordAuthentication() {

return new PasswordAuthentication("XXX@qq.com", "XXX"); // 发件人邮箱账号、授权码

}

});

// 2.创建邮件对象

Message message = new MimeMessage(session);

message.setFrom(new InternetAddress(from));

message.addRecipient(Message.RecipientType.TO, new InternetAddress("XXX@qq.com"));

message.setSubject("巡检故障通知");

StringBuffer sb = new StringBuffer();

for (String string : mail) {

sb.append("

}

String content = sb.toString();

message.setContent(content, "text/html;charset=UTF-8");

Transport.send(message);

logger.info("故障邮件发送成功");

} catch (Exception e) {

e.printStackTrace();

}

}

}

package com.save.until;

import java.io.File;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.URI;

import java.util.Enumeration;

import java.util.HashMap;

import java.util.Map;

import java.util.Properties;

/**

* 读取文件工具类

* @author zhangzhuo

*

*/

public class PropertiesUtil {

private Properties props;

private URI uri;

private static PropertiesUtil ourInstance = new PropertiesUtil("/config.properties");

public static PropertiesUtil getInstance() {

return ourInstance;

}

public PropertiesUtil(String fileName){

readProperties(fileName);

}

private void readProperties(String fileName) {

try {

props = new Properties();

InputStream fis =getClass().getResourceAsStream(fileName);

InputStreamReader re=new InputStreamRenEMEHihDRader(fis,"utf-8");

props.load(re);

} catch (Exception e) {

e.printStackTrace();

}

}

/**

* 获取某个属性

*/

public String getProperty(String key){

return props.getProperty(key);

}

/**

* 获取所有属性,返回一个map,不常用

* 可以试试props.putAll(t)

*/

public Map getAllProperty(){

Map map=new HashMap();

Enumeration enu = props.propertyNames();

while (enu.hasMoreElements()) {

String key = (String) enu.nextElement();

String value = props.getProperty(key);

map.put(key, value);

}

return map;

}

/**

* 在控制台上打印出所有属性,调试时用。

*/

public void printProperties(){

props.list(System.out);

}

/**

* 写入properties信息

*/

public void writeProperties(String key, String value) {

try {

OutputStream fos = new FileOutputStream(new File(uri));

props.setProperty(key, value);

// 将此 Properties 表中的属性列表(键和元素对)写入输出流

props.store(fos, "『comments』Update key:" + key);

} catch (Exception e) {

e.printStackTrace();

}

}

}

package com.save.until;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.jcraft.jsch.Channel;

import com.jcraft.jsch.JSchException;

import com.jcraft.jsch.Session;

/**

* 执行Shell工具类

* @author zhangzhuo

*

*/

public class SSHCommUtil {

final static Logger logger = LoggerFactory.getLogger(SSHCommUtil.class);

/**

* SHH连接linux Shell,返回结果

*/

public static String[] execShellCmdBySSH(String dstIp, int dstport,

String localIp, int localPort, int timeOut, String userName,

String password, String... cmds) throws Exception {

Session session = null;

Channel channel = null;

InputStream is = null;

OutputStream os = null;

try {

session = JSCHUtil.createSession(dstIp, dstport, localIp,

localPort, userName, password, timeOut);

logger.info("开始创建channel通道!");

//创建一个channel类型的通道

channel = session.openChannel("shell");

// Enable agent-forwarding.

// ((ChannelShell)channel).setAgentForwarding(true);

// Choose the pty-type "vt102".

// ((ChannelShell)channel).setPtyType("vt102");

// Set environment variable "LANG" as "ja_JP.eucJP".

// ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP");

channel.connect();

is = channel.getInputStream();

os = channel.getOutputStream();

String[] result = new String[cmds.length];

for (int i = 0; i < cmds.length; i++) {

result[i] = sendCommand(is, os, cmds[i]);

}

return result;

} catch (JSchException e) {

if (e.getMessage().contains("Auth fail")) {

logger.error(dstIp+"服务器验证失败");

throw new Exception("Auth error");

} else {

logger.error(dstIp+"服务器连接失败");

throw new Exception("Connect error");

}

} catch (Exception e) {

throw e;

} finally {

try {

is.close();

} catch (IOException e) {

}

try {

os.close();

} catch (IOException e) {

}

channel.disconnect();

session.disconnect();

}

}

/**

*执行Shell脚本并返回结果

*

*/

private static String sendCommand(InputStream is, OutputStream os,

String cmd) throws IOException {

logger.info("开始执行脚本!");

os.write(cmd.getBytes());

os.flush();

StringBuffer sb = new StringBuffer();

int beat = 0;

while (true) {

if (beat > 3) {

break;

}

if (is.available() > 0) {

byte[] b = new byte[is.available()];

is.read(b);

sb.append(new String(b));

beat = 0;

} else {

if (sb.length() > 0) {

beat++;

}

try {

Thread.sleep(sb.toString().trim().length() == 0 ? 1000

: 300);

} catch (InterruptedException e) {

}

}

}

return sb.toString();

}

}

package com.save.until;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.List;

import com.jcraft.jsch.ChannelExec;

import com.jcraft.jsch.JSch;

import com.jcraft.jsch.JSchException;

import com.jcraft.jsch.Session;

/**

* SSH工具类

*

*/

public class SSHExcuteCommandHelper {

Session session = null;

ChannelExec openChannel = null;

/**

* @param host 主机ip

* @param name 用户名

* @param pwd 密码

* @param port ssh端口

*/

public SSHExcuteCommandHelper(String host, String user, String pwd, int port) {

JSch jsch = new JSch();

try {

session = jsch.getSession(user, host, port);

java.util.Properties config = new java.util.Properties();

config.put("StrictHostKeyChecking", "no");

session.setTimeout(1000);

session.setConfig(config);

session.setPassword(pwd);

} catch (JSchException e) {

e.printStackTrace();

}

}

/**

* 是否连接成功,调用如果不需要调用execCommand方法那么必须调用 disconnect方法关闭session

* @return

*/

public boolean canConnection(){

try {

session.connect();

return true;

} catch (JSchException e) {

e.printStackTrace();

return false;

}

}

/**

* 关闭连接

*/

public void disconnect(){

if (openChannel != null && !openChannel.isClosed()) {

openChannel.disconnect();

}

if (session != null && session.isConnected()) {

session.disconnect();

}

}

/**

* 执行命令

* @param command

* @return

*/

public String execCommand(String command) {

StringBuffer result = new StringBuffer();

try {

if(!session.isConnected()){

session.connect();

}

openChannel = (ChannelExec) session.openChannel("exec");

openChannel.setCommand(command);

//int exitStatus = openChannel.getExitStatus();

openChannel.connect();

InputStream in = openChannel.getInputhttp://Stream();

BufferedReader reader = new BufferedReader(

new InputStreamReader(in));

String tmpStr = "";

while ((tmpStr = reader.readLine()) != null) {

result.append(new String(tmpStr.getBytes("gbk"), "UTF-8")).append("\n");

}

} catch (Exception e) {

e.printStackTrace();

result.append(e.getMessage());

} finally {

disconnect();

}

return result.toString();

}

/**

* 解析

* @param result

* @return

*/

public List> parseResult(String result){

List> parseResult = new ArrayList>();

List list = null;

//

for (String line : result.split("\n")) {

list = new ArrayList();

String[] columns = {};

//这个是针对df命令的 [Mounted on] 其实就一个,如果用空格就会分割出两个

if(line.contains("Mounted ")){

columns = line.replace("Mounted ", "Mounted-").split(" ");

}else{

columns = line.split(" ");

}

for (String column : columns) {

if (!" ".equals(column) && !"".equals(column)) {

list.add(column);

}

}

parseResult.add(list);

}

return parseResult;

}

//测试

/* public static void main(String args[]) {

SSHExcuteCommandHelper execute = new SSHExcuteCommandHelper("192.168.175.128", "root", "123456", 22);

System.out.println("是否连接成功"+execute.canConnection());

String s = execute.execCommand("free -m");

System.out.println("解析前");

System.out.println(s);

System.out.println("解析后");

List> parseResult = execute.parseResult(s);

for (List l : parseResult) {

System.out.println(l);

}

}*/

}

pahttp://ckage com.save.until;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.text.SimpleDateFormat;

import java.util.Date;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.save.action.InspAction;

/**

*

* @author zhangzhuo

*

*/

public class WriteUntil {

final static Logger logger = LoggerFactory.getLogger(WriteUntil.class);

/**

* 新建文件夹,并创建文件写入数据

*/

public static void createFile(String basePath,String filePath, String filename, String input) {

String[] dirs = filePath.split("/");

String tempPath = basePath;

for (String dir : dirs) {

if (null == dir || "".equals(dir)) continue;

tempPath += "\\" + dir;

}

//文件夹判断

File dir = new File(tempPath);//"d:\\test_dir"

if (dir.exists()) {

if (dir.isDirectory()) {

logger.info("文件夹存在");

} else {

logger.info("同名文件存在,无法创建目录");

}

} else {

logger.info("文件夹不存在,开始创建");

dir.mkdirs();

}

//文件判断

File file = new File(tempPath+filename);//"d:\\test_file.txt"

if (file.exists()) {

logger.info(filename+"已存在");

} else {

logger.info(filename+"文件不存在,开始创建");

try {

file.createNewFile();

} catch (IOException e) {

e.printStackTrace();

}

}

//写入数据

//方法一、每次写入覆盖之前的

/* try {

FileOutputStream fos = new FileOutputStream(tempPath+filename);

fos.write(input.getBytes());

fos.close();

} catch (Exception e) {

e.printStackTrace();

}*/

try {

FileOutputStream fos = new FileOutputStream(tempPath+filename, true);

fos.write(input.getBytes());

fos.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

//测试

/* public static void main(String[] args) {

//createFile("E:\\log", "2014/16/2/", "\\2020.txt", "hahha");

Date date = new Date();

SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");

String dateString = formatter.format(date);

System.out.println(dateString);

}*/

}

applicationContext.xml

xmlns:context="http://springframework.org/schema/context" xmlns:p="http://springframework.org/schema/p"

xmlns:aop="http://springframework.org/schema/aop" xmlns:tx="http://springframework.org/schema/tx"

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans-4.0.xsd

http://springframework.org/schema/context http://springframework.org/schema/context/spring-context-4.0.xsd

http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop-4.0.xsd http://springframework.org/schema/tx http://springframework.org/schema/tx/spring-tx-4.0.xsd

http://springframework.org/schema/util http://springframework.org/schema/util/spring-util-4.0.xsd">

class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

xmlns:context="http://springframework.org/schema/context" xmlns:p="http://springframework.org/schema/p"

xmlns:aop="http://springframework.org/schema/aop" xmlns:tx="http://springframework.org/schema/tx"

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://springframework.org/schema/beans http://springframework.org/schema/beans/spring-beans-4.0.xsd

http://springframework.org/schema/context http://springframework.org/schema/context/spring-context-4.0.xsd

http://springframework.org/schema/aop http://springframework.org/schema/aop/spring-aop-4.0.xsd http://springframework.org/schema/tx http://springframework.org/schema/tx/spring-tx-4.0.xsd

http://springframework.org/schema/util http://springframework.org/schema/util/spring-util-4.0.xsd">

class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

config.properties

#测试用服务器

192.168.175.128={"username":"root","password":"123456","shell":"ps -ef|grep mongo\n,df -h\n, free -m\n, top\n","server":"mongod"}

192.168.175.129={"username":"root","password":"123456","shell":"ps -ef|grep redis\n,df -h\n, free -m\n, top\n","server":"mongod"}

log4j.properties

#指定根Logger,及日志输出级别

#大于等于该级别的日志将被输出( DEBUG < INFO < WARN < ERROR < FATAL ),设为OFF可以关闭日志

log4j.rootLogger=INFO, A1,A2

#指定log输出目的,这里设为输出日志到指定目录的文件my.log中

log4j.appender.A1=org.apache.log4j.FileAppender

log4j.appender.A1.File=E:\\save\\log\\xj.log

#指定日志信息的格式

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%r %d{yyyy-MM-dd HH:mm:ss} %c %p -%m%n

#把A2输出到控制台

log4j.appender.A2=org.apache.log4j.ConsoleAppender

log4j.appender.A2.layout=org.apache.log4j.PatternLayout

log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c %p -%m%n

pom.xml:

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

4.0.0

com.save

save-xj

war

0.0.1-SNAPSHOT

save-xj Maven Webapp

http://maven.apache.org

com.jcraft

jsch

0.1.53

com.alibaba

fastjson

1.2.31

org.springframework

spring-context

3.1.1.RELEASE

org.springframework

spring-context-support

3.1.1.RELEASE

org.springframework

spring-tx

3.1.1.RELEASE

org.springframework

spring-web

3.0.5.RELEASE

org.quartz-scheduler

quartz

1.8.5

log4j

log4j

1.2.17

org.slf4j

slf4j-log4j12

1.7.21

com.sun.mail

javax.mail

1.4.4

javax.mail

mail

1.4

org.apache.commons

commons-lang3

3.4

org.apache.tomcat.maven

tomcat7-maven-plugin

2.2

8080

/

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

4.0.0

com.save

save-xj

war

0.0.1-SNAPSHOT

save-xj Maven Webapp

http://maven.apache.org

com.jcraft

jsch

0.1.53

com.alibaba

fastjson

1.2.31

org.springframework

spring-context

3.1.1.RELEASE

org.springframework

spring-context-support

3.1.1.RELEASE

org.springframework

spring-tx

3.1.1.RELEASE

org.springframework

spring-web

3.0.5.RELEASE

org.quartz-scheduler

quartz

1.8.5

log4j

log4j

1.2.17

org.slf4j

slf4j-log4j12

1.7.21

com.sun.mail

javax.mail

1.4.4

javax.mail

mail

1.4

org.apache.commons

commons-lang3

3.4

org.apache.tomcat.maven

tomcat7-maven-plugin

2.2

8080

/


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java 基本算法之归并排序实例代码
下一篇:Java Timezone类常见问题_动力节点Java学院整理
相关文章

 发表评论

暂时没有评论,来抢沙发吧~