首先創(chuàng)建springboot項(xiàng)目
shell腳本
這里是執(zhí)行本地腳本
#!/bin/sh
echo 'Hello World!'
然后編寫執(zhí)行shell腳本的util類
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class ShellUtils {
/**
* @param pathOrCommand 腳本路徑或者命令
* @return
*/
public static List<String> exceShell(String pathOrCommand) {
List<String> result = new ArrayList<>();
try {
// 執(zhí)行腳本
Process ps = Runtime.getRuntime().exec(pathOrCommand);
int exitValue = ps.waitFor();
if (0 != exitValue) {
System.out.println("call shell failed. error code is :" + exitValue);
}
// 只能接收腳本echo打印的數(shù)據(jù),并且是echo打印的最后一次數(shù)據(jù)
BufferedInputStream in = new BufferedInputStream(ps.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = br.readLine()) != null) {
System.out.println("腳本返回的數(shù)據(jù)如下: " + line);
result.add(line);
}
in.close();
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
最后開(kāi)發(fā)接口調(diào)用此類
@RestController
@RequestMapping("/shell/test")
public class ShellTestController {
@GetMapping("/shell")
public List<String> shellTest(){
List<String> list = ShellUtils.exceShell("/home/shelltest/test.sh");
return list;
}
}
如何執(zhí)行遠(yuǎn)程腳本
在這里我試用了三種方式,實(shí)現(xiàn)遠(yuǎn)程腳本的執(zhí)行
但是使用ssh2時(shí)
java.io.IOException: Key exchange was not finished, connection is closed.
at ch.ethz.ssh2.transport.KexManager.getOrWaitForConnectionInfo(KexManager.java:75)
at ch.ethz.ssh2.transport.TransportManager.getConnectionInfo(TransportManager.java:169)
at ch.ethz.ssh2.Connection.connect(Connection.java:759)
at ch.ethz.ssh2.Connection.connect(Connection.java:628)
at com.zhou.util.SSHClient.login(SSHClient.java:39)
at com.zhou.util.SSHClient.exec(SSHClient.java:47)
at com.zhou.util.SSHClient.main(SSHClient.java:76)
Caused by: java.io.IOException: Cannot negotiate, proposals do not match.
at ch.ethz.ssh2.transport.ClientKexManager.handleMessage(ClientKexManager.java:123)
at ch.ethz.ssh2.transport.TransportManager.receiveLoop(TransportManager.java:572)
at ch.ethz.ssh2.transport.TransportManager$1.run(TransportManager.java:261)
at java.lang.Thread.run(Thread.java:745)
會(huì)拋出上述的異常,大體的意思就是密鑰交換算法不匹配,導(dǎo)致連接失敗。
但是老版本的centos系統(tǒng)還是可以使用的
此版本使用沒(méi)有問(wèn)題 ,下面是代碼
引入的maven
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
package com.zhou.util;
import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
public class SSHClient {
private String ip;
private String username;
private String password;
private String charset = Charset.defaultCharset().toString();
private static final int TIME_OUT = 1000 * 5 * 60;
private Connection conn;
public SSHClient(String ip, String username, String password) {
this.ip = ip;
this.username = username;
this.password = password;
}
/**
* 登錄指遠(yuǎn)程服務(wù)器
* @return
* @throws IOException
*/
private boolean login() throws IOException {
conn = new Connection(ip);
conn.connect();
return conn.authenticateWithPassword(username, password);
}
public List<String> exec(String shell) throws Exception {
List<String> result = new ArrayList<>();
int ret = -1;
try {
if (login()) {
Session session = conn.openSession();
session.execCommand(shell);
session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
ret = session.getExitStatus();
// 只能接收腳本echo打印的數(shù)據(jù),并且是echo打印的最后一次數(shù)據(jù)
BufferedInputStream in = new BufferedInputStream(session.getStdout());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = br.readLine()) != null) {
System.out.println("腳本返回的數(shù)據(jù)如下: " + line);
result.add(line);
}
in.close();
br.close();
} else {
throw new Exception("登錄遠(yuǎn)程機(jī)器失敗" + ip); // 自定義異常類 實(shí)現(xiàn)略
}
} finally {
if (conn != null) {
conn.close();
}
}
return result;
}
public static void main(String[] args) {
try {
SSHClient sshClient = new SSHClient("192.168.0.1", "root", "123456");
List<String> exec = sshClient.exec("/home/shell/run_all.sh");
for (String s : exec) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用sshd可以正常進(jìn)行遠(yuǎn)程執(zhí)行shell文件
maven代碼
<!-- ssh-core start-->
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>net.i2p.crypto</groupId>
<artifactId>eddsa</artifactId>
<version>0.3.0</version>
</dependency>
<!-- ssh-core end-->
package com.zhou.util.sshcore;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.client.session.ClientSession;
import java.io.ByteArrayOutputStream;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class SshSelfDemo {
public static String runCommand(String hostName,String userName,String pwd,int port,String cmd, long timeout)
throws Exception {
SshClient client = SshClient.setUpDefaultClient();
try {
// Open the client
client.start();
// Connect to the server
ConnectFuture cf = client.connect(userName, hostName, port);
ClientSession session = cf.verify().getSession();
session.addPasswordIdentity(pwd);
session.auth().verify();
// Create the exec and channel its output/error streams
ChannelExec ce = session.createExecChannel(cmd);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
ce.setOut(out);
ce.setErr(err);
// Execute and wait
ce.open();
Set<ClientChannelEvent> events =
ce.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(timeout));
session.close(false);
return out.toString();
} finally {
client.stop();
}
}
public static void main(String[] args) throws Exception{
String hostName = "192.168.0.1";
String userName = "root";
String pwd = "123456";
int port = 22;
SshConnection conn = new SshConnection(userName,pwd,hostName);
// &&-表示前面命令執(zhí)行成功在執(zhí)行后面命令; ||表示前面命令執(zhí)行失敗了在執(zhí)行后面命令; ";"表示一次執(zhí)行兩條命令
String cmd = "/home/shell/run_all.sh";
String result = runCommand(hostName,userName,pwd,port,cmd,15);
System.out.println("===返回結(jié)果===>"+result);
// runCommandForInteractive(conn,15);
}
}
使用jsch也可以正常執(zhí)行shell文件
maven依賴
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
代碼文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-621661.html
package com.zhou.util.sshcore;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.util.Properties;
public class JSchExecShellUtil {
private static final Logger logger = LoggerFactory.getLogger(JSchExecShellUtil.class);
public static String execShell(String hostName,String userName,String pwd,int port,String command, int timeout){
// 創(chuàng)建JSch對(duì)象
JSch jSch = new JSch();
Session jSchSession = null;
Channel jschChannel = null;
// 存放執(zhí)行命令結(jié)果
StringBuffer result = new StringBuffer();
int exitStatus = 0;
try {
// 根據(jù)主機(jī)賬號(hào)、ip、端口獲取一個(gè)Session對(duì)象
jSchSession = jSch.getSession(userName, hostName, port);
// 存放主機(jī)密碼
jSchSession.setPassword(pwd);
// 去掉首次連接確認(rèn)
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
jSchSession.setConfig(config);
// 超時(shí)連接時(shí)間為3秒
jSchSession.setTimeout(timeout);
// 進(jìn)行連接
jSchSession.connect();
jschChannel = jSchSession.openChannel("exec");
((ChannelExec) jschChannel).setCommand(command);
jschChannel.setInputStream(null);
// 錯(cuò)誤信息輸出流,用于輸出錯(cuò)誤的信息,當(dāng)exitstatus<0的時(shí)候
((ChannelExec)jschChannel).setErrStream(System.err);
// 執(zhí)行命令,等待執(zhí)行結(jié)果
jschChannel.connect();
// 獲取命令執(zhí)行結(jié)果
InputStream in = jschChannel.getInputStream();
/**
* 通過(guò)channel獲取信息的方式,采用官方Demo代碼
*/
byte[] tmp=new byte[1024];
while(true){
while(in.available() > 0){
int i = in.read(tmp, 0, 1024);
if (i < 0) {
break;
}
result.append(new String(tmp, 0, i));
}
// 從channel獲取全部信息之后,channel會(huì)自動(dòng)關(guān)閉
if(jschChannel.isClosed()){
if (in.available() > 0) {
continue;
}
exitStatus = jschChannel.getExitStatus();
break;
}
try{Thread.sleep(1000);}catch(Exception ee){}
}
} catch (Exception e) {
logger.warn(e.getMessage());
} finally {
// 關(guān)閉sftpChannel
if (jschChannel != null && jschChannel.isConnected()) {
jschChannel.disconnect();
}
// 關(guān)閉jschSesson流
if (jSchSession != null && jSchSession.isConnected()) {
jSchSession.disconnect();
}
}
logger.info("獲取執(zhí)行命令的結(jié)果結(jié)果:"+result);
logger.info("退出碼為:"+exitStatus);
return result.toString();
}
public static void main(String[] args) {
String username = "root";
String password = "123456";
String host = "192.168.0.1";
int port = 22;
String commond = "/home/shell/run_all.sh";
execShell(host,username,password, port, commond, 1000);
}
}
以上是整理的Java遠(yuǎn)程調(diào)用以及本地調(diào)用的代碼實(shí)現(xiàn)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-621661.html
到了這里,關(guān)于springboot通過(guò)接口執(zhí)行本地shell腳本的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!