Java连续执行多条CMD命令及SSH登录技巧详解 - 脚本之家

java如何连续执行多条cmd命令

Java连续执行多条CMD命令及SSH登录技巧详解 - 脚本之家

2021 年 08 月 11 日 08 时 48 分 16 秒进行了更新,作者是薛 8。

这篇文章主要是介绍了关于 java 怎样去连续执行多条 cmd 命令的方式,它具有相当不错的参考价值,期望能对大家起到帮助作用。倘若存在错误或者没有考虑周全的地方,希望大家不要吝啬给予指教。

java连续执行多条cmd命令命令之间用&连接

例如:

执行该命令后创建了一个进程 p。

java ssh登录执行多条cmd命令

使用 Java 登录 ssh 后可以执行多条命令,并且能够解决在执行过程中出现 more 自动回车的问题。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
导入 java.io.UnsupportedEncodingException 类。
引入 org.apache.logging.log4j 包中的 LogManager 类。
导入 org.apache.logging.log4j.Logger;
引入 com.jcraft.jsch.Channel 这个类。
import com.jcraft.jsch.JSch;
导入 com.jcraft.jsch 库中的 JSchException 类。
引入 com.jcraft.jsch.Session 类。
引入 com.jcraft.jsch.UIKeyboardInteractive 类。
导入 com.jcraft.jsch 包中的 UserInfo 类。
 
类 JavaSsh 实现了 Runnable 接口。
获取到一个 Logger 实例,这个实例是通过 LogManager 获取到的。
	/**
	 * 退格
	 */
- 静态 final 的字符串 BACKSPACE 是由字节数组 [ 8 ] 构建出来的新字符串。
 
	/**
	 * ESC
	 */
3. 静态的最终字符串 ESC 被定义为一个新的字符串,这个字符串是由字节数组 { 27 } 所创建出来的。
 
	/**
	 * 空格
	 */
3. 静态的最终的字符串 BLANKSPACE 是通过一个字节数组[ 32 ]创建出来的新字符串。
 
	/**
	 * 回车
	 */
静态私有常量字符串 ENTER 由一个新的字节数组 { 13 } 创建而成。
 
	/**
	 * 某些设备回显数据中的控制字符
	 */
静态私有字符串数组 PREFIX_STRS 包含以下内容:退格键(BACKSPACE)加空格(BLANKSPACE)再加退格键(BACKSPACE),然后再加一个加号(+)。
(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 多次出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 持续出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 反复出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 不断出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 屡次出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 时常出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 经常出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 惯常出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 总是出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 一直出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 每每出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 往往出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 通常出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 多半出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 大致出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 差不多出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 近乎出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 接近出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 差不离出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 约略出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 略微出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 稍许出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 些许出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有点儿出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几分出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有一些出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有一点出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有若干出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有部分出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几分几毫出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几成出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几毫出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几丝出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几缕出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几星出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几点出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几点几毫出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)" 有几点几丝出现;(" + ESC + "\\[\\d+[A-Z]" + BLANKSPACE + "*)
 
	private int sleepTime = 200;
 
	/**
	 * 连接超时(单次命令总耗时)
	 */
	private int timeout = 4000;
 
	/**
	 * 保存当前命令的回显信息
	 */
被保护的字符串缓冲区 currEcho 。
 
	/**
	 * 保存所有的回显信息
	 */
声明了一个名为 totalEcho 的字符串缓冲区。
	private String ip;
	private int port;
这个字符串被定义为“endEcho”,它的值是“#,?,>,:”。
- 有这样一个字符串 moreEcho,它的内容是"---- More ----"。
这个私有字符串 moreCmd 的值为 BLANKSPACE 。
	private JSch jsch = null;
	private Session session;
	private Channel channel;
 
	@Override
	public void run() {
		InputStream is;
		try {
channel 获取到的输入流为 is 。
使用 readOneEcho 函数读取一个 echo 信息,该信息存储在 is 中,将其赋值给变量 echo 。
			while (echo != null) {
				currEcho.append(echo);
使用“\\n”作为分隔符对“echo”进行分割,分割后的结果存储在“String[] lineStr”中。
如果 lineStr 不为空且其长度大于 0 ,那么
获取到的字符串 lineStr ,其最后一个字符组成的字符串为 lastLineStr ,即 lastLineStr 等于 lineStr 的长度减 1 位置处的字符所组成的字符串。
如果 lastLineStr 不为空且 lastLineStr 中包含 moreEcho ,那么就会执行以下操作:
totalEcho 把 echo 中 lastLineStr 替换掉后添加进来。
					} else {
						totalEcho.append(echo);
					}
				}
				echo = readOneEcho(is);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
通过输入流 instr 来读取一个回显内容,读取的结果以字符串形式返回,该字符串为 protected 类型。
		byte[] buff = new byte[1024];
		int ret_read = 0;
		try {
			ret_read = instr.read(buff);
		} catch (IOException e) {
			return null;
		}
		if (ret_read > 0) {
创建一个新的字符串 result,其内容是从 buff 数组中从索引 0 开始,长度为 ret_read 的部分。
对于每一个字符串 PREFIX_STR ,它都在 PREFIX_STRS 之中 。
result 会将其开头的 PREFIX_STR 替换为空字符串。 即去掉 result 开头的 PREFIX_STR 部分。 让 result 不再包含 PREFIX_STR 。 从而达到去除 result 开头特定字符串的效果。
			}
			try {
使用“GBK”编码将 result 转换为字符串并返回。
遇到 UnsupportedEncodingException 异常时会执行以下操作:首先捕获该异常,然后进行相应的处理。
				e.printStackTrace();
				return null;
			}
		} else {
			return null;
		}
	}
 
创建一个名为 JavaSsh 的类,该类接收四个参数,分别是字符串类型的 ip、整数类型的 port、字符串类型的 endEcho 和字符串类型的 moreEcho 。
		this.ip = ip;
		this.port = port;
		if (endEcho != null) {
			this.endEcho = endEcho;
		}
		if (moreEcho != null) {
			this.moreEcho = moreEcho;
		}
创建了一个名为 totalEcho 的 StringBuffer 对象。
创建了一个新的字符串缓冲区对象 currEcho 。
	}
 
	private void close() {
		if (session != null) {
			session.disconnect();
		}
		if (channel != null) {
			channel.disconnect();
		}
	}
 
这个方法是否能进行登录操作取决于传入的字符串数组 cmds 。
		String user = cmds[0];
		String passWord = cmds[1];
		jsch = new JSch();
		try {
session 是通过 jsch 获取的会话,获取该会话的用户是 user,获取该会话的 IP 地址是 this.ip,获取该会话的端口号是 this.port。
session 将密码设置为 passWord 。
创建一个名为 ui 的 UserInfo 对象,它是一个 SSHUserInfo 的实例,通过以下方式初始化:
该方法用于展示消息,其参数为一个字符串类型的消息。
				}
 
判断是否提示用户输入是或否,传入一个消息字符串作为参数。如果用户输入的是“是”或“否”,则根据输入返回相应的布尔值;如果用户输入的不是“是”或“否”,则提示用户重新输入,直到输入“是”或“否”为止。
					return true;
				}
			};
			session.setUserInfo(ui);
			session.connect(30000);
session 打开了一个名为“shell”的通道,该通道被赋值给了变量 channel。
			channel.connect(3000);
			new Thread(this).start();
			try {
				Thread.sleep(sleepTime);
			} catch (Exception e) {
			}
			return true;
		} catch (JSchException e) {
			return false;
		}
	}
 
在保护模式下,要发送一个命令,这个命令是一个字符串形式的 command,并且还需要决定是否发送回车键,这个回车键的发送与否由 boolean 类型的 sendEnter 来决定,具体的发送操作就是通过这个方法来完成的。
		try {
通道的输出流被获取到并赋值给输出流 os 。
			os.write(command.getBytes());
			os.flush();
			if (sendEnter) {
创建了一个名为 currEcho 的 StringBuffer 对象。
				os.write(ENTER.getBytes());
				os.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
否则返回 false 。
		boolean contains = false;
如果 endEcho 为 null 或者 endEcho 经过去除两端空白字符后等于空字符串,那么
			return contains;
		}
将 endEcho 按照逗号进行分割,得到的字符串数组为 eds 。
		for (String ed : eds) {
如果 echo 经过去除两端空白字符后以 ed 结尾,那么
				contains = true;
				break;
			}
		}
		return contains;
	}
 
定义一个方法 runCommand,它接收一个字符串 command 和一个布尔值 ifEnter 作为参数。这个方法的作用是执行指定的命令 command,并根据 ifEnter 的值决定是否在执行命令后进入命令行交互界面。如果 ifEnter 为 true,则在执行命令后进入命令行交互界面;如果 ifEnter 为 false,则不进入命令行交互界面。最后,方法返回执行命令的结果。
		currEcho = new StringBuffer();
发送命令(command),如果需要输入(ifEnter)则进行输入操作。
		int time = 0;
如果 endEcho 为 null 或者 endEcho 等于空字符串。
当 currEcho 转换为字符串后,其值为空字符串时,就会执行以下操作:
				try {
					Thread.sleep(sleepTime);
					time += sleepTime;
					if (time >= timeout) {
						break;
					}
遇到 InterruptedException 异常 e 时,会执行以下操作。
					e.printStackTrace();
				}
			}
		} else {
当不包含当前回显的字符串表示的回显结束标志时,继续循环。
				try {
					Thread.sleep(sleepTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				time += sleepTime;
				if (time >= timeout) {
					break;
				}
将 currEcho 转换为字符串后,使用 "\\n" 作为分隔符将其拆分成字符串数组 lineStrs 。
如果 lineStrs 不为空且 lineStrs 的长度大于 0 。
如果 moreEcho 不为空并且 lineStrs 数组中的最后一个元素也不为空
如果 lineStrs 数组的最后一个元素包含 moreEcho ,则执行以下操作 ;如果 lineStrs 数组的最后一个元素包含 moreEcho ,就进行后续处理 ;若 lineStrs 数组的最后一个元素包含 moreEcho ,便执行相应的逻辑 ;当 lineStrs 数组的最后一个元素包含 moreEcho 时,会执行相关的步骤 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展相应的动作 ;倘若 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行对应的操作 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行那部分处理 ;要是 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行相关的事宜 ;若 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行对应的流程 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展那部分动作 ;当 lineStrs 数组的最后一个元素包含 moreEcho 时,会进行相应的处理 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之相关的操作 ;倘若 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展对应的行动 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行那部分相关的处理 ;要是 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之对应的操作 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展相应的事宜 ;若 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之相关的流程 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行那部分对应的处理 ;当 lineStrs 数组的最后一个元素包含 moreEcho 时,就会执行与之相关的动作 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展与之对应的行动 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的事宜 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之相关的流程 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的处理 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展与之相关的行动 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的事宜 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之相关的流程 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的处理 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展与之相关的行动 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的事宜 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之相关的流程 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的处理 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展与之相关的行动 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的事宜 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之相关的流程 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的处理 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展与之相关的行动 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的事宜 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会执行与之相关的流程 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关的处理 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会开展与之相关的行动 ;只要 lineStrs 数组的最后一个元素包含 moreEcho ,就会进行与之相关
						sendCommand(moreCmd, false);
						currEcho.append("\n");
						time = 0;
						continue;
					}
				}
			}
		}
		return currEcho.toString();
	}
 
这个方法用于生成批处理命令。它接收两个参数,一个是字符串数组`cmds`,另一个是整数数组`othernEenterCmds`。通过这两个参数来生成相应的批处理命令。
创建了一个 StringBuffer 对象,名为 sb 。
		for (int i = 2; i < cmds.length; i++) {
			String cmd = cmds[i];
			if (cmd.equals("")) {
				continue;
			}
			boolean ifInputEnter = false;
			if (othernEenterCmds != null) {
				for (int c : othernEenterCmds) {
					if (c == i) {
						ifInputEnter = true;
						break;
					}
				}
			}
			cmd += (char) 10;
			String resultEcho = runCommand(cmd, ifInputEnter);
			sb.append(resultEcho);
		}
		close();
		return totalEcho.toString();
	}
 
	public String executive(String[] cmds, int[] othernEenterCmds) {
		if (cmds == null || cmds.length < 3) {
			logger.error("{} ssh cmds is null", this.ip);
			return null;
		}
		if (login(cmds)) {
			return batchCommand(cmds, othernEenterCmds);
		}
		logger.error("{} ssh login error", this.ip);
		return null;
	}
 
	private abstract class SSHUserInfo implements UserInfo, UIKeyboardInteractive {
		public String getPassword() {
			return null;
		}
 
		public boolean promptYesNo(String str) {
			return true;
		}
 
		public String getPassphrase() {
			return null;
		}
 
		public boolean promptPassphrase(String message) {
			return true;
		}
 
		public boolean promptPassword(String message) {
			return true;
		}
 
		public void showMessage(String message) {
		}
 
		public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt,
				boolean[] echo) {
			return null;
		}
	}
 
	public static void main(String[] args) {
		String ip = "192.168.0.238";
		int port = 22;
		JavaSsh JavaSsh2 = new JavaSsh(ip, port, null, null);
		String username = "ssh";
		String password = "yzfar.com";
		String[] cmds = { username, password, "display mac-address", "display mac-address" };
		String executive = JavaSsh2.executive(cmds, null);
		System.out.println(executive);
	}
}

个人有此经验,期望能给大家作参考,也期望大家大力支持脚本之家。

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

25阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读