备注:根据自己的业务可以去修改一下。下面只是实现了我的业务:将服务器上的文件复制到另一个文件下,并且在指定的内容处添加内容。
1.pom文件
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.ethz.ganymed/ganymed-ssh2 -->
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>build210</version>
</dependency>
2.
package com.ed.core.util;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SFTPv3Client;
import ch.ethz.ssh2.SFTPv3DirectoryEntry;
import ch.ethz.ssh2.StreamGobbler;
import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* @ProjectName: gitIdeaWork
* @Package: com.ed.core.util
* @ClassName: DestHostShell
* @Author: zhao
* @Description:
* @Date: 2019/12/23 18:18
* @Version: 1.0
*/
public class DestHostShell {
Logger logger = LoggerFactory.getLogger(DestHostShell.class);
private static String userName = "***";
private static String password = "***";
private static String host = "***.***.*.**";
private static Integer port = 22;
/**
* 文件复制
* cpCommand : cp /home/upload/hello.txt /home/include/
* @param cpCommand
* @return
* @throws IOException
* @throws JSchException
*/
public static void execCommandByShell(String cpCommand)throws IOException,JSchException{
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession(userName, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");//第一次访问服务器不用输入yes
session.setTimeout(60*60*1000);
session.connect();
//2.尝试解决 远程ssh只能执行一句命令的情况
ChannelShell channelShell = (ChannelShell) session.openChannel("shell");
InputStream inputStream = channelShell.getInputStream();//从远端到达的数据 都能从这个流读取到
channelShell.setPty(true);
channelShell.connect();
OutputStream outputStream = channelShell.getOutputStream();//写入该流的数据 都将发送到远程端
//使用PrintWriter 就是为了使用println 这个方法
//好处就是不需要每次手动给字符加\n
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println(cpCommand);
printWriter.println("exit");//为了结束本次交互
printWriter.flush();//把缓冲区的数据强行输出
/**
shell管道本身就是交互模式的。要想停止,有两种方式:
一、人为的发送一个exit命令,告诉程序本次交互结束
二、使用字节流中的available方法,来获取数据的总大小,然后循环去读。
为了避免阻塞
*/
byte[] tmp = new byte[1024];
while(true){
while(inputStream.available() > 0){
int i = inputStream.read(tmp, 0, 1024);
if(i < 0) break;
String s = new String(tmp, 0, i);
if(s.indexOf("--More--") >= 0){
outputStream.write((" ").getBytes());
outputStream.flush();
}
System.out.println(s);
}
if(channelShell.isClosed()){
System.out.println("退出状态"+channelShell.getExitStatus());
break;
}
try{Thread.sleep(1000);}catch(Exception e){}
}
outputStream.close();
inputStream.close();
channelShell.disconnect();
session.disconnect();
System.out.println("复制完成");
} catch (JSchException e) {
e.printStackTrace();
}
}
/**
* 文件内容读取拼接
* @param directory:/home/testc/include/
* @param findContent : 指定内容
* @param replaceContent 替换内容
* @return
*/
public static String fileReadStr(String directory,String findContent,List<String> replaceContent,String fileName,String path){
//声明连接对象
Connection conn = null;
ch.ethz.ssh2.Session ss=null;
//参数
List<String> fileNameList=new ArrayList<String>(); //存放文件名
try {
//连接远程服务器
// 连接部署服务器
conn = new Connection(host);
conn.connect();
//使用用户名和密码登录
boolean b = conn.authenticateWithPassword(userName, password);
if (!b) {
throw new IOException("身份验证失败!");
} else {
SFTPv3Client sft = new SFTPv3Client(conn);
Vector<?> v = sft.ls(directory);//日志文件存放的目录
//遍历该目录下的所有文件
for (int i = 0; i < v.size(); i++) {
SFTPv3DirectoryEntry s = new SFTPv3DirectoryEntry();
s = (SFTPv3DirectoryEntry) v.get(i);
//文件名
String filename = s.filename;
if (filename.length() > 0 && filename.equals(fileName)) {
//获取符合要求的文件名
System.out.println("符合条件的文件名 - >"+filename);
fileNameList.add(filename);
}
}
List<String> contentList = new ArrayList<>();
//读取文件内容,并复制给UserInfo对象
for (int j = 0; j<fileNameList.size() ; j++) {
ss=conn.openSession(); //打开会话
ss.execCommand("cat ".concat(directory+fileNameList.get(j))); //读取对应目录下的对应文件
InputStream is = new StreamGobbler(ss.getStdout());
InputStreamReader gbk = new InputStreamReader(is, "UTF-8");
BufferedReader bs = new BufferedReader(gbk); //防止中文乱码
int lineCount = 0;
while(true){
String line=bs.readLine();
if(line==null){
break;
}else{
contentList.add(line);
lineCount++;
System.out.println( "第" + lineCount + "行,内容为:" + line);
//不等于#号,原因是防止这行注释掉
if(line.indexOf(findContent) != -1 && line.indexOf("#") == -1){
for(int i = 0; i < replaceContent.size(); i++){
contentList.add(replaceContent.get(i));
}
}
}
}
bs.close();
}
ss.close();
conn.close();
upLoadToIgenetech(contentList,fileName,path);
}
} catch (IOException e) {
System.err.printf("用户%s密码%s登录服务器%s失败!", userName, password, host);
e.printStackTrace();
}
return null;
}
/**
* 文件内容编辑
* @param contentList :内容
* @param fileName :文件名称
* @param dPath : /home/include/
*/
public static void upLoadToIgenetech(List<String> contentList, String fileName, String dPath){
JSch jsch = new JSch();
Session session = null;
try {
//用户名、ip地址、端口号
session = jsch.getSession(userName, host, port);
} catch (JSchException e) {
e.printStackTrace();
}
// 设置登陆主机的密码
session.setPassword(password);// 设置密码
// 设置第一次登陆的时候提示,可选值:(ask | yes | no)
session.setConfig("StrictHostKeyChecking", "no");
// 设置登陆超时时间
try {
session.connect(300000);
} catch (JSchException e) {
e.printStackTrace();
}
Channel channel = null;
try {
channel = (Channel) session.openChannel("sftp");
channel.connect(10000000);
ChannelSftp sftp = (ChannelSftp) channel;
try {
sftp.cd(dPath);
} catch (SftpException e) {
sftp.mkdir(dPath);
sftp.cd(dPath);
}
OutputStream o = null;
File file = new File(dPath + "/" + fileName);
o = sftp.put(file.getName());
new File(dPath + "/" + fileName);
for(int i = 0; i < contentList.size(); i++){
o.write((contentList.get(i) + "\r\n").getBytes("UTF-8"));
}
o.close();
System.out.println("编辑完成!");
} catch (Exception e) {
e.printStackTrace();
} finally {
session.disconnect();
channel.disconnect();
}
}
}
3.本地测试好使,部署在服务器上,立马不行,开始报错。各种百度好多坑,终于找到了解决办法
发现是由于JRE缺少包导致,添加包解决:
sunjce_provider.jar
位于本地JRE目录jre/lib/ext/下
将上面那个包复制到你自己项目的下面就ok。
JSchException: Session.connect: java.security.NoSuchAlgorithmException: DH KeyPairGenerator not avai