java实现服务器巡查的代码

需求

用户,给了一大批服务器,需要检查服务器能否ping通,ssh密码是否正常,以及检查服务器的cpu,内存,硬盘占用情况。一个个检查肯定不现实,于是希望通过代码实现。

批量ping

1.Jdk1.5的InetAddresss方式

注意:使用时应注意,如果远程服务器设置了防火墙或相关的配制,可能会影响到结果。另外,由于发送ICMP请求需要程序对系统有一定的权限,当这个权限无法满足时, isReachable方法将试着连接远程主机的TCP端口。可能出现isReachable=false但是用cmd验证却能够ping通的情况。

代码实现:

/**
* 这个不可行,和ping的结果并不完全一致 尽量别用
* @param ip
* @return
*/
public static boolean netOk(String ip){
InetAddress address=null;
boolean netOk=false;
try {
address =InetAddress.getByName(ip);
netOk= address.isReachable(5000);
}catch (Exception e) {
e.printStackTrace();
}
return netOk;
}

2.最简单的办法,直接调用CMD

注意:如果出现Windows环境下可以正常ping通的,而在centOS(Linux)里面无法ping通,可能是被ping的设备上有设置ping包大小限制,限制在了32位以内。

最终使用

Process pro = Runtime.getRuntime().exec("ping -s 32 " + ipAddress );

并解析结果来进行判断。

命令行基础

其中n是次数,w是超时时间,单位是毫秒

ping -n 1 -w 1000 9.8.8.8

代码实现:

/**
*
* @param ipAddress
* @param pingTimes 单位是毫秒
* @param timeOut
* @return
*/
public static boolean ping(String ipAddress, int pingTimes, int timeOut) {
BufferedReader in = null;
Runtime r = Runtime.getRuntime(); // 将要执行的ping命令,此命令是windows格式的命令
String pingCommand ="ping " + ipAddress +" -n " + pingTimes +" -w " + timeOut;
try { // 执行命令并获取输出
System.out.println(pingCommand);
Process p = r.exec(pingCommand);
if (p == null) {
return false;
}
in = new BufferedReader(new InputStreamReader(p.getInputStream())); // 逐行检查输出,计算类似出现=23ms TTL=62字样的次数
int connectedCount =0;
String line = null;
while ((line = in.readLine()) != null) {
connectedCount += getCheckResult(line);
} // 如果出现类似=23ms TTL=62这样的字样,出现的次数=测试次数则返回真
return connectedCount == pingTimes;
} catch (Exception ex) {
ex.printStackTrace(); // 出现异常则返回假
return false;
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

// 若line含有=18ms TTL=16字样,说明已经ping通,返回1,否則返回0.
private static int getCheckResult(String line) { // System.out.println("控制台输出的结果为:"+line);
Pattern pattern = Pattern.compile("(\\d+ms)(\\s+)(TTL=\\d+)", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
return 1;
}
return 0;
}

3.Java调用shell执行ping命令

注意:这种需要在linux环境执行

命令行基础

其中 -c是次数,-W是超时时间,单位是秒

ping -c 2 -W 1 8.8.8.8

/**
*
* @param ipAddress
* @param pingTimes
* @param timeOut 单位 s
* @return
*/
public static boolean pingByShell(String ipAddress, int pingTimes, int timeOut){
String sh="ping -c "+pingTimes+" -W "+timeOut+" "+ipAddress;
String result = exeShell(sh);
if(result!=null){
if(result.contains("ttl")){
return true;
}
}
return false;
}


/**
* 执行shell并且返回结果
* @param sh
* @return
*/
public static String exeShell(String sh){
Process process =null;
List<String> processList =new ArrayList<String>();
try {
process = Runtime.getRuntime().exec(sh);

BufferedReader input =new BufferedReader(new InputStreamReader(process.getInputStream()));
String line ="";
while ((line = input.readLine()) !=null) {
processList.add(line);
}
input.close();
}catch (IOException e) {
e.printStackTrace();
return null;
}
String result = StringUtils.join(processList,"\n");
return result;
}

批量ssh检查

需求:

先检查网络是否通(这里我是先检查ssh用的22端口),不通的记录下来,端口通的,再用文档记录的登录信息ssh登录,将登录成功的和不成功的分别记录下来。

注意:有的服务器有安全策略,不要同一台服务器多次尝试。

依赖引入

<!--ssh  -->
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>

工具封装

package com.isi.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Calendar;

import org.apache.commons.lang3.StringUtils;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;


public class SshUtil {
private static String DEFAULT_CHAR_SET ="UTF-8";
private static String tipStr ="=======================%s=======================";
private static String splitStr ="=====================================================";

/**
* 登录主机
* @return
* 登录成功返回true,否则返回false
*/
public static Connection login(String ip, String userName, String password){
boolean isAuthenticated =false;
Connection conn =null;
long startTime = Calendar.getInstance().getTimeInMillis();
try {
conn =new Connection(ip);
conn.connect();// 连接主机

isAuthenticated = conn.authenticateWithPassword(userName, password);// 认证
if(isAuthenticated){
System.out.println(String.format(tipStr,"认证成功"));
}else {
System.out.println(String.format(tipStr,"认证失败"));
}
}catch (IOException e) {
System.err.println(String.format(tipStr,"登录失败"));
e.printStackTrace();
}
long endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("登录用时: " + (endTime - startTime)/1000.0 +"s\n" + splitStr);
return conn;
}


public static boolean pwdCheck(String ip, String userName, String password){
boolean isAuthenticated =false;
Connection conn =null;
long startTime = Calendar.getInstance().getTimeInMillis();
try {
conn =new Connection(ip);
conn.connect();// 连接主机

isAuthenticated = conn.authenticateWithPassword(userName, password);// 认证
if(isAuthenticated){
System.out.println(String.format(tipStr,"认证成功"));
return true;
}else {
System.out.println(String.format(tipStr,"认证失败"));
return false;
}
}catch (Exception e) {
System.err.println(String.format(tipStr,"登录失败"));
e.printStackTrace();
}finally {
if(conn!=null){
conn.close();
}
}
long endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("登录用时: " + (endTime - startTime)/1000.0 +"s\n" + splitStr);
return false;
}


/**
* 远程执行shell脚本或者命令
* @param cmd
* 即将执行的命令
* @return
* 命令执行完后返回的结果值
*/
public static String execute(Connection conn, String cmd){
String result ="";
Session session =null;
try {
if(conn !=null){
session = conn.openSession(); // 打开一个会话
session.execCommand(cmd); // 执行命令
result = processStdout(session.getStdout(), DEFAULT_CHAR_SET);

//如果为得到标准输出为空,说明脚本执行出错了
if(StringUtils.isBlank(result)){
System.err.println("【得到标准输出为空】\n执行的命令如下:\n" + cmd);
result = processStdout(session.getStderr(), DEFAULT_CHAR_SET);
}else{
System.out.println("【执行命令成功】\n执行的命令如下:\n" + cmd);
}
}
}catch (IOException e) {
System.err.println("【执行命令失败】\n执行的命令如下:\n" + cmd +"\n" + e.getMessage());
e.printStackTrace();
}finally {
if (conn !=null) {
conn.close();
}
if (session !=null) {
session.close();
}
}
return result;
}

/**
* 解析脚本执行返回的结果集
* @param in 输入流对象
* @param charset 编码
* @return
* 以纯文本的格式返回
*/
private static String processStdout(InputStream in, String charset){
InputStream stdout =new StreamGobbler(in);
StringBuffer buffer =new StringBuffer();
try {
BufferedReader br =new BufferedReader(new InputStreamReader(stdout, charset));
String line =null;
while((line = br.readLine()) !=null){
buffer.append(line +"\n");
}
}catch (UnsupportedEncodingException e) {
System.err.println("解析脚本出错:" + e.getMessage());
e.printStackTrace();
}catch (IOException e) {
System.err.println("解析脚本出错:" + e.getMessage());
e.printStackTrace();
}
return buffer.toString();
}

/**
* 判断端口是否通
* @param host
* @param port
* @param timeout
* @return
*/
public static boolean isHostConnectable(String host,int port,int timeout) {
Socket socket =new Socket();
try {
socket.connect(new InetSocketAddress(host, port),timeout);
socket.setSoTimeout(timeout);
}catch (IOException e) {
e.printStackTrace();
return false;
}finally {
try {
socket.close();
}catch (IOException e) {
e.printStackTrace();
}
}
return true;
}

}

密码核对

public static void main(String[] args){
String ip ="192.168.4.188"; // 此处根据实际情况,换成自己需要访问的主机IP
String userName ="root";
String password ="123456";
boolean flag = pwdCheck(ip, userName, password);
System.out.println("flag===="+flag);

}

资源巡查

使用封装的sshUtil

public static void main(String[] args){
// 此处根据实际情况,换成自己需要访问的主机IP
String ip ="192.168.4.188";
String userName ="root";
String password ="123456";
/* boolean flag = pwdCheck(ip, userName, password);
System.out.println("flag===="+flag);*/

Connection connection = login(ip, userName, password);

//查看最大的盘 指定---为分隔符,默认的分隔符java无法指定
String max_disk_cmd="df | sort -k2nr | head -1 | awk '{print $2,$3,$4,$5}' OFS='---' ";
//查看内存使用情况
String free_mem_cmd="free | sort -k2nr | head -1 | awk '{print $2,$3,$4}' OFS='---'";
//计算cpu使用率, -n number:指定在结束前应该产生的最大迭代次数或帧数,一般迭代次数越大,获取到的cpu使用率越准确; 本脚本中是迭代了5次,"-n5"
String cpu_use_cmd="top -b -n5 | fgrep \"Cpu(s)\" | tail -1 | awk -F'id,' '{split($1, vs, \",\"); v=vs[length(vs)]; sub(/\\s+/, \"\", v);sub(/\\s+/, \"\", v); printf \"%d\", 100-v;}'";

String result = execute(connection, cpu_use_cmd);
System.out.println("result = " + result);
String[] datas = result.split("---");
String str = Arrays.toString(datas);
System.out.println("str = " + str);
closeConn(connection);
}

使用命令组合 sort

#-n: --numeric-sort    按照数字的值进行比较

#-k:--key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2

        按指定的列做排序

#-r:--reverse    反序排列

-t:指定排序用的字段的分隔符

sort -t":" -k 3 -nr/etc/passwd

按两个字段做排序:

sort -t: -k7 -k3nr/etc/passwd

head

head   -n  1  显示文件前1行内容

head   -n  -1  显示文件除了最后1行的内容

head   -c   5  显示文件前n个字节

 head   -c   -5  显示文件除了最后5个字节的内容

awk

输出指定列

awk '{print $1,$4}' test


格式化输出,指定输出分隔符

awk '{printf "%-8s %-10s\n",$1,$4}' test

也可以用

awk '{print $1,$2}' OFS=' '


 指定输入分隔符

awk -F, '{print $1,$2}' test


推荐 收藏
评论(0) 阅读(217)
刷新评论 返回顶部
签名 : 喜欢现在的自己吗?
洋最新博客