Java용 SSH 라이브러리
Java를 사용한SSH 라이브러리 접속의 예를 알고 있는 사람이 있습니까?
Java Secure Channel(JSCH)은 메이븐, 개미 및 이클립스가 사용하는 매우 인기 있는 라이브러리입니다.BSD 스타일의 라이선스를 가진 오픈소스입니다
업데이트: GSOC 프로젝트와 코드는 활성화되지 않았습니다.단, 다음 URL은 https://github.com/hierynomus/sshj 입니다.
히에리노무스는 2015년 초부터 관리직을 이어받았다.다음은 더 이상 유지보수가 되지 않는 오래된 Github 링크입니다.
https://github.com/shikhar/sshj
GSOC 프로젝트가 있었습니다.
http://code.google.com/p/commons-net-ssh/
코드 품질은 JSch보다 나은 것 같습니다.JSch는 완전하고 동작하고 있지만 문서화가 되어 있지 않습니다.프로젝트 페이지에 베타 릴리스가 예정되어 있으며, 저장소에 대한 마지막 약속은 8월 중순이었습니다.
API 비교:
http://code.google.com/p/commons-net-ssh/
SSHClient ssh = new SSHClient();
//ssh.useCompression();
ssh.loadKnownHosts();
ssh.connect("localhost");
try {
ssh.authPublickey(System.getProperty("user.name"));
new SCPDownloadClient(ssh).copy("ten", "/tmp");
} finally {
ssh.disconnect();
}
Session session = null;
Channel channel = null;
try {
JSch jsch = new JSch();
session = jsch.getSession(username, host, 22);
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
session.connect();
// exec 'scp -f rfile' remotely
String command = "scp -f " + remoteFilename;
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
// get I/O streams for remote scp
OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream();
channel.connect();
byte[] buf = new byte[1024];
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
while (true) {
int c = checkAck(in);
if (c != 'C') {
break;
}
// read '0644 '
in.read(buf, 0, 5);
long filesize = 0L;
while (true) {
if (in.read(buf, 0, 1) < 0) {
// error
break;
}
if (buf[0] == ' ') {
break;
}
filesize = filesize * 10L + (long) (buf[0] - '0');
}
String file = null;
for (int i = 0;; i++) {
in.read(buf, i, 1);
if (buf[i] == (byte) 0x0a) {
file = new String(buf, 0, i);
break;
}
}
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
// read a content of lfile
FileOutputStream fos = null;
fos = new FileOutputStream(localFilename);
int foo;
while (true) {
if (buf.length < filesize) {
foo = buf.length;
} else {
foo = (int) filesize;
}
foo = in.read(buf, 0, foo);
if (foo < 0) {
// error
break;
}
fos.write(buf, 0, foo);
filesize -= foo;
if (filesize == 0L) {
break;
}
}
fos.close();
fos = null;
if (checkAck(in) != 0) {
System.exit(0);
}
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
channel.disconnect();
session.disconnect();
}
} catch (JSchException jsche) {
System.err.println(jsche.getLocalizedMessage());
} catch (IOException ioe) {
System.err.println(ioe.getLocalizedMessage());
} finally {
channel.disconnect();
session.disconnect();
}
}
방금 sshj를 발견했는데, JSCH보다 훨씬 간결한 API를 가지고 있는 것 같습니다(Java 6이 필요합니다).이 문서에는 주로 레포에 관한 예가 포함되어 있습니다.보통 이 문서만으로 충분합니다만, 이제 막 시작한 프로젝트에 도전해 볼 수 있을 것 같습니다.
Apache MINA 프로젝트를 기반으로 한 최근 출시된 SSHD를 살펴보십시오.
github에는 Jsch up의 새로운 버전이 있습니다.https://github.com/vngx/vngx-jsch 에는 포괄적인 javadoc, 퍼포먼스 향상, 예외 처리 향상, RFC 사양 준수 향상 등이 있습니다.어떤 방법으로든 기여하고 싶은 경우 이슈를 열거나 풀 요청을 보내 주십시오.
나는 miku의 답변과 jsch 예제 코드를 가져갔다.그 후 세션 중에 여러 파일을 다운로드하여 원래 타임스탬프를 보존해야 했습니다.이것이 제 예시 코드입니다.많은 사람들이 유용하다고 생각할 것입니다.filename Hack() 함수는 저만의 사용 사례를 무시해 주세요.
package examples;
import com.jcraft.jsch.*;
import java.io.*;
import java.util.*;
public class ScpFrom2 {
public static void main(String[] args) throws Exception {
Map<String,String> params = parseParams(args);
if (params.isEmpty()) {
System.err.println("usage: java ScpFrom2 "
+ " user=myid password=mypwd"
+ " host=myhost.com port=22"
+ " encoding=<ISO-8859-1,UTF-8,...>"
+ " \"remotefile1=/some/file.png\""
+ " \"localfile1=file.png\""
+ " \"remotefile2=/other/file.txt\""
+ " \"localfile2=file.txt\""
);
return;
}
// default values
if (params.get("port") == null)
params.put("port", "22");
if (params.get("encoding") == null)
params.put("encoding", "ISO-8859-1"); //"UTF-8"
Session session = null;
try {
JSch jsch=new JSch();
session=jsch.getSession(
params.get("user"), // myuserid
params.get("host"), // my.server.com
Integer.parseInt(params.get("port")) // 22
);
session.setPassword( params.get("password") );
session.setConfig("StrictHostKeyChecking", "no"); // do not prompt for server signature
session.connect();
// this is exec command and string reply encoding
String encoding = params.get("encoding");
int fileIdx=0;
while(true) {
fileIdx++;
String remoteFile = params.get("remotefile"+fileIdx);
String localFile = params.get("localfile"+fileIdx);
if (remoteFile == null || remoteFile.equals("")
|| localFile == null || localFile.equals("") )
break;
remoteFile = filenameHack(remoteFile);
localFile = filenameHack(localFile);
try {
downloadFile(session, remoteFile, localFile, encoding);
} catch (Exception ex) {
ex.printStackTrace();
}
}
} catch(Exception ex) {
ex.printStackTrace();
} finally {
try{ session.disconnect(); } catch(Exception ex){}
}
}
private static void downloadFile(Session session,
String remoteFile, String localFile, String encoding) throws Exception {
// send exec command: scp -p -f "/some/file.png"
// -p = read file timestamps
// -f = From remote to local
String command = String.format("scp -p -f \"%s\"", remoteFile);
System.console().printf("send command: %s%n", command);
Channel channel=session.openChannel("exec");
((ChannelExec)channel).setCommand(command.getBytes(encoding));
// get I/O streams for remote scp
byte[] buf=new byte[32*1024];
OutputStream out=channel.getOutputStream();
InputStream in=channel.getInputStream();
channel.connect();
buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'
// reply: T<mtime> 0 <atime> 0\n
// times are in seconds, since 1970-01-01 00:00:00 UTC
int c=checkAck(in);
if(c!='T')
throw new IOException("Invalid timestamp reply from server");
long tsModified = -1; // millis
for(int idx=0; ; idx++){
in.read(buf, idx, 1);
if(tsModified < 0 && buf[idx]==' ') {
tsModified = Long.parseLong(new String(buf, 0, idx))*1000;
} else if(buf[idx]=='\n') {
break;
}
}
buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'
// reply: C0644 <binary length> <filename>\n
// length is given as a text "621873" bytes
c=checkAck(in);
if(c!='C')
throw new IOException("Invalid filename reply from server");
in.read(buf, 0, 5); // read '0644 ' bytes
long filesize=-1;
for(int idx=0; ; idx++){
in.read(buf, idx, 1);
if(buf[idx]==' ') {
filesize = Long.parseLong(new String(buf, 0, idx));
break;
}
}
// read remote filename
String origFilename=null;
for(int idx=0; ; idx++){
in.read(buf, idx, 1);
if(buf[idx]=='\n') {
origFilename=new String(buf, 0, idx, encoding); // UTF-8, ISO-8859-1
break;
}
}
System.console().printf("size=%d, modified=%d, filename=%s%n"
, filesize, tsModified, origFilename);
buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'
// read binary data, write to local file
FileOutputStream fos = null;
try {
File file = new File(localFile);
fos = new FileOutputStream(file);
while(filesize > 0) {
int read = Math.min(buf.length, (int)filesize);
read=in.read(buf, 0, read);
if(read < 0)
throw new IOException("Reading data failed");
fos.write(buf, 0, read);
filesize -= read;
}
fos.close(); // we must close file before updating timestamp
fos = null;
if (tsModified > 0)
file.setLastModified(tsModified);
} finally {
try{ if (fos!=null) fos.close(); } catch(Exception ex){}
}
if(checkAck(in) != 0)
return;
buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'
System.out.println("Binary data read");
}
private static int checkAck(InputStream in) throws IOException {
// b may be 0 for success
// 1 for error,
// 2 for fatal error,
// -1
int b=in.read();
if(b==0) return b;
else if(b==-1) return b;
if(b==1 || b==2) {
StringBuilder sb=new StringBuilder();
int c;
do {
c=in.read();
sb.append((char)c);
} while(c!='\n');
throw new IOException(sb.toString());
}
return b;
}
/**
* Parse key=value pairs to hashmap.
* @param args
* @return
*/
private static Map<String,String> parseParams(String[] args) throws Exception {
Map<String,String> params = new HashMap<String,String>();
for(String keyval : args) {
int idx = keyval.indexOf('=');
params.put(
keyval.substring(0, idx),
keyval.substring(idx+1)
);
}
return params;
}
private static String filenameHack(String filename) {
// It's difficult reliably pass unicode input parameters
// from Java dos command line.
// This dirty hack is my very own test use case.
if (filename.contains("${filename1}"))
filename = filename.replace("${filename1}", "Korilla ABC ÅÄÖ.txt");
else if (filename.contains("${filename2}"))
filename = filename.replace("${filename2}", "test2 ABC ÅÄÖ.txt");
return filename;
}
}
http://code.google.com/p/connectbot/, Windows Linux 또는 Android 상에서 src\com\trilead\triv2를 컴파일합니다.로컬 포트 포워더를 작성하거나 다이내믹 포트 포워더를 작성할 수 있습니다.
언급URL : https://stackoverflow.com/questions/995944/ssh-library-for-java
'source' 카테고리의 다른 글
MySQL의 기본 조합이 latin1_swedish_ci인 이유는 무엇입니까? (0) | 2022.11.19 |
---|---|
PHP 오류: "참조 기준으로 매개 변수 2를 전달할 수 없습니다." (0) | 2022.11.19 |
JavaScript 객체에 동적으로 명명된 속성을 추가할 수 있습니까? (0) | 2022.11.19 |
PHP Try Catch 블록에 예외 발생 (0) | 2022.11.19 |
Eclipse에서 조건부 중단점을 사용하는 방법은 무엇입니까? (0) | 2022.11.18 |