JAVA执行远端服务器的脚本
问题描述
工作中遇到这样一个问题,我们的应用为了实现高可用会采取双机部署,拓扑图大致如下:

这种方案可以简单的保证高可用,即便应用服务器或者数据库服务器其中一台宕机,整个系统的功能还是不会受到影响,但是这里会出现一个问题:例如当应用服务器1宕机了,所有的负载集中到应用服务器2上以后,因为系统功能是正常的,而作为产品交付客户后也没有现场的实施或运维人员在,我们并不知道有一台服务器已经宕机了,所以,我们要实现一个简单的监控,去查看每个服务器上的每个应用程序是否正常的启动着,当异常的时候可以通过网页重新启动一下.
实现思路
在我们的数据库中建立两张表,一张服务器表,一张应用表,服务器表作为主表
在服务器对应位置为每一个需要监控的应用放置一个监控的SHELL脚本,一个重启的SHELL脚本
在WEB服务中增加定时任务,采用轮询的方式执行监控脚本,如果返回值正常,则更新应用表中的状态字段,同时在WEB页面中加入一个监控页面,可以在应用状态异常的通过按钮点击完成重启操作
技术要点
基本的增删改查并没有什么问题,在我的设计思路中有两个点需要注意
- SHELL脚本的编写
这个领域我并不了解,交由负责实施的同事解决 - JAVA任务调度
这部分我可能会单独写一篇博客来记录一下我自己学习Spring Boot中的 @Scheduled注解和比较常用的Quartz框架的过程和对比 - JAVA链接服务器并执行SHELL
这里我采用的依赖包是:
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
在有了这个依赖包之后,我就只用提供两个共通的工具方法就可以了,一个是登录一下服务器,看看服务器是否宕机,一个是执行SELL脚本的方法,根据SHELL的返回值确定监控的服务是否正常的方法就好了
代码实现
因为执行SHELL脚本的时候可能是给出正常的返回值,也可能是异常的信息,这里需要一个JAVA Bean来接收这两个消息,代码如下:
import java.io.Serializable;
/**
* shell脚本执行结果<br/>
* 先通过getSuccess方法判断命令是否执行成功<br/>
* 执行成功的时候采用result作为返回值<br/>
* 执行不成功采用errorOut作为返回值<br/>
*
* @author weizj
*/
public class ShellResult implements Serializable {
private static final long serialVersionUID = -110281463872334425L;
/** 脚本输出结果 */
private String result;
/** 异常输出结果 */
private String errorMsg;
/** 回话退出状态 */
private int exitStatus;
public ShellResult() {
}
public ShellResult(String result, String errorOut, int exitStatus) {
this.result = result.trim();
this.errorMsg = errorOut.trim();
this.exitStatus = exitStatus;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result.trim();
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg.trim();
}
public int getExitStatus() {
return exitStatus;
}
public void setExitStatus(int exitStatus) {
this.exitStatus = exitStatus;
}
/** 是否成功关闭会话 */
public boolean getSuccess() {
return this.exitStatus == 0;
}
}
工具类方法代码如下:
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* java执行shell脚本的工具类
*
* @author weizj
*/
public class GanymedUtils {
private static final Logger logger = LoggerFactory.getLogger(GanymedUtils.class);
/** 超时时间 */
private static final int TIME_OUT = 1000 * 5 * 60;
/**
* 登录远端服务器
*
* @param ip 主机地址
* @param userName 用户名
* @param password 密码
* @return 当前的连接
* @throws IOException
*/
public static Connection login(String ip, String userName, String password) throws IOException {
Connection connection = new Connection(ip);
connection.connect();
return connection.authenticateWithPassword(userName, password) ? connection : null;
}
/**
* 执行一个命令
*
* @param ip 主机ip
* @param userName 用户名
* @param password 密码
* @param scripts 需要执行的脚本
* @param charset 字符编码
* @return ShellResult类
* @throws Exception
*/
public static ShellResult exec(String ip, String userName, String password, String scripts, Charset charset) throws IOException {
Connection connection = login(ip, userName, password);
if (connection == null) {
throw new RuntimeException("登录远程服务器出现异常,ip为:" + ip);
}
// Open a new {@link Session} on this connection
Session session = connection.openSession();
try (InputStream stdOut = new StreamGobbler(session.getStdout()); InputStream stdErr = new StreamGobbler(session.getStderr())) {
// Execute a command on the remote machine.
session.execCommand(scripts);
String outStr = processStream(stdOut, charset.name());
String outErr = processStream(stdErr, charset.name());
session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
int exitStatus = session.getExitStatus();
return new ShellResult(outStr, outErr, exitStatus);
}
}
/**
* 执行脚本
*
* @param in 输入流
* @param charset 字符编码
* @return
* @throws IOException
*/
private static String processStream(InputStream in, String charset) throws IOException {
byte[] buf = new byte[1024];
StringBuilder sb = new StringBuilder();
while (in.read(buf) != -1) {
sb.append(new String(buf, charset));
}
return sb.toString();
}
public static void main(String[] args) {
try {
ShellResult status = exec("10.0.0.1", "root", "root", "ipconfig", StandardCharsets.UTF_8);
System.out.println(">>>>>>Result>>>>>>>");
System.out.println(status.getResult());
System.out.println(">>>>>>ErrorMsg>>>>>>>>");
System.out.println(status.getErrorMsg());
} catch (IOException e) {
e.printStackTrace();
}
}
}
通过这两个类再配合任务调度就可以基本的实现对应用的监控了.
JAVA执行远端服务器的脚本的更多相关文章
- java执行hive命令或者脚本
java执行脚本 import java.io.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import ja ...
- Jenkins执行远程服务器的脚本-Hudson SCP publisher plugin插件
1.搜索插件 2.配置远程服务器账号密码 3.配置远程服务器 4.构建配置
- java远程执行linux服务器上的shell脚本
业务场景:需要从服务器A中新增的文件同步至本地服务器,服务器A中内存有限,需同步成功之后清除文件. Java调用远程shell脚本,需要和远程服务器建立ssh链接,再调用指定的shell脚本. 1.创 ...
- Java代码调用服务器上的Shell脚本
Java代码调用服务器上的Shell脚本 这里主要是因为我们报表平台有用到用户手工录入的数据作为结果数据且需要纳入saiku去展示 如我们所知,saiku不会自动刷新,所以需要在数据更新接口中调用服务 ...
- Java执行Dos-Shell脚本
Java执行Dos-Shell脚本 1.介绍 2.调用shell脚本 2.1 获取键盘输入 2.2 构建指令 2.3 Java代码 3.Java调用Shell并传入参数 4.Java调用远程的Shel ...
- java ssh远程服务器并执行多条shell命令
java ssh远程服务器并执行多条命令 import java.io.BufferedReader; import java.io.IOException; import java.io.Input ...
- Java 执行 SQL 脚本文件
转自:http://blog.csdn.net/hongmin118/article/details/4588941 package com.unmi.db; import java.io.FileI ...
- Java执行JavaScript脚本破解encodeInp()加密
一:背景 在模拟登录某网站时遇到了用户名和密码被JS进行加密提交的问题,如图: 二:解决方法 1.我们首先需要获得该JS加密函数,一般如下: conwork.js var keyStr = " ...
- java执行shell脚本并输出执行情况
1.脚本test.sh,置于/Users/hdwang目录下 #!/bin/sh cd /Users/hdwang echo ls:`ls` ;i<=;i++)); do + ); sleep ...
随机推荐
- Serv-U 配置说明(虚拟路径、网络驱动器、个人文件夹,数据库管理)
实现效果 1.用户数据存在数据库,可以自己修改. 2.支持匿名用户使用部分功能 3.每个用户均有私人文件夹,可以自己存放文件 4.FTP内主要的文件都在存储内,不存在服务器上 匿名用户访问情况: 普通 ...
- File和FileStream的区别
File和FileStream的区别直观点:File是一个静态类:FileStream是一个非静态类.File:是一个文件的类,对文件进行操作.其内部封装了对文件的各种操作(MSDN:提供用于创建.复 ...
- leetcode268缺失数字
int missingNumber(int* nums, int numsSize) { ) /; ;i<numsSize;i++){ sum = sum - nums[i]; } return ...
- vue实例
<!--需求: 背景图片,进度条,减和重置按钮 进度条填满红色,值为100%,点击减时,进度条依次减十,减到0时换一张背景图片,减按钮消失,点击重置按钮时,进度条重新填满红色-->效果图: ...
- 云笔记项目-Spring事务学习-传播MANDATORY
接下来测试事务传播属性MANDATORY Service层 所有Service层实现类都设置事务传播属性为MANDATORY. LayerT层代码 package LayerT; import jav ...
- SocketIO Server
package com.fd.socketio; import org.json.JSONObject; import com.corundumstudio.socketio.AckRequest; ...
- Ambari2.6.2 HDP2.6.5 大数据集群搭建
Ambari 2.6.2 中 HDFS-2.7.3 YARN-2.7.3 HIVE-1.2.1 HBASE-1.1.2 ZOOKEEPER-3.4.6 SPARK-2.3.0 注:本文基于root用户 ...
- CentOS 6安装配置mongodb
安装过程 服务器下载安装包 下载: curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel62-4.0.6.tgz; 解压 ...
- Hadoop环境搭建--Docker完全分布式部署Hadoop环境(菜鸟采坑吐血整理)
系统:Centos 7,内核版本3.10 本文介绍如何从0利用Docker搭建Hadoop环境,制作的镜像文件已经分享,也可以直接使用制作好的镜像文件. 一.宿主机准备工作 0.宿主机(Centos7 ...
- python jieba 库分词结合Wordcloud词云统计
import jieba jieba.add_word("福军") jieba.add_word("少安") excludes={"一个", ...