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"; // 此處根據實際情況,換成自己需要訪問的主機IPString userName = "root";String password = "123456";boolean flag = pwdCheck(ip, userName, password);System.out.println("flag===="+flag);}資源巡查
使用封裝的sshUtil
public static void main(String[] args){// 此處根據實際情況,換成自己需要訪問的主機IPString 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來源
linux(centos8):用sort對文本內容排序 - 劉宏締的架構森林 - 博客園一,sort的用途 1,作用: sort命令用于將文本文件內容加以排序。 它能夠以行為單位來排序 2,sort常與uniq搭配使用,原因: 用uniq命令去重時, 需要相同的每行位置相鄰才能生效, 所https://www.cnblogs.com/architectforest/p/12921979.html
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
來源
linux awk命令根據分隔符輸出,詳解Linux中的awk命令_玲瓏閣玉韋的博客-CSDN博客簡介awk是一個強大的文本分析工具,相對于grep的查找,sed的編輯,awk在其對數據分析并生成報告時,顯得尤為強大。簡單來說awk就是把文件逐行的讀入,以空格為默認分隔符將每行切片,切開的部分再進行各種分析處理。awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。awk其名稱得自于它的創始人 Alfred Aho 、Pete...https://blog.csdn.net/weixin_42572602/article/details/116557799
總結
以上是生活随笔為你收集整理的java实现服务器巡查的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 单条删除和批量删除的思路和实现
- 下一篇: “易管田”高标准农田巡查管护数字化解决方