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);
}
}
个人有此经验,期望能给大家作参考,也期望大家大力支持脚本之家。