java连接linux服务器执行shell命令(框架分析+推荐)
一、分类+连接方式
程序打成jar包,在本地服务器上执行shell命令。这种使用MyRuntimeUtil工具类java程序远程linux服务器有两个框架分别是:jsch与ganymed-ssh2框架。推荐使用jsch框架因为ganymed-ssh2框架不支持麒麟服务器的连接原因是openssl版本过高,ganymed-ssh框架不维护了所以不支持。
二、执行本地的shell命令
cn.hutool
hutool-all
5.7.21
工具类
package com.dameng.util;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.StaticLog;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* @author xgt(小光头)
* @version 1.0
* @date 2022-3-3 22:40
*/
public class MyRuntimeUtil {
/**
* 执行系统命令,使用系统默认编码
*
* @param cmds 命令列表,每个元素代表一条命令
* @return 执行结果
* @throws IORuntimeException IO异常
*/
public static String execForStr(String... cmds) throws IORuntimeException {
return execForStr(CharsetUtil.systemCharset(), cmds);
}
/**
* 执行系统命令,使用系统默认编码
*
* @param charset 编码
* @param cmds 命令列表,每个元素代表一条命令
* @return 执行结果
* @throws IORuntimeException IO异常
* @since 3.1.2
*/
public static String execForStr(Charset charset, String... cmds) throws IORuntimeException {
return getResult(exec(cmds), charset);
}
public static String execForErrStr(Charset charset,String cmd) throws IORuntimeException {
return getResultErr(exec(cmd), charset);
}
/**
* 执行系统命令,使用系统默认编码
*
*/
public static String execForStr(Charset charset, String cmds) throws IORuntimeException {
return getResult(exec(cmds), charset);
}
/**
* 执行系统命令,使用系统默认编码
*
* @param cmds 命令列表,每个元素代表一条命令
* @return 执行结果,按行区分
* @throws IORuntimeException IO异常
*/
public static List execForLines(String... cmds) throws IORuntimeException {
return execForLines(CharsetUtil.systemCharset(), cmds);
}
/**
* 执行系统命令,使用系统默认编码
*
* @param charset 编码
* @param cmds 命令列表,每个元素代表一条命令
* @return 执行结果,按行区分
* @throws IORuntimeException IO异常
* @since 3.1.2
*/
public static List execForLines(Charset charset, String... cmds) throws IORuntimeException {
return getResultLines(exec(cmds), charset);
}
/**
* 执行命令
* 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
*
* @param cmds 命令
* @return {@link Process}
*/
public static Process exec(String... cmds) {
Process process;
try {
process = new ProcessBuilder(handleCmds(cmds)).redirectErrorStream(true).start();
} catch (IOException e) {
throw new IORuntimeException(e);
}
return process;
}
/**
* 执行命令
* 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
*
* @param cmd 命令
* @return {@link Process}
*/
public static Process exec(String cmd) {
Process process;
try {
// 得到Java进程的相关Runtime运行对象
Runtime runtime = Runtime.getRuntime();
if(cmd.indexOf("|")>0){
String[] cmdArr = {"sh","-c",cmd};
process = runtime.exec(cmdArr);
}else{
process = runtime.exec(cmd);
}
} catch (IOException e) {
throw new IORuntimeException(e);
}
return process;
}
/**
* 执行命令
* 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
*
* @param envp 环境变量参数,传入形式为key=value,null表示继承系统环境变量
* @param cmds 命令
* @return {@link Process}
* @since 4.1.6
*/
public static Process exec(String[] envp, String... cmds) {
return exec(envp, null, cmds);
}
/**
* 执行命令
* 命令带参数时参数可作为其中一个参数,也可以将命令和参数组合为一个字符串传入
*
* @param envp 环境变量参数,传入形式为key=value,null表示继承系统环境变量
* @param dir 执行命令所在目录(用于相对路径命令执行),null表示使用当前进程执行的目录
* @param cmds 命令
* @return {@link Process}
* @since 4.1.6
*/
public static Process exec(String[] envp, File dir, String... cmds) {
try {
return Runtime.getRuntime().exec(handleCmds(cmds), envp, dir);
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
// -------------------------------------------------------------------------------------------------- result
/**
* 获取命令执行结果,使用系统默认编码,获取后销毁进程
*
* @param process {@link Process} 进程
* @return 命令执行结果列表
*/
public static List getResultLines(Process process) {
return getResultLines(process, CharsetUtil.systemCharset());
}
/**
* 获取命令执行结果,使用系统默认编码,获取后销毁进程
*
* @param process {@link Process} 进程
* @param charset 编码
* @return 命令执行结果列表
* @since 3.1.2
*/
public static List getResultLines(Process process, Charset charset) {
InputStream in = null;
try {
in = process.getInputStream();
return IoUtil.readLines(in, charset, new ArrayList());
} finally {
IoUtil.close(in);
destroy(process);
}
}
/**
* 获取命令执行结果,使用系统默认编码,,获取后销毁进程
*
* @param process {@link Process} 进程
* @return 命令执行结果列表
* @since 3.1.2
*/
public static String getResult(Process process) {
return getResult(process, CharsetUtil.systemCharset());
}
/**
* 获取命令执行结果,获取后销毁进程
*
* @param process {@link Process} 进程
* @param charset 编码
* @return 命令执行结果列表
* @since 3.1.2
*/
public static String getResult(Process process, Charset charset) {
InputStream in = null;
InputStream errorStream = null;
try {
in = process.getInputStream();
errorStream = process.getErrorStream();
String errorResult = IoUtil.read(errorStream, charset);
if(StrUtil.isNotBlank(errorResult)){
StaticLog.warn("Shell command execution error, because {}",errorResult);
}
return IoUtil.read(in, charset);
} finally {
IoUtil.close(in);
IoUtil.close(errorStream);
destroy(process);
}
}
/**
* 获取错误的执行结果,获取后销毁进程
*
* @param process {@link Process} 进程
* @param charset 编码
* @return 命令执行结果列表
* @since 3.1.2
*/
public static String getResultErr(Process process, Charset charset) {
InputStream in = null;
InputStream errorStream = null;
try {
in = process.getInputStream();
errorStream = process.getErrorStream();
// System.out.println("252"+IoUtil.read(errorStream, charset));
return IoUtil.read(errorStream, charset);
} finally {
IoUtil.close(in);
IoUtil.close(errorStream);
destroy(process);
}
}
/**
* 获取命令执行异常结果,使用系统默认编码,,获取后销毁进程
*
* @param process {@link Process} 进程
* @return 命令执行结果列表
* @since 4.1.21
*/
public static String getErrorResult(Process process) {
return getErrorResult(process, CharsetUtil.systemCharset());
}
/**
* 获取命令执行异常结果,获取后销毁进程
*
* @param process {@link Process} 进程
* @param charset 编码
* @return 命令执行结果列表
* @since 4.1.21
*/
public static String getErrorResult(Process process, Charset charset) {
InputStream in = null;
try {
in = process.getErrorStream();
return IoUtil.read(in, charset);
} finally {
IoUtil.close(in);
destroy(process);
}
}
/**
* 销毁进程
*
* @param process 进程
* @since 3.1.2
*/
public static void destroy(Process process) {
if (null != process) {
process.destroy();
}
}
/**
* 增加一个JVM关闭后的钩子,用于在JVM关闭时执行某些操作
*
* @param hook 钩子
* @since 4.0.5
*/
public static void addShutdownHook(Runnable hook) {
Runtime.getRuntime().addShutdownHook((hook instanceof Thread) ? (Thread) hook : new Thread(hook));
}
/**
* 获得JVM可用的处理器数量(一般为CPU核心数)
*
* @return 可用的处理器数量
* @since 5.3.0
*/
public static int getProcessorCount() {
return Runtime.getRuntime().availableProcessors();
}
/**
* 获得JVM中剩余的内存数,单位byte
*
* @return JVM中剩余的内存数,单位byte
* @since 5.3.0
*/
public static long getFreeMemory() {
return Runtime.getRuntime().freeMemory();
}
/**
* 获得JVM已经从系统中获取到的总共的内存数,单位byte
*
* @return JVM中剩余的内存数,单位byte
* @since 5.3.0
*/
public static long getTotalMemory() {
return Runtime.getRuntime().totalMemory();
}
/**
* 获得JVM中可以从系统中获取的最大的内存数,单位byte,以-Xmx参数为准
*
* @return JVM中剩余的内存数,单位byte
* @since 5.3.0
*/
public static long getMaxMemory() {
return Runtime.getRuntime().maxMemory();
}
/**
* 获得JVM最大可用内存,计算方法为:
* 最大内存-总内存+剩余内存
*
* @return 最大可用内存
*/
public static long getUsableMemory() {
return getMaxMemory() - getTotalMemory() + getFreeMemory();
}
/**
* 获取当前进程ID,首先获取进程名称,读取@前的ID值,如果不存在,则读取进程名的hash值
*
* @return 进程ID
* @throws UtilException 进程名称为空
* @since 5.7.3
*/
public static int getPid() throws UtilException {
final String processName = ManagementFactory.getRuntimeMXBean().getName();
if (StrUtil.isBlank(processName)) {
throw new UtilException("Process name is blank!");
}
final int atIndex = processName.indexOf('@');
if (atIndex > 0) {
return Integer.parseInt(processName.substring(0, atIndex));
} else {
return processName.hashCode();
}
}
/**
* 处理命令,多行命令原样返回,单行命令拆分处理
*
* @param cmds 命令
* @return 处理后的命令
*/
private static String[] handleCmds(String... cmds) {
if (ArrayUtil.isEmpty(cmds)) {
throw new NullPointerException("Command is empty !");
}
// 单条命令的情况
if (1 == cmds.length) {
final String cmd = cmds[0];
if (StrUtil.isBlank(cmd)) {
throw new NullPointerException("Command is blank !");
}
cmds = cmdSplit(cmd);
}
return cmds;
}
/**
* 命令分割,使用空格分割,考虑双引号和单引号的情况
*
* @param cmd 命令,如 git commit -m 'test commit'
* @return 分割后的命令
*/
private static String[] cmdSplit(String cmd) {
final List cmds = new ArrayList();
final int length = cmd.length();
final Stack stack = new Stack();
boolean inWrap = false;
final StrBuilder cache = StrUtil.strBuilder();
char c;
for (int i = 0; i |