package com.sohu.cache.server.nmon;
import java.io.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sohu.cache.server.data.OS;
import com.sohu.cache.server.data.OSInfo;
import com.sohu.cache.ssh.SSHTemplate.DefaultLineProcessor;
import com.sohu.cache.ssh.SSHTemplate.Result;
import com.sohu.cache.ssh.SSHTemplate.SSHSession;
import com.sohu.cache.util.NMONFileFactory;
import com.sohu.cache.util.OSFactory;
/**
* 服务器监控脚本服务(nmon识别和监控)
*/
public class NMONService {
private static final Logger logger = LoggerFactory.getLogger(NMONService.class);
//获取系统版本位数命令
public static final String OS_INFO_CMD = "/bin/uname -a; /bin/cat /etc/issue";
//nmon路径
public static final String NMON_DIR = "/opt/cachecloud/soft/";
//nmon文件名
public static final String NMON = "nmon";
//nmon完整路径
public static final String NMON_FILE = NMON_DIR + NMON;
//获取nmon版本
public static final String NMON_VERSION = "[ -e \""+NMON_FILE+"\" ] && "+NMON_FILE+" -V";
//nmon输出的结果文件
public static final String NMON_LOG = "/tmp/nmon.log";
//nmon输出的老结果文件
public static final String NMON_OLD_LOG = "/tmp/nmon.old.log";
//tcp输出的结果文件
public static final String SOCK_LOG = "/tmp/sock.log";
//ulimit输出的结果文件
public static final String ULIMIT_LOG = "/tmp/ulimit.log";
//nmon监控启动
public static final String START_SERVER_COLLECT = NMON_FILE+" -F " + NMON_LOG + " -s0 -c1;" +
"/bin/grep TCP /proc/net/sockstat > " + SOCK_LOG +
";ulimit -n -u > " + ULIMIT_LOG;
//创建nmon路径
public static final String MK_NMON_DIR = "/bin/mkdir -p /opt/cachecloud/soft/";
/**
* 启动nmon收集系统状况
* @param ip
* @param session
* @return @OSInfo 收集到的操作系统信息
*/
public OSInfo start(String ip, SSHSession session) {
Result startCollectResult = session.executeCommand(START_SERVER_COLLECT);
if(!startCollectResult.isSuccess()) {
logger.error("start nmon "+ip+" err:"+startCollectResult.getResult(),
startCollectResult.getExcetion());
//执行命令没有发生异常,则nmon可能不存在或有问题
if(startCollectResult.getExcetion() == null) {
//尝试处理出错信息
return initNmon(ip, session);
}
}
return null;
}
/**
* 尝试修复启动失败的错误
* @param ip
* @param session
*/
private OSInfo initNmon(String ip, SSHSession session) {
//获取nmon版本
String version = getNMONVersion(ip, session);
//获取操作系统原始信息
OSInfo osInfo = getOSInfo(ip, session);
OS os = null;
//nmon文件不存在,需要根据操作系统识别是否支持
if(null == version) {
logger.warn("{} not exist {}", ip, NMON_FILE);
//将原始信息转换为可识别的操作系统
os = OSFactory.getOS(osInfo);
} else {
//nmon存在,但是版本有问题,此时不应该再判断系统信息了,直接用默认的
logger.warn("{} {} version err:"+version, ip, NMON_FILE);
os = OSFactory.getDefaultOS(osInfo);
}
if(os == null) {
logger.error("unkonw os info={}", osInfo);
return null;
}
//获取nmon文件
File nmonFile = NMONFileFactory.getNMONFile(os);
if(nmonFile == null) {
logger.warn("{} no corresponding nmon file", os);
nmonFile = NMONFileFactory.getNMONFile(OSFactory.getDefaultOS(osInfo));
}
//将nmon文件传输至服务器
sendNMONToServer(ip, session, nmonFile);
return osInfo;
}
/**
* 获取nmon文件版本
* @param ip
* @param session
* @return 存在返回版本,不存在返回null, 执行错误返回异常
*/
private String getNMONVersion(String ip, SSHSession session) {
Result nmonVersionResult = session.executeCommand(NMON_VERSION);
if(nmonVersionResult.isSuccess()) {
return nmonVersionResult.getResult();
} else {
logger.error(NMON_VERSION+" err:"+nmonVersionResult.getResult(), nmonVersionResult.getExcetion());
}
return null;
}
/**
* 获取操作系统信息
* @param ip
* @param session
* @return OSInfo
*/
private OSInfo getOSInfo(String ip, SSHSession session) {
final OSInfo osInfo = new OSInfo();
session.executeCommand(OS_INFO_CMD, new DefaultLineProcessor() {
public void process(String line, int lineNum) throws Exception {
switch(lineNum) {
case 1:
osInfo.setUname(line);
break;
case 2:
osInfo.setIssue(line);
}
}
});
return osInfo;
}
/**
* 将nmon文件scp到服务器上
* @param ip
* @param session
* @param nmonFile
*/
private void sendNMONToServer(String ip, SSHSession session, File nmonFile) {
Result mkResult = session.executeCommand(MK_NMON_DIR);
if(!mkResult.isSuccess()) {
logger.error("mkdir err:"+mkResult.getResult(), mkResult.getExcetion());
return;
}
Result scpRst = session.scpToFile(nmonFile.getAbsolutePath(), NMON, NMON_DIR);
if(scpRst.isSuccess()) {
logger.info("scp {} to {} success", nmonFile.getAbsolutePath(), ip);
} else {
logger.error("scp to "+ip+" err", scpRst.getExcetion());
}
}
}