備註:根據自己的業務可以去修改一下。下面只是實現了我的業務:將服務器上的文件複製到另一個文件下,並且在指定的內容處添加內容。
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