使用java代碼連接到局域網內的Windows服務器中的軟件並執行指令
1、前言
最近需要實現一個功能,編寫java代碼連接windows服務器並運行命令。
使用一款叫做freeSSHd的軟件進行連接。使用時,將freeSSHd安裝到想要連接的目標服務器上(相當於java代碼是客戶端,freeSSHd是服務器)。
1.1 freeSSHd 簡介
freeSSHd是一個SFTP服務器。它支持使用密碼或SSH免密登錄的方法進行上傳文件或遠程操作系統。
其實就是一個遠程操作的服務端,安裝了SFTP服務器的操作系統就可以被支持進行遠程操作。這個在Linux操作系統中使用比較常見。但是在Windows操作系統上也會有這樣的需求,比如我們需要自動化地在另一台Windows的服務器上進行遠程部署服務,這是就需要能遠程操作該系統。而freeSSHd是提供給Windows的一個免費的SFTP服務器,搭建簡單,使用效果也比較好。
PS,相關api的使用:
2、 安裝freeSSHd
2.1 下載
軟件下載地址:下載freeSSHd.exe
2.2 開始安裝freeSSHd:
雙擊程序進行安裝,選好自己的安裝目錄后就一路next即可
安裝過程中會提示兩個選項
-
Private keys should be created. Should I do it now?
這是在詢問現在是否創建私鑰,選是。
-
Do you want to run FreeSSHd as a system service?
這是在詢問是否開啟freeSSHd服務,選是。
2.3 freeSSHd配置
雙擊桌面上的freeSSHd或者從開始菜單欄中的freeSSHd並不會打開軟件,這是因為軟件已經啟動並隱藏在右下角處。
在桌面右下角右擊freeSSHdService,選擇settings進行配置。
1、首先配置Server status
找到Server status選項卡,SSH server is running. 默認是紅叉,點擊下方 Click here to start it.啟動服務,紅叉會變成綠勾
如果沒有變成綠勾,並報錯“the specified address is already in use”,這是因為服務在上面已經開啟,需要關閉。win + r 輸入services.msc 找到freeSShd的服務關閉,
關閉之后重啟點擊Click here to start it啟動服務,這時候發現服務已經啟動。
2、配置用戶
找到Users選項卡,點擊add添加一個用戶
第二欄authorization選項選擇 Password stored as SHA1 hash,接着輸入用戶名和密碼。之后確定
3、配置端口
找到SSH選項卡 listen address:監聽的地址 port:監聽的端口 max number of connections:最大連接數,自行配置,端口號默認22盡量不要修改
3、遠程連接服務器(Windows和Linux)在控制台界面執行指令
創建普通的maven項目saodisheng-freesshd
不得不說idea2021.1相較於之前使用的2019.3界面更加舒適啦
3.1 方式一
需要借助Ganymed SSH的jar包
<!-- https://mvnrepository.com/artifact/ch.ethz.ganymed/ganymed-ssh2 -->
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
代碼如下
package top.saodisheng.ganymed;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* description:
*
* @author 掃地生_saodisheng
* @date 2021/7/7
*/
@Slf4j
public class SSH_Ganymed {
public static void main(String[] args) {
// 服務器ipv4地址
String ipv4Address = "xx.xx.xx.xx";
// freeSshd設置的連接端口
int port = 22;
// username
String freeSshdUserName = "saodisheng";
// password
String freeSshdUserPassword = "saodisheng";
// 在cmd中執行的命令
String command = "java -version";
// String command = "E:\\Environment\\Navicat_Premium_12\\navicat.exe";
connectServer(ipv4Address, port, freeSshdUserName, freeSshdUserPassword, command);
}
public static void connectServer(String ipv4Address, int port, String freeSshdUserName, String freeSshdUserpassword, String command) {
Connection conn = null;
Session session = null;
InputStream is = null;
BufferedReader br = null;
try {
// 創建連接
conn = new Connection(ipv4Address, port);
conn.connect(); // 開啟連接
// login
boolean isLogin = conn.authenticateWithPassword(freeSshdUserName, freeSshdUserpassword); // 獲取登錄狀態
if (isLogin) {
log.debug("Login success");
System.out.println("login success");
} else {
log.debug("login failed");
System.out.println("login failed");
}
// 獲取session即打開會話框(終端)
session = conn.openSession();
// 執行指令
session.execCommand(command);
// 獲取輸出的結果,用於將結果輸出到控制台
is = new StreamGobbler(session.getStdout());
br = new BufferedReader(new InputStreamReader(is, "GBK"));
while (true) {
String line = br.readLine();
if (line == null) {
break;
}
System.out.println(line);
}
// 查看指令執行的結果,session.getExitStatus(); 獲取指令的執行結果,0表示執行成功,非0表示失敗。
System.out.println(session.getExitStatus());
} catch (IOException e) {
log.error("", e);
System.out.println(e.getMessage());
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
}
if (is != null) {
is.close();
}
if (session != null) {
session.close();
}
if (conn != null) {
conn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.2 方式二
需要借助JSch的包
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
代碼如下
package saodisheng.jsch;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
/**
* description:
*
* @author 掃地生_saodisheng
* @date 2021/7/7
*/
@Slf4j
public class SSH_JSch {
public static void main(String[] args) {
// 服務器ipv4地址
String ipv4Address = "xx.xx.xx.xx";
// freeSshd設置的連接端口
int port = 22;
// username
String freeSshdUserName = "saodisheng";
// password
String freeSshdUserPassword = "saodisheng";
// 在cmd中執行的命令
String command = "ls -al; pwd";
String info = SSH_JSch.connectServer(ipv4Address, port, freeSshdUserName, freeSshdUserPassword, command);
System.out.println(info);
}
public static String connectServer(String freesshdIpFour, int freesshdPort, String freesshdUsername, String freesshdPassword, String command) {
// 創建JSch對象
JSch jSch = new JSch();
BufferedReader reader = null;
Channel channel = null;
Session session = null;
try {
// 獲取會話
session = jSch.getSession(freesshdUsername, freesshdIpFour, freesshdPort);
if (session == null) {
log.debug("session 打開失敗, session為空");
System.out.println("session 打開失敗, session為空");
}
// 設置第一次登陸的時候提示,可選值:(ask | yes | no),不設置的話會出現連接失敗的情況
session.setConfig("StrictHostKeyChecking", "no");
// 設置登錄密碼
session.setPassword(freesshdPassword);
Properties config = new Properties();
session.setTimeout(1500);
// 連接
session.connect();
if (command != null) {
// 打開通道
channel = session.openChannel("exec");
// 設置指令
((ChannelExec) channel).setCommand(command);
// 指令提交執行
channel.connect();
InputStream in = channel.getInputStream();
reader = new BufferedReader(new InputStreamReader(in, "GBK"));
String buf;
StringBuffer sb = new StringBuffer();
while ((buf = reader.readLine()) != null) {
sb = sb.append(buf + "\n");
}
// 查看指令執行狀態, 0表示成功,非0表示失敗
int exitStatus = channel.getExitStatus();
System.out.println(exitStatus);
return sb.toString();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (session != null) {
session.disconnect();
}
if (channel != null) {
channel.disconnect();
}
}
return null;
}
}
可能遇到問題:
com.jcraft.jsch.JSchException: UnknownHostKey: x.x.x.x. RSA key fingerprint is 1b:1e:f4:0e:e7:07:e2:9a:4b:15:7d:1a:47:a9:e8:eb
4、在cmd里面運行程序
比如說我要在cmd控制台中啟動Navicat軟件
1、找到Navicat所在的路徑
我的路徑為:E:\Environment\Navicat_Premium_12\navicat.exe
切記:路徑中不可出現空格
2、打開cmd界面,直接將路徑輸入即可
結合前面的程序可知,我們只要將cmd中的指令更換即可實現啟動指定程序的目的。
比如我要通過java程序遠程打開指定的軟件:
由此也可以發現,當我們需要遠程啟動相應的服務時,最重要的是要連接到對應的服務器。在Linux平台上,我們也可以通過遠程啟動shell腳本來控制某些指定的服務。