mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-09 00:18:39 +03:00
reduce reliance on implicit channel close; add close() method to SFTP classes; update examples
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
import net.schmizz.sshj.SSHClient;
|
import net.schmizz.sshj.SSHClient;
|
||||||
|
import net.schmizz.sshj.connection.channel.direct.Session;
|
||||||
import net.schmizz.sshj.connection.channel.direct.Session.Command;
|
import net.schmizz.sshj.connection.channel.direct.Session.Command;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -25,18 +26,20 @@ public class Exec {
|
|||||||
|
|
||||||
public static void main(String... args)
|
public static void main(String... args)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
SSHClient ssh = new SSHClient();
|
final SSHClient ssh = new SSHClient();
|
||||||
ssh.loadKnownHosts();
|
ssh.loadKnownHosts();
|
||||||
|
|
||||||
ssh.connect("localhost");
|
ssh.connect("localhost");
|
||||||
try {
|
try {
|
||||||
|
|
||||||
ssh.authPublickey(System.getProperty("user.name"));
|
ssh.authPublickey(System.getProperty("user.name"));
|
||||||
|
final Session session = ssh.startSession();
|
||||||
Command cmd = ssh.startSession().exec("ping -c 1 google.com");
|
try {
|
||||||
|
final Command cmd = session.exec("ping -c 1 google.com");
|
||||||
System.out.print(cmd.getOutputAsString());
|
System.out.print(cmd.getOutputAsString());
|
||||||
System.out.println("\n** exit status: " + cmd.getExitStatus());
|
System.out.println("\n** exit status: " + cmd.getExitStatus());
|
||||||
|
} finally {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
ssh.disconnect();
|
ssh.disconnect();
|
||||||
|
|||||||
@@ -37,35 +37,35 @@ class RudimentaryPTY {
|
|||||||
ssh.addHostKeyVerifier(new ConsoleKnownHostsVerifier(khFile, System.console()));
|
ssh.addHostKeyVerifier(new ConsoleKnownHostsVerifier(khFile, System.console()));
|
||||||
|
|
||||||
ssh.connect("localhost");
|
ssh.connect("localhost");
|
||||||
|
|
||||||
Shell shell = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
ssh.authPublickey(System.getProperty("user.name"));
|
ssh.authPublickey(System.getProperty("user.name"));
|
||||||
|
|
||||||
final Session session = ssh.startSession();
|
final Session session = ssh.startSession();
|
||||||
session.allocateDefaultPTY();
|
try {
|
||||||
|
|
||||||
shell = session.startShell();
|
session.allocateDefaultPTY();
|
||||||
|
|
||||||
new StreamCopier("stdout", shell.getInputStream(), System.out)
|
final Shell shell = session.startShell();
|
||||||
.bufSize(shell.getLocalMaxPacketSize())
|
|
||||||
.start();
|
|
||||||
|
|
||||||
new StreamCopier("stderr", shell.getErrorStream(), System.err)
|
new StreamCopier("stdout", shell.getInputStream(), System.out)
|
||||||
.bufSize(shell.getLocalMaxPacketSize())
|
.bufSize(shell.getLocalMaxPacketSize())
|
||||||
.start();
|
.start();
|
||||||
|
|
||||||
// Now make System.in act as stdin. To exit, hit Ctrl+D (since that results in an EOF on System.in)
|
new StreamCopier("stderr", shell.getErrorStream(), System.err)
|
||||||
// This is kinda messy because java only allows console input after you hit return
|
.bufSize(shell.getLocalMaxPacketSize())
|
||||||
// But this is just an example... a GUI app could implement a proper PTY
|
.start();
|
||||||
StreamCopier.copy(System.in, shell.getOutputStream(), shell.getRemoteMaxPacketSize(), true);
|
|
||||||
|
// Now make System.in act as stdin. To exit, hit Ctrl+D (since that results in an EOF on System.in)
|
||||||
|
// This is kinda messy because java only allows console input after you hit return
|
||||||
|
// But this is just an example... a GUI app could implement a proper PTY
|
||||||
|
StreamCopier.copy(System.in, shell.getOutputStream(), shell.getRemoteMaxPacketSize(), true);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|
||||||
if (shell != null)
|
|
||||||
shell.close();
|
|
||||||
ssh.disconnect();
|
ssh.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
import net.schmizz.sshj.SSHClient;
|
import net.schmizz.sshj.SSHClient;
|
||||||
|
import net.schmizz.sshj.sftp.SFTPClient;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -24,14 +25,19 @@ public class SFTPDownload {
|
|||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
SSHClient ssh = new SSHClient();
|
final SSHClient ssh = new SSHClient();
|
||||||
ssh.loadKnownHosts();
|
ssh.loadKnownHosts();
|
||||||
ssh.connect("localhost");
|
ssh.connect("localhost");
|
||||||
try {
|
try {
|
||||||
ssh.authPublickey(System.getProperty("user.name"));
|
ssh.authPublickey(System.getProperty("user.name"));
|
||||||
final String src = "test_file";
|
final String src = "test_file";
|
||||||
final String target = "/tmp/";
|
final String target = "/tmp/";
|
||||||
ssh.newSFTPClient().get(src, target);
|
final SFTPClient sftp = ssh.newSFTPClient();
|
||||||
|
try {
|
||||||
|
sftp.get(src, target);
|
||||||
|
} finally {
|
||||||
|
sftp.close();
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
ssh.disconnect();
|
ssh.disconnect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package examples;
|
package examples;
|
||||||
|
|
||||||
import net.schmizz.sshj.SSHClient;
|
import net.schmizz.sshj.SSHClient;
|
||||||
|
import net.schmizz.sshj.sftp.SFTPClient;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -25,14 +26,19 @@ public class SFTPUpload {
|
|||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
SSHClient ssh = new SSHClient();
|
final SSHClient ssh = new SSHClient();
|
||||||
ssh.loadKnownHosts();
|
ssh.loadKnownHosts();
|
||||||
ssh.connect("localhost");
|
ssh.connect("localhost");
|
||||||
try {
|
try {
|
||||||
ssh.authPublickey(System.getProperty("user.name"));
|
ssh.authPublickey(System.getProperty("user.name"));
|
||||||
final String src = System.getProperty("user.home") + File.separator + "test_file";
|
final String src = System.getProperty("user.home") + File.separator + "test_file";
|
||||||
final String target = "/tmp/";
|
final String target = "/tmp/";
|
||||||
ssh.newSFTPClient().put(src, target);
|
final SFTPClient sftp = ssh.newSFTPClient();
|
||||||
|
try {
|
||||||
|
sftp.put(src, target);
|
||||||
|
} finally {
|
||||||
|
sftp.close();
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
ssh.disconnect();
|
ssh.disconnect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class X11 {
|
|||||||
|
|
||||||
public static void main(String... args)
|
public static void main(String... args)
|
||||||
throws IOException, InterruptedException {
|
throws IOException, InterruptedException {
|
||||||
SSHClient ssh = new SSHClient();
|
final SSHClient ssh = new SSHClient();
|
||||||
|
|
||||||
// Compression makes X11 more feasible over slower connections
|
// Compression makes X11 more feasible over slower connections
|
||||||
// ssh.useCompression();
|
// ssh.useCompression();
|
||||||
@@ -55,7 +55,7 @@ public class X11 {
|
|||||||
*/
|
*/
|
||||||
sess.reqX11Forwarding("MIT-MAGIC-COOKIE-1", "b0956167c9ad8f34c8a2788878307dc9", 0);
|
sess.reqX11Forwarding("MIT-MAGIC-COOKIE-1", "b0956167c9ad8f34c8a2788878307dc9", 0);
|
||||||
|
|
||||||
Command cmd = sess.exec("/usr/X11/bin/xcalc");
|
final Command cmd = sess.exec("/usr/X11/bin/xcalc");
|
||||||
|
|
||||||
new StreamCopier("stdout", cmd.getInputStream(), System.out).start();
|
new StreamCopier("stdout", cmd.getInputStream(), System.out).start();
|
||||||
new StreamCopier("stderr", cmd.getErrorStream(), System.err).start();
|
new StreamCopier("stderr", cmd.getErrorStream(), System.err).start();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener;
|
|||||||
import net.schmizz.sshj.transport.Transport;
|
import net.schmizz.sshj.transport.Transport;
|
||||||
import net.schmizz.sshj.transport.TransportException;
|
import net.schmizz.sshj.transport.TransportException;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
@@ -248,9 +249,9 @@ public class ConnectionImpl
|
|||||||
public void notifyDisconnect()
|
public void notifyDisconnect()
|
||||||
throws SSHException {
|
throws SSHException {
|
||||||
super.notifyDisconnect();
|
super.notifyDisconnect();
|
||||||
FutureUtils.alertAll(new ConnectionException("Disconnected."), globalReqFutures);
|
final ConnectionException ex = new ConnectionException("Disconnected.");
|
||||||
for (Channel chan : channels.values())
|
FutureUtils.alertAll(ex, globalReqFutures);
|
||||||
chan.finishOff();
|
ErrorNotifiable.Util.alertAll(ex, new HashSet<Channel>(channels.values()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -302,8 +302,7 @@ public abstract class AbstractChannel
|
|||||||
rwin.expand(howMuch);
|
rwin.expand(howMuch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void finishOff() {
|
||||||
public void finishOff() {
|
|
||||||
conn.forget(this);
|
conn.forget(this);
|
||||||
close.set();
|
close.set();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,9 +117,6 @@ public interface Channel
|
|||||||
/** @return whether the channel is open. */
|
/** @return whether the channel is open. */
|
||||||
boolean isOpen();
|
boolean isOpen();
|
||||||
|
|
||||||
/** Called when this channel's end-of-life has been reached. Subclasses may override but must call super. */
|
|
||||||
void finishOff();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an EOF message to the server for this channel; indicating that no more data will be sent by us. The {@code
|
* Sends an EOF message to the server for this channel; indicating that no more data will be sent by us. The {@code
|
||||||
* OutputStream} for this channel will be closed and no longer usable.
|
* OutputStream} for this channel will be closed and no longer usable.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import net.schmizz.sshj.xfer.FilePermission;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
@@ -27,7 +28,8 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class SFTPClient {
|
public class SFTPClient
|
||||||
|
implements Closeable {
|
||||||
|
|
||||||
/** Logger */
|
/** Logger */
|
||||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
@@ -238,4 +240,10 @@ public class SFTPClient {
|
|||||||
xfer.upload(source, dest);
|
xfer.upload(source, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
throws IOException {
|
||||||
|
sftp.close();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import net.schmizz.sshj.connection.channel.direct.SessionFactory;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
@@ -30,7 +31,7 @@ import java.util.Set;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class SFTPEngine
|
public class SFTPEngine
|
||||||
implements Requester {
|
implements Requester, Closeable {
|
||||||
|
|
||||||
/** Logger */
|
/** Logger */
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
@@ -233,4 +234,10 @@ public class SFTPEngine
|
|||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
throws IOException {
|
||||||
|
sub.close();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,8 +421,8 @@ public final class TransportImpl
|
|||||||
.putInt(reason.toInt())
|
.putInt(reason.toInt())
|
||||||
.putString(message)
|
.putString(message)
|
||||||
.putString(""));
|
.putString(""));
|
||||||
} catch (IOException logged) {
|
} catch (IOException worthless) {
|
||||||
log.warn("Error writing packet: {}", logged);
|
log.debug("Error writing packet: {}", worthless.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user