content: 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());
  		}
  	}
  }
  