Authored by zhangmingm

检测宕机相关的类。

package com.sitech.ismp.check.downtime;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.sitech.util.SqlMapFactory;
import org.apache.log4j.Logger;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @author frank zmm@honggroup.com.cn
* @Description: 检查主机,数据库,中间件的连接状态dao.
* @Package com.sitech.ismp.check.downtime
* @ClassName: com.sitech.ismp.check.downtime.CheckConnectionDao
* @date 2017年04月22日 15:05
*/
public class CheckConnectionDao {
protected static SqlMapClient sqlmapClient;
protected static SqlMapClient oracleSqlMapClient ;
/**
* 因为继承 basedao 后,报basedao 找不到,因此写到方法里面。
*/
static {
sqlmapClient = SqlMapFactory.getDefaultSqlMapClient();
oracleSqlMapClient= SqlMapFactory.getOracleSqlMapClient("oracle_sqlmap.xml");
}
private static Logger log=Logger.getLogger(CheckConnectionDao.class);
/**
* 插入ping结果。
* @param bean
*/
public void addPingConnectionState(ConnectionStateBean bean){
try {
sqlmapClient.insert("addPingConnectionState", bean);
log.info("******* CheckConnectionDao **** execute method addPingConnectionState ******");
} catch (SQLException e) {
log.error("Exception while addPingConnectionState.",e);
}
}
/**
* 根据IP获取该IP对应ping不通的次数。
* @param map
* @return
*/
public List<ConnectionStateBean> getStatByParam(HashMap<String, Object> map){
List<ConnectionStateBean> beanList=new ArrayList<ConnectionStateBean>();
try {
beanList=sqlmapClient.queryForList("getStatByParam", map);
} catch (SQLException e) {
e.printStackTrace();
}
return beanList;
}
}
... ...
package com.sitech.ismp.check.downtime;
import com.sitech.util.upload.RomoteController;
import com.sitech.util.upload.SSHThread;
import com.sitech.util.upload.TelnetThread;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.GenericAddress;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
/**
* @author frank zmm@honggroup.com.cn
* @Description: 检查主机,数据库,中间件的连接状态实现类。
* @Package com.sitech.ismp.check.downtime
* @ClassName: com.sitech.ismp.check.downtime.CheckConnectionService
* @date 2017年04月22日 14:36
*/
public class CheckConnectionService {
private static Logger log= Logger.getLogger(CheckConnectionService.class);
private Snmp mSnmp = null;
private CommunityTarget mCommunityTarget = null;
public String getDbConnectionState(ParamterBean bean){
boolean state=contentWithJdbc(bean);
String flag=null;
if(state){
flag="UP";
}else{
flag="DOWN";
}
// addDbConnectionState(bean,flag);
return flag;
}
/**
* 使用snmp协议连接Windows主机。
* @param bean
* @return
*/
private boolean contentWithJdbc(ParamterBean bean){
String type=bean.getType(); // 数据库类型
String className=null;
if("oracle".equalsIgnoreCase(type)){
className="oracle.jdbc.driver.OracleDriver";
}else if("mysql".equalsIgnoreCase(type)){
className="com.mysql.jdbc.Driver";
}else if("sqlServer".equalsIgnoreCase(type)){
className="com.microsoft.jdbc.sqlserver.SQLServerDriver";
}else if("db2".equalsIgnoreCase(type)){
className="com.ibm.db2.jcc.DB2Driver";
}
Connection conn=null;
String dsUser=bean.getUSER_NAME();
String dsPassword=bean.getPASSWORD();
String url=bean.getURL();
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
log.error("没有找到对应的驱动程序!",e);
}
try {
conn= DriverManager.getConnection(url, dsUser, dsPassword);
} catch (SQLException e) {
log.error("根据用户信息,URL获取连接异常!",e);
}
boolean temp=false;
if(null !=conn){
temp=true;
try {
conn.close();
conn=null;
} catch (SQLException e) {
e.printStackTrace();
}
}
return temp;
}
/**
* 使用 SSH 或 Telnet 协议 获取设备的连接结果,能连接返回 UP,否则返回 DOWN.
* @param bean
* @return
*/
public String getConnectionState4Snmp(ParamterBean bean){
boolean state=contentWithSnmp(bean);
String flag=null;
if(state){
flag="UP";
}else{
flag="DOWN";
}
return flag;
}
/**
* 使用snmp协议连接Windows主机。
* 初始化snmp后,获取主机名称,如果能获取到的话说明能连接,否则不能连接。
* @param bean
* @return
*/
private boolean contentWithSnmp(ParamterBean bean){
init(bean);
String nameoid=".1.3.6.1.2.1.1.5.0";
String result = null;
PDU pdu = new PDU();
VariableBinding var = new VariableBinding(new OID(nameoid), new OctetString());
pdu.add(var);
pdu.setType(PDU.GET);
ResponseEvent res = null;
try {
res = mSnmp.send(pdu, mCommunityTarget);
} catch (IOException e) {
log.error("mSnmp.send() has error!");
e.printStackTrace();
}
PDU result_pdu = res.getResponse();
if (result_pdu != null) {
VariableBinding vb = result_pdu.get(0);
result = vb.getVariable().toString();
}
boolean isConnection=false;
if(!StringUtils.isEmpty(result)){
isConnection=true;
}
return isConnection;
}
/**
* 初始化snmp。
* @param bean
*/
private void init(ParamterBean bean){
String ip=bean.getDEVICE_IP();
String communityStr=bean.getCOMMUNITY();
int port=bean.getPROTOCOL_PORT();
String addr = "udp:" + ip + "/" + port;
OctetString community = new OctetString(communityStr);
Address address = GenericAddress.parse(addr);
mCommunityTarget = new CommunityTarget(address, community);
TransportMapping vTransport = null;
try {
vTransport = new DefaultUdpTransportMapping();
} catch (IOException e) {
log.error(" create vTransport has error!",e);
}
mSnmp = new Snmp(vTransport);
try {
vTransport.listen();
} catch (IOException e) {
log.error(" vTransport.listen() has error!",e);
}
mCommunityTarget.setCommunity(community);
try {
mCommunityTarget.setAddress(new UdpAddress(InetAddress.getByName(ip), port));
} catch (UnknownHostException e) {
log.error(" setAddress() has error!",e);
}
mCommunityTarget.setRetries(2);
mCommunityTarget.setTimeout(5000);
mCommunityTarget.setVersion(SnmpConstants.version2c);
}
/**
* 使用 SSH 或 Telnet 协议 获取设备的连接结果,能连接返回 UP,否则返回 DOWN.
* @param bean
* @return
*/
public String getConnectionState4SshOrTelnet(ParamterBean bean){
boolean sshState=contentWithSsh(bean);
String flag=null;
if(sshState){
flag="UP";
}else{
flag="DOWN";
}
return flag;
}
/**
* 进行ssh连接,判断是否可以连接成功。
* windows操作系统使用 TelnetThread类连接。 Windows的客户端需要配置并开启Telnet相关的服务。
* @return
*/
private boolean contentWithSsh(ParamterBean bean){
String protocol=bean.getPROTOCOL();
String ipAddr=bean.getDEVICE_IP();
int protocolPort=bean.getPROTOCOL_PORT();
String userName=bean.getUSER_NAME();
String password=bean.getPASSWORD();
boolean temp=false;
RomoteController tt = null;
log.info("execute contentWithSsh method,params is: ipAddr="+ipAddr+",protocol="+protocol+",protocolPort="+protocolPort+",userName="+userName);
if(loginParamterIsOk(protocol,ipAddr,protocolPort,userName,password)){
try {
if (protocol != null && protocol.equalsIgnoreCase("telnet")) {
tt = new TelnetThread(ipAddr, protocolPort, userName, password);
} else if (protocol != null && protocol.equalsIgnoreCase("ssh")) {
tt = new SSHThread(ipAddr, protocolPort, userName, password);
}else{
log.error("===================== unknown protocol =====================");
}
}catch (Exception e){
log.error(protocol+"connect have exception!");
}
tt.initial();
boolean flag=tt.isAuthorized();
if (flag){ // 认证通过
log.info(ipAddr+" SSH connect,Authorized result is true authorized success!");
temp=true;
}else{
log.info(ipAddr+" SSH connect,Authorized result is false authorized fail!");
}
}
return temp;
}
/**
* 获取ping的结果,UP 或 DOWN。
* 该方法负责一个采集周期内的3次ping操作。
* @return
*/
public String getPingState(ParamterBean bean){
String ipAddr =bean.getDEVICE_IP();
String result=null;
boolean flag=false;
if(!StringUtils.isEmpty(ipAddr)){
int pingErrorCount=0; // ping 不通的次数,ping3次。
int interval=8; // 时间间隔8秒。
boolean temp=false;
for(int i=0;i<3;i++){
temp=executeCommand(ipAddr); // ping不通返回false。
log.info("["+ipAddr+"]ping result is ["+temp+"],(true:can connect;false:can't connect)");
if(!temp){
pingErrorCount++;
}
try {
Thread.sleep(interval*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(pingErrorCount == 3){
log.info("["+ipAddr+"] can't connect 3 times.");
}else{
flag=true;
log.info("["+ipAddr+"] can connect.");
}
if(flag){
result="UP";
}else{
result="DOWN";
}
}
return result;
}
/**
* 返回ping后的结果。
* @param ipAddr ip 地址。
* @return
*/
private boolean executeCommand(String ipAddr){
boolean flag=false;
if(!StringUtils.isEmpty(ipAddr)){
String command = "/bin/ping -c 3 -w 3 " + ipAddr;;
// 执行command 命令。
String line = null;
StringBuilder sb = new StringBuilder();
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
process = runtime.exec(command);
} catch (IOException e) {
log.error("execute command ["+command+"] has some error!");
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
while ((line = bufferedReader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
log.error("======== bufferedReader.readLine() has some error!");
}
String pingResult=sb.toString();
/**
* 当执行结果出现下面字符说明已经执行完成。
* ping 通的时候 结果包含【min/avg/max/mdev】
* ping 不通的时候 结果包含【100% packet loss】
*/
if(pingResult.contains("100% packet loss") || (pingResult.contains("min/avg/max/mdev"))){
process.destroy();
log.info("execute command ["+command+"] finish!");
}
String os = System.getProperty("os.name").toLowerCase();
log.info("------------ operator system is :" + os);
// 解析command命令结果,包含【100% packet loss】 意味着ping不通,返回 false。
if(os.indexOf("linux") >= 0){
if (!StringUtils.isEmpty(pingResult)) {
if(!pingResult.contains("100% packet loss")){
flag = true;
}
}
}
}
return flag;
}
/**
* 判断所有的参数是否为空。
* @param protocol 协议类型
* @param ipAddr IP地址
* @param protocolPort 协议端口
* @param userName 用户名
* @param password 密码
* @return
*/
private boolean loginParamterIsOk(String protocol,String ipAddr,int protocolPort,String userName,String password){
boolean flag=true;
if(StringUtils.isEmpty(protocol))
flag=false;
if(StringUtils.isEmpty(ipAddr))
flag=false;
if(StringUtils.isEmpty(protocolPort+""))
flag=false;
if(StringUtils.isEmpty(userName))
flag=false;
if(StringUtils.isEmpty(password))
flag=false;
return flag;
}
/**
* 插入ping结果。
* @param bean
*/
public void addPingConnectionState(ConnectionStateBean bean){
CheckConnectionDao dao=new CheckConnectionDao();
dao.addPingConnectionState(bean);
}
/**
* 将ParamterBean与state设置到ConnectionStateBean的属性上。
* @param bean
* @param state
* @return
*/
public ConnectionStateBean getBean(ParamterBean bean,String state){
ConnectionStateBean stateBean=new ConnectionStateBean();
stateBean.setDEVICE_ID(UUID.randomUUID().toString());
stateBean.setDEVICE_IP(bean.getDEVICE_IP());
stateBean.setCREATE_DATE(new Date().getTime());
return stateBean;
}
/**
* 根据IP与时间获取该时间段内ping不通的次数。
* 按照降序查询头3条,如果3条数据状态都为down,则视为宕机。
* @param ip
* @return
*/
public List<ConnectionStateBean> getStatByParam(String ip){
CheckConnectionDao dao=new CheckConnectionDao();
HashMap<String, Object> map=new HashMap<String, Object>();
map.put("DEVICE_IP",ip);
return dao.getStatByParam(map);
}
public static void main(String [] args){
long beforeTime = 15*60*1000+500;//15.5分钟前
long afterTime = 30*1000;//半分钟后
Date now = new Date();
long nn=now.getTime();
long before = nn - beforeTime;
long after = nn + afterTime;
System.out.println(nn);
System.out.println(after);
System.out.println(before);
}
}
... ...
package com.sitech.ismp.check.downtime;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @author frank zmm@honggroup.com.cn
* @Description: 检查主机,数据库,中间件的连接状态。
* 其中主机包含 Linux/unix ping ssh 2种状态;Windows ping snmp 2种状态;
* 数据库 ping jdbc 2种状态; 中间件(Tomcat) ping jmx状态
*
* 需要区分 Windows与其他系统。在方法参数上,将map转换成CheckConnectionBean再使用。
* @Package com.sitech.ismp.check.downtime
* @ClassName: com.sitech.ismp.check.downtime.CheckConnectionState
* @date 2017年04月22日 14:17
*/
public class CheckConnectionState {
private static Logger log= Logger.getLogger(CheckConnectionState.class);
CheckConnectionService service=new CheckConnectionService();
//******************************* 获取主机相关状态代码 *******************************//
//******* 主机分为Linux/unix与Windows两大类,连接的时候前者使用ssh后者使用snmp ************//
//******************************* 获取主机相关状态代码 *******************************//
/**
* 获取设备的ping结果,能ping通返回 UP,否则返回 DOWN.
* 需要连续ping3次,将ping的结果插入到 TB_CONNECTION_STATE.
* @param bean
* @return
*/
public String getPingState(ParamterBean bean){
String state=service.getPingState(bean);
String type=bean.getType();
if("windows".equals(type) || "linux".equals(type)|| "unix".equals(type)){
String ip=bean.getDEVICE_IP();
if(!StringUtils.isEmpty(ip)){
ConnectionStateBean stateBean=new ConnectionStateBean();
stateBean.setDEVICE_STATE(state); // 设备状态
stateBean.setDEVICE_ID(UUID.randomUUID().toString());
stateBean.setDEVICE_IP(bean.getDEVICE_IP());
stateBean.setCREATE_DATE(new Date().getTime());
service.addPingConnectionState(stateBean);
}
}
return state;
}
/**
* 根据IP获取ping不通的次数。只取集合中的前3条数据。当都为down的时候表明已经宕机,少于3次不算宕机。
* @param ip
* @return
*/
public String getPingErrorState(String ip){
List<ConnectionStateBean> list=service.getStatByParam(ip);
int temp=0;
String state=null;
ConnectionStateBean bean=null;
if(null !=list && list.size()>0){
for(int i=0;i<3;i++){
bean=list.get(i);
state=bean.getDEVICE_STATE();
if("DOWN".equals(state)){
temp++;
}
}
}
String stat="UP";
if(temp==3){
stat="DOWN";
}
return stat;
}
/**
* 使用 SSH 或 Telnet 协议 获取设备的连接结果,能连接返回 UP,否则返回 DOWN.
* @param bean
*/
public String getConnectionState4SshOrTelnet(ParamterBean bean){
String state=service.getConnectionState4SshOrTelnet(bean);
return state;
}
/**
* 使用 SNMP 协议 获取设备的连接结果,能连接返回 UP,否则返回 DOWN.
* @param bean
*/
public String getConnectionState4Snmp(ParamterBean bean){
String state=service.getConnectionState4Snmp(bean);
log.info("***** getConnectionState4Snmp ***state= "+state+"**************");
return state;
}
/**
* Oracle数据库连接状态
* @param bean
*/
public String getOracleConnectionState(ParamterBean bean){
bean.setType("oracle");
String state=service.getDbConnectionState(bean);
return state;
}
public static void main(String [] args){
CheckConnectionState ss=new CheckConnectionState();
ParamterBean bean1=new ParamterBean();
bean1.setUSER_NAME("Administrator");
bean1.setPASSWORD("0213");
bean1.setPROTOCOL_PORT(161);
bean1.setDEVICE_IP("192.168.1.141");
ss.getConnectionState4Snmp(bean1);
ParamterBean bean=new ParamterBean();
bean.setPASSWORD("tiger");
bean.setUSER_NAME("scott");
bean.setURL("jdbc:oracle:thin:@192.168.1.130:1521:ORCL");
System.out.println(ss.getOracleConnectionState(bean));
}
/**
* Mysql 数据库连接状态
* @param bean
*/
public String getMysqlConnectionState(ParamterBean bean){
bean.setType("Mysql");
String state=service.getDbConnectionState(bean);
return state;
}
/**
* SqlServer 数据库连接状态
* @param bean
*/
public void getSqlServerConnectionState(ParamterBean bean){
bean.setType("SqlServer");
String state=service.getDbConnectionState(bean);
}
/**
* Db2 数据库连接状态
* @param bean
*/
public void getDb2ConnectionState(ParamterBean bean){
bean.setType("Db2");
String state=service.getDbConnectionState(bean);
}
}
... ...
package com.sitech.ismp.check.downtime;
/**
* @author frank zmm@honggroup.com.cn
* @Description: 存放检测主机连接的各种参数。
* @Package com.sitech.ismp.check.downtime
* @ClassName: com.sitech.ismp.check.downtime.ConnectionStateBean
* @date 2017年04月22日 14:34
*/
public class ConnectionStateBean {
// ID
private String DEVICE_ID;
// 设备IP地址
private String DEVICE_IP;
// 设备状态
private String DEVICE_STATE;
// 创建时间
private Long CREATE_DATE;
public String getDEVICE_ID() {
return DEVICE_ID;
}
public void setDEVICE_ID(String DEVICE_ID) {
this.DEVICE_ID = DEVICE_ID;
}
public String getDEVICE_IP() {
return DEVICE_IP;
}
public void setDEVICE_IP(String DEVICE_IP) {
this.DEVICE_IP = DEVICE_IP;
}
public String getDEVICE_STATE() {
return DEVICE_STATE;
}
public void setDEVICE_STATE(String DEVICE_STATE) {
this.DEVICE_STATE = DEVICE_STATE;
}
public Long getCREATE_DATE() {
return CREATE_DATE;
}
public void setCREATE_DATE(Long CREATE_DATE) {
this.CREATE_DATE = CREATE_DATE;
}
@Override
public String toString() {
return "ConnectionStateBean{" +
"DEVICE_ID='" + DEVICE_ID + '\'' +
", DEVICE_IP='" + DEVICE_IP + '\'' +
", DEVICE_STATE='" + DEVICE_STATE + '\'' +
", CREATE_DATE=" + CREATE_DATE +
'}';
}
}
... ...
package com.sitech.ismp.check.downtime;
/**
* @author frank zmm@honggroup.com.cn
* @Description: 存放检测主机连接的各种参数。
* @Package com.sitech.ismp.check.downtime
* @ClassName: com.sitech.ismp.check.downtime.ParamterBean
* @date 2017年04月22日 15:08
*/
public class ParamterBean {
// 设备IP地址
private String DEVICE_IP;
// 连接协议(ssh/telnet)
private String PROTOCOL;
// 协议端口
private int PROTOCOL_PORT;
// 用户名(分主机与数据库)
private String USER_NAME;
// 密码(分主机与数据库)
private String PASSWORD;
private String URL;
private String COMMUNITY;
private String Type;
public ParamterBean() {
}
public ParamterBean(String DEVICE_IP) {
this.DEVICE_IP = DEVICE_IP;
}
public String getDEVICE_IP() {
return DEVICE_IP;
}
public void setDEVICE_IP(String DEVICE_IP) {
this.DEVICE_IP = DEVICE_IP;
}
public String getPROTOCOL() {
return PROTOCOL;
}
public void setPROTOCOL(String PROTOCOL) {
this.PROTOCOL = PROTOCOL;
}
public int getPROTOCOL_PORT() {
return PROTOCOL_PORT;
}
public void setPROTOCOL_PORT(int PROTOCOL_PORT) {
this.PROTOCOL_PORT = PROTOCOL_PORT;
}
public String getUSER_NAME() {
return USER_NAME;
}
public void setUSER_NAME(String USER_NAME) {
this.USER_NAME = USER_NAME;
}
public String getPASSWORD() {
return PASSWORD;
}
public void setPASSWORD(String PASSWORD) {
this.PASSWORD = PASSWORD;
}
public String getType() {
return Type;
}
public void setType(String type) {
Type = type;
}
public String getURL() {
return URL;
}
public void setURL(String URL) {
this.URL = URL;
}
public String getCOMMUNITY() {
return COMMUNITY;
}
public void setCOMMUNITY(String COMMUNITY) {
this.COMMUNITY = COMMUNITY;
}
@Override
public String toString() {
return "ParamterBean{" +
"DEVICE_IP='" + DEVICE_IP + '\'' +
", PROTOCOL='" + PROTOCOL + '\'' +
", COMMUNITY='" + COMMUNITY + '\'' +
", PROTOCOL_PORT=" + PROTOCOL_PORT +
", USER_NAME='" + USER_NAME + '\'' +
", PASSWORD='" + PASSWORD + '\'' +
'}';
}
}
... ...