sshjを試してみた
javaで作られているsshクライアントであるsshjを試してみました
https://github.com/hierynomus/sshj/blob/master/examples/src/main/java/net/schmizz/sshj/examples/LocalPF.java
単純にssh経由でコマンドを実行するだけでなくsshプロトコルを利用しているscpやsftpも利用できて、シンプルなターミナルも作れるので作業の自動化に役に立ちそうな気がします。
サンプルも簡単に動かすことができました。
https://github.com/hierynomus/sshj/tree/master/examples/src/main/java/net/schmizz/sshj/examples
ssh接続設定
private SSHClient sshConnectSetting(String host, String username, String password) throws IOException { SSHClient ssh = new SSHClient(); ssh.loadKnownHosts(); ssh.connect(host); // keepAliveの感覚設定 ssh.getConnection().getKeepAlive().setKeepAliveInterval(5); // 接続時のsshキーの指定はauthPublickeyを認証時のパスワードにはauthPasswordを使う // ssh.authPublickey(keyPath); ssh.authPassword(username,password); return ssh; }
ssh接続キーの指定にはSSHClientのauthPublickeyメソッッドを使います。認証時のパスワードが必要な場合はauthPasswordを呼び出します。
コマンド実行
public void sshjSample() throws IOException { final SSHClient ssh = sshConnectSetting("***", "***", "***"); try { // コマンド実行 sessionCommand(ssh.startSession(), "echo 'hello sshj' >> hello_sshj.txt", 5); } finally { ssh.disconnect(); } } private void sessionCommand(Session session, String command, int timeout) throws IOException { try { final Session.Command cmd = session.exec(command); System.out.println(IOUtils.readFully(cmd.getInputStream()).toString()); cmd.join(timeout, TimeUnit.SECONDS); System.out.println("\n** exit status: " + cmd.getExitStatus()); } finally { session.close(); } }
scp
private void scpDownloadSample(SSHClient ssh, String downloadFilePath, String saveFileDir) throws IOException{ ssh.newSCPFileTransfer().download(downloadFilePath, new FileSystemFile(saveFileDir)); } private void scpUpload(SSHClient ssh, FileSystemFile uploadFile, String uploadPath) throws IOException{ ssh.newSCPFileTransfer().upload(uploadFile, uploadPath); }
sftp
private void sftpUploadSample(SSHClient ssh, FileSystemFile uploadFile, String uploadDir) throws IOException{ final SFTPClient sftp = ssh.newSFTPClient(); try { sftp.put(uploadFile, uploadDir); } finally { sftp.close(); } } private void sftpUploadSample(SSHClient ssh, String downloadFilePath, String saveFileDir) throws IOException{ final SFTPClient sftp = ssh.newSFTPClient(); try { sftp.get(downloadFilePath, new FileSystemFile(saveFileDir)); } finally { sftp.close(); } }
ローカルポートフォワード
private void localPortFowardSample(SSHClient ssh, String localHost, int localPort, String remoteHost, int remotePort) throws IOException{ final LocalPortForwarder.Parameters params = new LocalPortForwarder.Parameters(localHost, localPort, remoteHost, remotePort); final ServerSocket ss = new ServerSocket(); ss.setReuseAddress(true); ss.bind(new InetSocketAddress(params.getLocalHost(), params.getLocalPort())); try { ssh.newLocalPortForwarder(params, ss).listen(); } finally { ss.close(); } }
リモートポートフォワード
private void remotePortFowardSample(SSHClient ssh, String remoteHost, int remotePort) throws IOException{ try { ssh.getRemotePortForwarder().bind( new RemotePortForwarder.Forward(remotePort), new SocketForwardingConnectListener(new InetSocketAddress(remoteHost, remotePort))); ssh.getTransport().setHeartbeatInterval(30); // Something to hang on to so that the forwarding stays ssh.getTransport().join(); }catch (IOException e){ e.printStackTrace(); } }
ターミナル
private void samplePTY(String host, String username, String password) throws IOException{ final SSHClient ssh = new SSHClient(); final File khFile = new File(OpenSSHKnownHosts.detectSSHDir(), "known_hosts"); ssh.addHostKeyVerifier(new ConsoleKnownHostsVerifier(khFile, System.console())); ssh.connect(host); ssh.authPassword(username,password); try { // ssh.authPublickey(System.getProperty("user.name")); final Session session = ssh.startSession(); try { session.allocateDefaultPTY(); final Session.Shell shell = session.startShell(); new StreamCopier(shell.getInputStream(), System.out, LoggerFactory.DEFAULT) .bufSize(shell.getLocalMaxPacketSize()) .spawn("stdout"); new StreamCopier(shell.getErrorStream(), System.err, LoggerFactory.DEFAULT) .bufSize(shell.getLocalMaxPacketSize()) .spawn("stderr"); // 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 new StreamCopier(System.in, shell.getOutputStream(), LoggerFactory.DEFAULT) .bufSize(shell.getRemoteMaxPacketSize()) .copy(); } finally { session.close(); } } finally { ssh.disconnect(); } }