Jaka jest najlepsza metoda wykonania transferu scp za pomocą języka programowania Java? Wygląda na to, że mogę to zrobić za pomocą JSSE, JSch lub bibliotek Java Bouncy Castle. Żadne z tych rozwiązań nie wydaje się mieć łatwej odpowiedzi.
Jaka jest najlepsza metoda wykonania transferu scp za pomocą języka programowania Java? Wygląda na to, że mogę to zrobić za pomocą JSSE, JSch lub bibliotek Java Bouncy Castle. Żadne z tych rozwiązań nie wydaje się mieć łatwej odpowiedzi.
Odpowiedzi:
Skończyło się na tym, że korzystałem z Jsch - było to całkiem proste i wydawało się, że skalowałem się całkiem nieźle ( łapałem kilka tysięcy plików co kilka minut).
wtyczka: sshj to jedyny rozsądny wybór! Aby rozpocząć, zobacz poniższe przykłady: pobieranie , przesyłanie .
Spójrz tutaj
To jest kod źródłowy zadania SCP Antsa. Kod w metodzie „wykonaj” to miejsce, w którym znajdują się jej nakrętki i śruby. To powinno dać ci rzetelny obraz tego, co jest wymagane. Wydaje mi się, że używa JSch.
Alternatywnie możesz również wykonać to zadanie Ant bezpośrednio z kodu Java.
Opakowałem Jsch kilkoma narzędziami, aby uczynić go nieco bardziej przyjaznym i nazwałem go
Dostępne tutaj: https://github.com/willwarren/jscp
Narzędzie SCP do tarowania folderu, spakowania go i scpowania gdzieś, a następnie rozpakowania.
Stosowanie:
// create secure context
SecureContext context = new SecureContext("userName", "localhost");
// set optional security configurations.
context.setTrustAllHosts(true);
context.setPrivateKeyFile(new File("private/key"));
// Console requires JDK 1.7
// System.out.println("enter password:");
// context.setPassword(System.console().readPassword());
Jscp.exec(context,
"src/dir",
"destination/path",
// regex ignore list
Arrays.asList("logs/log[0-9]*.txt",
"backups")
);
Zawiera również przydatne klasy - Scp i Exec oraz TarAndGzip, które działają w podobny sposób.
Jest to rozwiązanie wysokopoziomowe , nie trzeba odkrywać na nowo. Szybko i brudno!
1) Najpierw przejdź do http://ant.apache.org/bindownload.cgi i pobierz najnowszy plik binarny Apache Ant. (obecnie apache-ant-1.9.4-bin.zip).
2) Wypakuj pobrany plik i znajdź JAR ant-jsch.jar („apache-ant-1.9.4 / lib / ant-jsch.jar”). Dodaj ten plik JAR do swojego projektu . Również ant-launcher.jar i ant.jar.
3) Idź do Jcraft jsch SouceForge Project i pobierz jar. Obecnie jsch-0.1.52.jar . Dodaj również ten plik JAR do swojego projektu .
Teraz możesz łatwo użyć w kodzie java Ant Classes Scp do kopiowania plików przez sieć lub SSHExec do poleceń na serwerach SSH.
4) Przykładowy kod Scp:
// This make scp copy of
// one local file to remote dir
org.apache.tools.ant.taskdefs.optional.ssh.Scp scp = new Scp();
int portSSH = 22;
String srvrSSH = "ssh.your.domain";
String userSSH = "anyuser";
String pswdSSH = new String ( jPasswordField1.getPassword() );
String localFile = "C:\\localfile.txt";
String remoteDir = "/uploads/";
scp.setPort( portSSH );
scp.setLocalFile( localFile );
scp.setTodir( userSSH + ":" + pswdSSH + "@" + srvrSSH + ":" + remoteDir );
scp.setProject( new Project() );
scp.setTrust( true );
scp.execute();
Projekt openssh wymienia kilka alternatyw Javy, Trilead SSH dla Javy wydaje się pasować do tego, o co prosisz.
Używam tego SFTP API, które ma SCP o nazwie Zehon, jest świetne, tak łatwe w użyciu z dużą ilością przykładowego kodu. Oto witryna http://www.zehon.com
Spojrzałem na wiele z tych rozwiązań i wielu z nich nie lubiłem. Głównie dlatego, że irytujący krok polegający na konieczności identyfikacji znanych hostów. To i JSCH jest na absurdalnie niskim poziomie w stosunku do polecenia scp.
Znalazłem bibliotekę, która tego nie wymaga, ale jest spakowana i używana jako narzędzie wiersza poleceń. https://code.google.com/p/scp-java-client/
Przejrzałem kod źródłowy i odkryłem, jak go używać bez wiersza poleceń. Oto przykład przesyłania:
uk.co.marcoratto.scp.SCP scp = new uk.co.marcoratto.scp.SCP(new uk.co.marcoratto.scp.listeners.SCPListenerPrintStream());
scp.setUsername("root");
scp.setPassword("blah");
scp.setTrust(true);
scp.setFromUri(file.getAbsolutePath());
scp.setToUri("root@host:/path/on/remote");
scp.execute();
Największym minusem jest to, że nie ma go w repozytorium Maven (które mogłem znaleźć). Ale łatwość użycia jest dla mnie tego warta.
jsCH świetnie się dla mnie sprawdził. Poniżej znajduje się przykład metody, która połączy się z serwerem sftp i pobierze pliki do określonego katalogu. Zaleca się trzymanie się z daleka od wyłączania StrictHostKeyChecking. Chociaż konfiguracja jest nieco trudniejsza, ze względów bezpieczeństwa normą powinno być określenie znanych hostów.
jsch.setKnownHosts ("C: \ Users \ test \ known_hosts"); Zalecana
JSch.setConfig ("StrictHostKeyChecking", "nie"); - Niepolecane
import com.jcraft.jsch.*;
public void downloadFtp(String userName, String password, String host, int port, String path) {
Session session = null;
Channel channel = null;
try {
JSch ssh = new JSch();
JSch.setConfig("StrictHostKeyChecking", "no");
session = ssh.getSession(userName, host, port);
session.setPassword(password);
session.connect();
channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftp = (ChannelSftp) channel;
sftp.get(path, "specify path to where you want the files to be output");
} catch (JSchException e) {
System.out.println(userName);
e.printStackTrace();
} catch (SftpException e) {
System.out.println(userName);
e.printStackTrace();
} finally {
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
Tak jak niektórzy tutaj, napisałem otokę wokół biblioteki JSch.
Nazywa się way-secshell i jest hostowany na GitHub:
https://github.com/objectos/way-secshell
// scp myfile.txt localhost:/tmp
File file = new File("myfile.txt");
Scp res = WaySSH.scp()
.file(file)
.toHost("localhost")
.at("/tmp")
.send();
JSch to przyjemna biblioteka do pracy. Ma dość prostą odpowiedź na twoje pytanie.
JSch jsch=new JSch();
Session session=jsch.getSession(user, host, 22);
session.setPassword("password");
Properties config = new Properties();
config.put("StrictHostKeyChecking","no");
session.setConfig(config);
session.connect();
boolean ptimestamp = true;
// exec 'scp -t rfile' remotely
String command="scp " + (ptimestamp ? "-p" :"") +" -t "+rfile;
Channel 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();
if(checkAck(in)!=0){
System.exit(0);
}
File _lfile = new File(lfile);
if(ptimestamp){
command="T "+(_lfile.lastModified()/1000)+" 0";
// The access time should be sent here,
// but it is not accessible with JavaAPI ;-<
command+=(" "+(_lfile.lastModified()/1000)+" 0\n");
out.write(command.getBytes()); out.flush();
if(checkAck(in)!=0){
System.exit(0);
}
}
Pełny kod można znaleźć pod adresem
http://faisalbhagat.blogspot.com/2013/09/java-uploading-file-remotely-via-scp.html
Oto przykład przesyłania pliku za pomocą JSch :
ScpUploader.java
:
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import java.io.ByteArrayInputStream;
import java.util.Properties;
public final class ScpUploader
{
public static ScpUploader newInstance()
{
return new ScpUploader();
}
private volatile Session session;
private volatile ChannelSftp channel;
private ScpUploader(){}
public synchronized void connect(String host, int port, String username, String password) throws JSchException
{
JSch jsch = new JSch();
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session = jsch.getSession(username, host, port);
session.setPassword(password);
session.setConfig(config);
session.setInputStream(System.in);
session.connect();
channel = (ChannelSftp) session.openChannel("sftp");
channel.connect();
}
public synchronized void uploadFile(String directoryPath, String fileName, byte[] fileBytes, boolean overwrite) throws SftpException
{
if(session == null || channel == null)
{
System.err.println("No open session!");
return;
}
// a workaround to check if the directory exists. Otherwise, create it
channel.cd("/");
String[] directories = directoryPath.split("/");
for(String directory : directories)
{
if(directory.length() > 0)
{
try
{
channel.cd(directory);
}
catch(SftpException e)
{
// swallowed exception
System.out.println("The directory (" + directory + ") seems to be not exist. We will try to create it.");
try
{
channel.mkdir(directory);
channel.cd(directory);
System.out.println("The directory (" + directory + ") is created successfully!");
}
catch(SftpException e1)
{
System.err.println("The directory (" + directory + ") is failed to be created!");
e1.printStackTrace();
return;
}
}
}
}
channel.put(new ByteArrayInputStream(fileBytes), directoryPath + "/" + fileName, overwrite ? ChannelSftp.OVERWRITE : ChannelSftp.RESUME);
}
public synchronized void disconnect()
{
if(session == null || channel == null)
{
System.err.println("No open session!");
return;
}
channel.exit();
channel.disconnect();
session.disconnect();
channel = null;
session = null;
}
}
AppEntryPoint.java
:
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public final class AppEntryPoint
{
private static final String HOST = "192.168.1.1";
private static final int PORT = 22;
private static final String USERNAME = "root";
private static final String PASSWORD = "root";
public static void main(String[] args) throws IOException
{
ScpUploader scpUploader = ScpUploader.newInstance();
try
{
scpUploader.connect(HOST, PORT, USERNAME, PASSWORD);
}
catch(JSchException e)
{
System.err.println("Failed to connect the server!");
e.printStackTrace();
return;
}
System.out.println("Successfully connected to the server!");
byte[] fileBytes = Files.readAllBytes(Paths.get("C:/file.zip"));
try
{
scpUploader.uploadFile("/test/files", "file.zip", fileBytes, true); // if overwrite == false, it won't throw exception if the file exists
System.out.println("Successfully uploaded the file!");
}
catch(SftpException e)
{
System.err.println("Failed to upload the file!");
e.printStackTrace();
}
scpUploader.disconnect();
}
}
-: Trochę poprawiając odpowiedź Fernando, jeśli używasz Mavena do zarządzania zależnościami: -
pom.xml :
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-jsch</artifactId>
<version>${ant-jsch.version}</version>
</dependency>
Dodaj tę zależność w swoim projekcie. Najnowszą wersję można znaleźć tutaj .
Kod Java :
public void scpUpload(String source, String destination) {
Scp scp = new Scp();
scp.setPort(port);
scp.setLocalFile(source);
scp.setTodir(username + ":" + password + "@" + host + ":" + destination);
scp.setProject(new Project());
scp.setTrust(true);
scp.execute();
}
Napisałem serwer scp, który jest znacznie łatwiejszy niż inne. Do jej rozwijania używam projektu Apache MINA (Apache SSHD). Możesz zajrzeć tutaj: https://github.com/boomz/JSCP
Możesz również pobrać plik jar z /jar
katalogu. Jak używać? Spójrz na: https://github.com/boomz/JSCP/blob/master/src/Main.java
Muszę rekurencyjnie kopiować folder, po wypróbowaniu różnych rozwiązań, ostatecznie kończy się na ProcessBuilder + oczekiwanie / spawn
scpFile("192.168.1.1", "root","password","/tmp/1","/tmp");
public void scpFile(String host, String username, String password, String src, String dest) throws Exception {
String[] scpCmd = new String[]{"expect", "-c", String.format("spawn scp -r %s %s@%s:%s\n", src, username, host, dest) +
"expect \"?assword:\"\n" +
String.format("send \"%s\\r\"\n", password) +
"expect eof"};
ProcessBuilder pb = new ProcessBuilder(scpCmd);
System.out.println("Run shell command: " + Arrays.toString(scpCmd));
Process process = pb.start();
int errCode = process.waitFor();
System.out.println("Echo command executed, any errors? " + (errCode == 0 ? "No" : "Yes"));
System.out.println("Echo Output:\n" + output(process.getInputStream()));
if(errCode != 0) throw new Exception();
}