英文:
how to execute remote commands using apache mina sshd
问题
以下是您提供的代码的翻译:
SSHServer.java
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.command.Command;
import org.apache.sshd.server.command.CommandFactory;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.scp.ScpCommandFactory;
import org.apache.sshd.server.shell.InteractiveProcessShellFactory;
import org.apache.sshd.server.shell.ProcessShellCommandFactory;
import org.apache.sshd.server.shell.ProcessShellFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SSHServer {
private SshServer sshServer;
private static final Logger logger = LoggerFactory.getLogger(SSHServer.class);
public SSHServer(int port) {
sshServer = SshServer.setUpDefaultServer();
initializeServer(port);
}
private void initializeServer(int port) {
sshServer.setPort(port);
sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
sshServer.setFileSystemFactory(getFileSystemFactory());
sshServer.setCommandFactory(getScpCommandFactory());
sshServer.setPasswordAuthenticator(getPasswordAuthenticator());
sshServer.setShellFactory(getProcessShellFactory());
}
public int getPort() {
return sshServer.getPort();
}
public String getHost() {
return sshServer.getHost();
}
public void startServer() throws IOException {
sshServer.start();
logger.debug("SSHServer started on Port: {}", sshServer.getPort());
}
public void stopServer() throws IOException {
sshServer.stop();
logger.debug("SSHServer stopped...");
}
private ScpCommandFactory getScpCommandFactory() {
CommandFactory myCommandFactory = new CommandFactory() {
@Override
public Command createCommand(ChannelSession channelSession, String s) {
logger.info("Command on SSHServer: {}", s);
return null;
}
};
return new ScpCommandFactory.Builder().withDelegate(new ProcessShellCommandFactory()).build();
}
private VirtualFileSystemFactory getFileSystemFactory() {
return new VirtualFileSystemFactory() {
@Override
public Path getUserHomeDir(SessionContext session) {
String userHomeDir = System.getProperty("user.home");
return Paths.get(userHomeDir);
}
};
}
private PasswordAuthenticator getPasswordAuthenticator() {
return (username, password, serverSession) -> {
logger.info("authenticating user: {}", username);
return true;
};
}
private ProcessShellFactory getProcessShellFactory() {
return new InteractiveProcessShellFactory();
}
}
SSHClient.java
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.session.SessionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SSHClient {
private SshClient sshClient;
private String username;
private String host;
private String password;
private int port;
private static final Logger logger = LoggerFactory.getLogger(SSHClient.class);
private SSHClient(){}
public SSHClient(String username, String password, String host, int port) {
logger.info("Creating SSHClient for username: {} for {}:{}", username, host, port);
sshClient = SshClient.setUpDefaultClient();
sshClient.setFileSystemFactory(new VirtualFileSystemFactory() {
@Override
public Path getUserHomeDir(SessionContext session) {
return Paths.get(System.getProperty("user.home"));
}
});
this.username = username;
this.password = password;
this.host = host;
this.port = port;
}
public ClientSession connect() throws IOException {
ConnectFuture connectFuture = sshClient.connect(username, host, port).verify();
logger.info("SSHClient is connected: {}", connectFuture.isConnected());
return connectFuture.getSession();
}
public void startClient() {
sshClient.start();
logger.info("SSHClient is started...");
}
public void stopClient() {
sshClient.stop();
logger.info("SSHClient is stopped...");
}
}
TestSSH.java
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
public class TestSSH {
public static void main(String[] args) throws IOException {
SSHServer sshServer = new SSHServer(null, 45018);
sshServer.startServer();
SSHClient sshClient = new SSHClient("", "", "localhost", 45018);
sshClient.startClient();
ClientSession clientSession = sshClient.connect();
clientSession.addPasswordIdentity("randompassword");
System.out.println(clientSession.auth().verify().isSuccess());
ClientChannel execChannel = clientSession.createChannel(ClientChannel.CHANNEL_EXEC, "whoami");
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
execChannel.setOut(out);
execChannel.setErr(err);
execChannel.open().await(1, TimeUnit.SECONDS);
Collection<ClientChannelEvent> waitMask = execChannel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 10000);
waitMask.forEach(event -> System.out.println(event.name()));
System.out.println(execChannel.getExitStatus());
byte[] errBytes = err.toByteArray();
byte[] outBytes = out.toByteArray();
System.out.println(new String(outBytes, StandardCharsets.UTF_8));
System.out.println(new String(errBytes, StandardCharsets.UTF_8));
sshServer.stopServer();
System.out.println("Exiting");
System.exit(0);
}
}
请注意,由于代码片段较长,翻译中的某些细节可能会有所省略。如果您在使用代码时遇到问题,可以针对具体问题提出相关的问题。
英文:
I am trying to execute remote commands on an SSHServer running on my local windows machine.
I am able to run simple command like "whoami" but failing to run something like "java -version" or "dir"
Here is my code so far, can you tell where I am going wrong?
SSHServer.java
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.session.SessionContext;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.command.Command;
import org.apache.sshd.server.command.CommandFactory;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.scp.ScpCommandFactory;
import org.apache.sshd.server.shell.InteractiveProcessShellFactory;
import org.apache.sshd.server.shell.ProcessShellCommandFactory;
import org.apache.sshd.server.shell.ProcessShellFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SSHServer {
private SshServer sshServer;
private static final Logger logger = LoggerFactory.getLogger(SSHServer.class);
public SSHServer(int port) {
sshServer = SshServer.setUpDefaultServer();
initializeServer(port);
}
private void initializeServer(int port) {
sshServer.setPort(port);
sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
sshServer.setFileSystemFactory(getFileSystemFactory());
sshServer.setCommandFactory(getScpCommandFactory());
sshServer.setPasswordAuthenticator(getPasswordAuthenticator());
sshServer.setShellFactory(getProcessShellFactory());
//sshServer.setSessionHeartbeat(SessionHeartbeatController.HeartbeatType.IGNORE, TimeUnit.SECONDS, 5);
}
public int getPort() {
return sshServer.getPort();
}
public String getHost() {
return sshServer.getHost();
}
public void startServer() throws IOException {
sshServer.start();
logger.debug("SSHServer started on Port: {}", sshServer.getPort());
}
public void stopServer() throws IOException {
sshServer.stop();
logger.debug("SSHServer stopped...");
}
private ScpCommandFactory getScpCommandFactory() {
CommandFactory myCommandFactory = new CommandFactory() {
@Override
public Command createCommand(ChannelSession channelSession, String s) {
logger.info("Command on SSHServer: {}", s);
return null;
}
};
return new ScpCommandFactory.Builder().withDelegate(new ProcessShellCommandFactory()).build();
}
private VirtualFileSystemFactory getFileSystemFactory() {
return new VirtualFileSystemFactory() {
@Override
public Path getUserHomeDir(SessionContext session) {
String userHomeDir = System.getProperty("user.home");
return Paths.get(userHomeDir);
}
};
}
private PasswordAuthenticator getPasswordAuthenticator() {
return (username, password, serverSession) -> {
logger.info("authenticating user: {}", username);
return true;
};
}
private ProcessShellFactory getProcessShellFactory() {
return new InteractiveProcessShellFactory();
}
}
SSHClient.java
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.session.SessionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
public class SSHClient {
private SshClient sshClient;
private String username;
private String host;
private String password;
private int port;
private static final Logger logger = LoggerFactory.getLogger(SSHClient.class);
private SSHClient(){}
public SSHClient(String username, String password, String host, int port) {
logger.info("Creating SSHClient for username: {} for {}:{}", username, host, port);
sshClient = SshClient.setUpDefaultClient();
sshClient.setFileSystemFactory(new VirtualFileSystemFactory() {
@Override
public Path getUserHomeDir(SessionContext session) {
return Paths.get(System.getProperty("user.home"));
}
});
this.username = username;
this.password = password;
this.host = host;
this.port = port;
}
public ClientSession connect() throws IOException {
ConnectFuture connectFuture = sshClient.connect(username, host, port).verify();
logger.info("SSHClient is connected: {}", connectFuture.isConnected());
return connectFuture.getSession();
}
public void startClient() {
sshClient.start();
logger.info("SSHClient is started...");
}
public void stopClient() {
sshClient.stop();
logger.info("SSHClient is stopped...");
}
}
TestSSH.java
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
public class TestSSH {
public static void main(String[] args) throws IOException {
SSHServer sshServer = new SSHServer(null, 45018);
sshServer.startServer();
SSHClient sshClient = new SSHClient("", "", "localhost", 45018);
sshClient.startClient();
ClientSession clientSession = sshClient.connect();
clientSession.addPasswordIdentity("randompassword");
System.out.println(clientSession.auth().verify().isSuccess());
ClientChannel execChannel = clientSession.createChannel(ClientChannel.CHANNEL_EXEC, "whoami");
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
execChannel.setOut(out);
execChannel.setErr(err);
execChannel.open().await(1, TimeUnit.SECONDS);
Collection<ClientChannelEvent> waitMask = execChannel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 10000);
waitMask.forEach(event -> System.out.println(event.name()));
System.out.println(execChannel.getExitStatus());
byte[] errBytes = err.toByteArray();
byte[] outBytes = out.toByteArray();
System.out.println(new String(outBytes, StandardCharsets.UTF_8));
System.out.println(new String(errBytes, StandardCharsets.UTF_8));
/* Scanner scanner = new Scanner(System.in);
scanner.nextInt();*/
sshServer.stopServer();
System.out.println("Exiting");
System.exit(0);
}
}
here is the output for "whoami":
2020-07-24 19:22:44,267 DEBUG c.w.v.g.s.SSHServer [main] SSHServer started on Port: 45018
2020-07-24 19:22:44,278 INFO c.w.v.g.s.SSHClient [main] Creating SSHClient for username: for localhost:45018
2020-07-24 19:22:44,369 INFO c.w.v.g.s.SSHClient [main] SSHClient is started...
2020-07-24 19:22:44,713 INFO c.w.v.g.s.SSHClient [main] SSHClient is connected: true
2020-07-24 19:22:45,835 INFO c.w.v.g.s.SSHServer [sshd-SshServer[41d477ed](port=45018)-nio2-thread-3] authenticating user:
true
CLOSED
EOF
EXIT_STATUS
OPENED
0
properOutputhere
2020-07-24 19:22:46,969 DEBUG c.w.v.g.s.SSHServer [main] SSHServer stopped...
Exiting
Process finished with exit code 0
here is the output when I try to execute "dir" using:
ClientChannel execChannel = clientSession.createChannel(ClientChannel.CHANNEL_EXEC, "dir");
output:
2020-07-24 19:25:20,128 DEBUG c.w.v.g.s.SSHServer [main] SSHServer started on Port: 45018
2020-07-24 19:25:20,140 INFO c.w.v.g.s.SSHClient [main] Creating SSHClient for username: for localhost:45018
2020-07-24 19:25:20,237 INFO c.w.v.g.s.SSHClient [main] SSHClient is started...
2020-07-24 19:25:20,566 INFO c.w.v.g.s.SSHClient [main] SSHClient is connected: true
2020-07-24 19:25:21,453 INFO c.w.v.g.s.SSHServer [sshd-SshServer[33d512c1](port=45018)-nio2-thread-3] authenticating user:
true
TIMEOUT
OPENED
null
2020-07-24 19:25:31,539 DEBUG c.w.v.g.s.SSHServer [main] SSHServer stopped...
Exiting
Process finished with exit code 0
答案1
得分: 1
package com.example.demo;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.security.KeyPair;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.channel.Channel;
// https://stackoverflow.com/questions/63075107/how-to-execute-remote-commands-using-//apache-mina-sshd
public class SshClientDemo {
public String getFileList(String host, String username, String password, int port, long defaultTimeout) throws Exception {
// uses the default id_rsa and id_rsa.pub files to connect to ssh server
SshClient client = SshClient.setUpDefaultClient();
client.start();
try (ClientSession session = client.connect(username, host, port).verify(defaultTimeout, TimeUnit.SECONDS).getSession()) {
//session.addPasswordIdentity(password);
session.auth().verify(defaultTimeout, TimeUnit.SECONDS);
try (ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
ClientChannel channel = session.createChannel(Channel.CHANNEL_EXEC, "dir")) // to execute remote commands
{
channel.setOut(responseStream);
channel.setErr(errorStream);
try {
channel.open().verify(defaultTimeout, TimeUnit.SECONDS);
try (OutputStream pipedIn = channel.getInvertedIn()) {
pipedIn.write("dir".getBytes());
pipedIn.flush();
}
channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),
TimeUnit.SECONDS.toMillis(defaultTimeout));
String error = new String(errorStream.toByteArray());
if (!error.isEmpty()) {
throw new Exception(error);
}
return responseStream.toString();
}
finally {
channel.close(false);
}
}
}
finally {
client.stop();
}
}
}
// use this where you need to maybe main method
SshClientDemo demo = new SshClientDemo();
try {
String data = demo.getFileList("<your host name>", "<your user name>", null, 22, 10);
System.out.println(" listing.....");
System.out.println(data);
}
catch (Exception e) {
e.printStackTrace();
}
listing.....
Volume in drive C is win-ent
Volume Serial Number is 2C26-6048
Directory of c:\users\atlantis
06/04/2021 04:03 PM <DIR> .
06/04/2021 04:03 PM <DIR> ..
06/18/2020 07:34 PM <DIR> .android
...
... (listing of files and directories)
...
08/06/2020 08:30 PM <DIR> IBM
02/14/2020 05:14 PM <DIR> Intel
07/16/2020 07:23 PM 52,192 java_error_in_idea_6696.log
06/24/2020 11:01 AM 68,569 java_error_in_webstorm_17796.log
...
... (more file listing)
...
06/15/2020 07:20 PM 144 webstorm.txt
17 File(s) 174,037 bytes
63 Dir(s) 36,056,952,832 bytes free
英文:
package com.example.demo;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.security.KeyPair;
import java.util.EnumSet;
import java.util.concurrent.TimeUnit;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.channel.ClientChannel;
import org.apache.sshd.client.channel.ClientChannelEvent;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.channel.Channel;
// https://stackoverflow.com/questions/63075107/how-to-execute-remote-commands-using-//apache-mina-sshd
public class SshClientDemo {
public String getFileList(String host, String username, String password, int port, long defaultTimeout) throws Exception {
// uses the default id_rsa and id_rsa.pub files to connect to ssh server
SshClient client = SshClient.setUpDefaultClient();
client.start();
try (ClientSession session = client.connect(username, host, port).verify(defaultTimeout, TimeUnit.SECONDS).getSession()) {
//session.addPasswordIdentity(password);
session.auth().verify(defaultTimeout, TimeUnit.SECONDS);
try (ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
ClientChannel channel = session.createChannel(Channel.CHANNEL_EXEC, "dir")) // to execute remote commands
{
channel.setOut(responseStream);
channel.setErr(errorStream);
try {
channel.open().verify(defaultTimeout, TimeUnit.SECONDS);
try (OutputStream pipedIn = channel.getInvertedIn()) {
pipedIn.write("dir".getBytes());
pipedIn.flush();
}
channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),
TimeUnit.SECONDS.toMillis(defaultTimeout));
String error = new String(errorStream.toByteArray());
if (!error.isEmpty()) {
throw new Exception(error);
}
return responseStream.toString();
}
finally {
channel.close(false);
}
}
}
finally {
client.stop();
}
}
}
// use this where you need to maybe main method
SshClientDemo demo = new SshClientDemo();
try {
String data = demo.getFileList("<your host name>", "<your user name>", null, 22, 10);
System.out.println(" listing.....");
System.out.println(data);
}
catch (Exception e) {
e.printStackTrace();
}
# output
listing.....
Volume in drive C is win-ent
Volume Serial Number is 2C26-6048
Directory of c:\users\atlantis
06/04/2021 04:03 PM <DIR> .
06/04/2021 04:03 PM <DIR> ..
06/18/2020 07:34 PM <DIR> .android
06/20/2020 10:24 PM 57 .angular-config.json
06/01/2020 11:26 AM <DIR> .ApacheDirectoryStudio
02/16/2020 12:11 AM <DIR> .aws
04/20/2021 03:01 PM 30,199 .bash_history
08/14/2020 08:06 PM 995 .bash_history2
04/22/2020 02:16 PM 20,438 .boto
04/01/2021 04:21 PM <DIR> .cache
07/23/2020 07:26 PM <DIR> .cassandra
08/14/2020 12:07 AM <DIR> .codemix
08/14/2020 12:13 AM <DIR> .codemix-store
08/13/2020 05:54 PM 104 .codemix.properties
09/01/2020 07:03 PM <DIR> .codewind
06/16/2020 12:06 PM <DIR> .config
07/26/2020 07:22 PM 15 .dbshell
03/13/2021 07:18 PM <DIR> .docker
11/23/2020 12:28 PM <DIR> .eclipse
04/17/2020 07:56 PM 60 .gitconfig
04/17/2021 03:06 PM <DIR> .gnupg
04/11/2021 10:46 PM <DIR> .gradle
03/31/2020 11:33 PM <DIR> .groovy
03/26/2021 09:51 PM <DIR> .hawtjni
06/19/2020 02:11 PM <DIR> .IntelliJIdea2019.2
04/26/2021 04:18 PM <DIR> .ipython
04/07/2021 07:24 PM <DIR> .jenkins
12/07/2020 09:26 PM <DIR> .jmc
04/26/2021 04:17 PM <DIR> .jupyter
03/13/2021 07:51 PM <DIR> .kube
09/15/2020 12:20 PM <DIR> .lemminx
04/14/2020 06:14 PM <DIR> .m2
04/23/2020 11:01 AM 37 .minttyrc
07/21/2020 12:18 PM 0 .mongorc.js
06/18/2020 08:58 PM <DIR> .nbi
06/18/2020 01:29 PM 4 .node_repl_history
06/07/2021 07:34 PM <DIR> .p2
05/07/2021 02:19 PM <DIR> .remain
06/04/2021 04:03 PM <DIR> .scalaide
08/10/2020 04:52 PM 11 .scala_history
06/14/2021 01:26 AM <DIR> .ssh
08/02/2020 06:06 PM <DIR> .sts4
08/22/2020 07:21 PM <DIR> .swt
04/16/2021 06:46 PM <DIR> .tmp
02/14/2020 10:58 PM <DIR> .tooling
04/16/2021 02:20 PM <DIR> .VirtualBox
04/12/2020 10:25 PM <DIR> .vscode
06/26/2020 11:00 AM 32 .vuerc
03/13/2021 03:30 PM <DIR> .webclipse
06/20/2020 11:17 AM <DIR> .WebStorm2019.3
06/07/2021 04:22 PM 0 .xdm-global-lock
06/06/2020 11:46 AM <DIR> .xdman
03/11/2021 10:02 PM <DIR> 3D Objects
04/11/2021 10:14 PM <DIR> caches
03/11/2021 10:02 PM <DIR> Contacts
04/11/2021 10:14 PM <DIR> daemon
05/12/2021 08:41 PM <DIR> Desktop
06/13/2021 10:35 PM <DIR> Documents
06/12/2021 04:18 PM <DIR> Downloads
03/11/2021 10:02 PM <DIR> Favorites
04/01/2021 11:58 PM <DIR> go
08/02/2020 05:20 PM <DIR> hsperfdata_atlantis
08/06/2020 08:30 PM <DIR> IBM
02/14/2020 05:14 PM <DIR> Intel
07/16/2020 07:23 PM 52,192 java_error_in_idea_6696.log
06/24/2020 11:01 AM 68,569 java_error_in_webstorm_17796.log
04/11/2021 10:17 PM <DIR> jdks
03/11/2021 10:02 PM <DIR> Links
07/23/2020 01:35 PM 1,180 mongo.sql
03/11/2021 10:02 PM <DIR> Music
04/11/2021 10:13 PM <DIR> native
09/04/2020 05:57 PM <DIR> OneDrive
06/30/2020 12:05 PM <DIR> opera autoupdate
06/08/2021 04:32 PM <DIR> Pictures
02/14/2020 05:27 PM <DIR> Roaming
03/11/2021 10:02 PM <DIR> Saved Games
07/13/2020 11:28 AM <DIR> sdk
03/11/2021 10:02 PM <DIR> Searches
03/11/2021 10:02 PM <DIR> Videos
06/15/2020 07:20 PM 144 webstorm.txt
17 File(s) 174,037 bytes
63 Dir(s) 36,056,952,832 bytes free
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论