方式一:
使用 h.ethz.ssh2.Session 的 execCommand 方法执行cmd指令
1.首先需要增加依赖
<dependency>
<groupId>ch.ethz.ganymedgroupId>
<artifactId>ganymed-ssh2artifactId>
<version>build210version>
dependency>
Java代码示例如下
public static void main(String[] args) {
makeFolder("127.0.0.520","userlocal","123",22,"/usr/local/at2.0/perfreport/","testwc");
}
public static void makeFolder(String ip, String username, String password, Integer port,
String resultPath,String folderFront) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//登录执行机
Connection conn = null;
ch.ethz.ssh2.Session session = null;
try {
conn = new Connection(ip,port);
conn.connect();
boolean flag = conn.authenticateWithPassword(username, password);// 认证֤
if (!flag) {
throw new BusinessException(ResponseMsg.FAILURE + "压测机IP、用户名或密码不正确!");
}
//从压测机拷贝执行报告到远程报告发布服务器
session = conn.openSession();
StringBuffer cmdStr = new StringBuffer();
//去目标文件夹
cmdStr.append("cd");
cmdStr.append(" ");
cmdStr.append(resultPath);
cmdStr.append(";");
//压缩
cmdStr.append("mkdir");
cmdStr.append(" ");
cmdStr.append(folderFront);
cmdStr.append(";");
session.execCommand(cmdStr.toString());
} catch (IOException e) {
throw new BusinessException(ResponseMsg.FAILURE + "执行新建文件夹失败:", e.getCause());
} finally {
if(conn != null){
conn.close();
}
if(session != null){
session.close();
}
}
}
方式二:
我们有时候不仅仅是需要执行cmd指令,我们还需要像黑窗口时一样获取指令的返回值
这时我们可以使用类似SFTPv3Client 等方式来获取返回值 。 这个同样是 ch.ethz.ssh2包下的,和上面的pom依赖是一样的。
public static void main(String[] args) {
System.out.println(ifExitFile("127.0.0.520", "userlocal", "123", 22, "/usr/local/at2.0/perfreport/"));
}
public static Boolean ifExitFile(String resultMachineIp, String resultMachineUsername, String resultMachinePassword,
Integer resultMachinePort, String resultMachinePath){
//登录报告服务器
Connection conn = null;
ch.ethz.ssh2.Session session = null;
int i =0;
try {
conn = new Connection(resultMachineIp, resultMachinePort);
conn.connect();
boolean flag = conn.authenticateWithPassword(resultMachineUsername, resultMachinePassword);// 认证֤
if (!flag) {
throw new BusinessException(ResponseMsg.FAILURE + "无法连接报告服务器");
}
//给文件夹目录赋权限
session = conn.openSession();
//判断是否有这个文件夹 如果有就删除
SFTPv3Client sftpv3Client = new SFTPv3Client(conn);
while (true){
i++;
boolean hasDir = false;
try {
ch.ethz.ssh2.SFTPv3FileAttributes sftpAttrs = sftpv3Client.lstat(resultMachinePath);
hasDir = sftpAttrs.isDirectory();
}catch(IOException e){
}
if (hasDir){
return true;
}else {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (i>10){
return false;
}
}
}
} catch (IOException e) {
throw new BusinessException(ResponseMsg.FAILURE + "查看文件是否存在失败:", e.getCause());
} finally {
if(conn != null){
conn.close();
}
if(session != null){
session.close();
}
}
}
注意:
这个cmd指令是串行的,但仅仅只是cmd指令是串行执行的,他不会想我们的linux黑框框一样,等你收到返回值才执行下一步。
比如说我使用scp去复制文件到目标服务器,scp可能需要两秒,对目标服务器的文件进行解压 ,而此时很有可能文件还没有传完,解压指令就开始执行了,导致东西解压不成功。
所以就需要像 方法二 中的 ifExitFile方法,用来循环判断是否执行成功再走下一步。
再附赠几个我写的方法
//获取服务器文件的内容
public String getFile(String ip, String username, String password, String path) {
//延时,等待文件传输完再获取
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 文件scp到数据服务器
Connection conn = null;
if (StringUtils.isNotBlank(path)){
path += "/"+STATISTICS_FILE;
}
try {
conn = new Connection(ip);
conn.connect();
boolean flag = conn.authenticateWithPassword(username, password);// 认证֤
if (!flag) {
throw new BusinessException(ResponseMsg.FAILURE + "压测机IP、用户名或密码不正确!");
}
SCPClient client = new SCPClient(conn);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 本地文件scp到远程目录
// client.put(sourcePath, targetName, targetFolder, mode);
client.get(path, baos);
String errorFile = new String(baos.toByteArray(), "utf-8");
return errorFile;
} catch (IOException e) {
throw new BusinessException(ResponseMsg.FAILURE + e.getCause().getMessage());
}
} catch (IOException e) {
throw new BusinessException(ResponseMsg.FAILURE + "执行scp指令时出现异常:", e.getCause());
} finally {
conn.close();
}
}
/**
* @param ip Linux服务器IP
* @param username Linux服务器用户名
* @param password Linux服务器密码
* @param sourcePath 源文件全路径
* @param targetName 目标文件名
* @param targetFolder 目标文件夹全路径
* @param mode 存取模式(chmod)
* @throws IOException
* @Description: 使用scp把脚本文件传送到远端服务器
*/
public void transScriptToRemote(String ip, String username, String password, String sourcePath, String targetName,
String targetFolder, String mode) {
if (mode == null) {
mode = "0600";
}
// 文件scp到数据服务器
Connection conn = null;
try {
conn = new Connection(ip);
conn.connect();
boolean flag = conn.authenticateWithPassword(username, password);// 认证֤
if (!flag) {
throw new BusinessException(ResponseMsg.FAILURE + "压测机IP、用户名或密码不正确!");
}
SCPClient client = new SCPClient(conn);
try {
// 本地文件scp到远程目录
client.put(sourcePath, targetName, targetFolder, mode);
} catch (IOException e) {
String message = e.getCause().getMessage();
if (message.contains("No such file or directory")) {
Session session = conn.openSession();
session.execCommand("mkdir " + targetFolder);
// 本地文件scp到远程目录
client.put(new String(sourcePath.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1),
new String(targetName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1), targetFolder, mode);
} else {
throw new BusinessException(ResponseMsg.FAILURE + e.getCause().getMessage());
}
}
} catch (IOException e) {
throw new BusinessException(ResponseMsg.FAILURE + "执行scp指令时出现异常:", e.getCause());
} finally {
conn.close();
}
}