#頭條創作挑戰賽#
背景
java 通過jsch 遠端執行指令 jsch 主要是類似Xshell 隻不過是代碼級别使用,而 Xshell使用界面化
jsch可以執行任何shell 腳本,但是弊端是執行一次必須要關閉目前會話,每次都要cd目前目錄
在執行相關指令,都是操作 channle 同時寫了一個cmd執行方法為的是執行linux指令
setCommand(…) 這個方法是比較重要的 session就是維護你目前會話和伺服器進行交流的
channle相當于管道流,資料互動用的
一、導入相關的依賴包
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
二、實作相關的工具類
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Slf4j
public class ShellUtil {
private String host;
private String username;
private String password;
private int port = 22;
private int timeout = 60 * 60 * 1000;
public ShellUtil(String host, String username, String password, int port, int timeout) {
this.host = host;
this.username = username;
this.password = password;
this.port = port;
this.timeout = timeout;
}
public ShellUtil(String host, String username, String password) {
this.host = host;
this.username = username;
this.password = password;
}
public Session createSession() throws JSchException {
JSch jSch = new JSch();
// 1. 擷取 ssh session
Session session = jSch.getSession(username, host, port);
session.setPassword(password);
session.setTimeout(timeout);
//StrictHostKeyChecking=no 最不安全的級别,當然也沒有那麼多煩人的提示了,相對安全的内網測試時建議使用
//如果連接配接server的key在本地不存在,那麼就自動添加到檔案中(預設是known_hosts),并且給出一個警告。
//StrictHostKeyChecking=ask 預設的級别,就是出現剛才的提示了。如果連接配接和key不比對,給出提示,并拒絕登入。
//StrictHostKeyChecking=yes 最安全的級别,如果連接配接與key不比對,就拒絕連接配接,不會提示詳細資訊。
session.setConfig("StrictHostKeyChecking", "no");
// 擷取到 ssh session
session.connect();
return session;
}
public String execCommand(String cmd) {
Session session = null;
ChannelExec channelExec = null;
BufferedReader inputStreamReader = null;
BufferedReader errInputStreamReader = null;
StringBuilder runLog = new StringBuilder("");
StringBuilder errLog = new StringBuilder("");
try {
session = createSession();
// 2. 通過 exec 方式執行 shell 指令
channelExec = (ChannelExec) session.openChannel("exec");
channelExec.setCommand(cmd);
// 執行指令
channelExec.connect();
// 3. 擷取标準輸入流
inputStreamReader = new BufferedReader(new
InputStreamReader(channelExec.getInputStream()));
// 4. 擷取标準錯誤輸入流
errInputStreamReader = new BufferedReader(new
InputStreamReader(channelExec.getErrStream()));
// 5. 記錄指令執行 log
String line;
while ((line = inputStreamReader.readLine()) != null) {
runLog.append(line).append("\n");
}
// 6. 記錄指令執行錯誤 log
String errLine;
while ((errLine = errInputStreamReader.readLine()) != null) {
errLog.append(errLine).append("\n");
}
// 7. 輸出 shell 指令執行日志
log.info("exitStatus={},openChannel.isClosed={}", channelExec.getExitStatus(), channelExec.isClosed());
log.info("指令執行完成,執行日志如下:{}", runLog.toString());
log.info("指令執行完成,執行錯誤日志如下:{}", errLog.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (!StringUtils.isEmpty(inputStreamReader)) {
inputStreamReader.close();
}
if (!StringUtils.isEmpty(errInputStreamReader)) {
errInputStreamReader.close();
}
if (!StringUtils.isEmpty(channelExec)) {
channelExec.disconnect();
}
if (!StringUtils.isEmpty(session)) {
session.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return runLog.toString();
}
}
三、實作調用
String shCmd = "sh /xxx/xxx/syncFile.sh";
//執行調用腳本執行
ShellUtil shellUtil = new ShellUtil("ip", "username", "password");
String execLog = shellUtil.execCommand(shCmd);
log.info(execLog);