Quelle est la meilleure méthode pour effectuer un transfert scp via le langage de programmation Java? Il semble que je puisse être en mesure de le faire via JSSE, JSch ou les bibliothèques Java _ du château gonflable. Aucune de ces solutions ne semble avoir de réponse facile.
J'ai fini par utiliser Jsch - c'était assez simple et semblait évoluer assez bien (je saisissais quelques milliers de fichiers toutes les quelques minutes).
plug: sshj est le seul choix sensé! Consultez ces exemples pour commencer: téléchargement , téléchargement .
Jetez un oeil ici
C'est le code source de la tâche SCP des fourmis. Le code de la méthode "execute" est l'endroit où se trouvent ses écrous et ses boulons. Cela devrait vous donner une idée juste de ce qui est requis. Il utilise JSch je crois.
Alternativement, vous pouvez également exécuter directement cette tâche Ant à partir de votre code Java.
J'ai enveloppé Jsch avec quelques méthodes utilitaires pour le rendre un peu plus convivial et l'ai appelé
Disponible ici: https://github.com/willwarren/jscp
Utilitaire SCP pour tarer un dossier, le zipper et le scp quelque part, puis le décompresser.
Usage:
// 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")
);
Comprend également des classes utiles - Scp et Exec, et un TarAndGzip, qui fonctionnent à peu près de la même manière.
C'est une solution de haut niveau , pas besoin de réinventer. Rapide et sale!
1) Tout d'abord, allez sur http://ant.Apache.org/bindownload.cgi et téléchargez le dernier binaire Apache Ant . (de nos jours, Apache-ant-1.9.4-bin.Zip).
2) Extraire le fichier téléchargé et trouver le JAR ant-jsch.jar ("Apache-ant-1.9.4/lib/ant-jsch.jar"). Ajoutez ce JAR dans votre projet . Aussi ant-launcher.jar et ant.jar.
3) Allez dans Projet Jcraft jsch SouceForge et téléchargez le bocal. De nos jours, jsch-0.1.52.jar . Aussi Ajoutez ce JAR dans votre projet .
Maintenant, pouvez-vous facilement utiliser dans Java codez les classes Ant Scp pour copier des fichiers sur le réseau ou SSHExec pour les commandes dans les serveurs SSH.
4) Exemple de code 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();
Le projet openssh répertorie plusieurs Java, Trilead SSH pour Java semble correspondre à ce que vous demandez.
J'ai regardé beaucoup de ces solutions et n'en ai pas aimé beaucoup. Principalement parce que l'étape ennuyeuse de devoir identifier vos hôtes connus. Cela et JSCH est à un niveau ridiculement bas par rapport à la commande scp.
J'ai trouvé une bibliothèque qui n'en a pas besoin, mais elle est regroupée et utilisée comme outil de ligne de commande. https://code.google.com/p/scp-Java-client/
J'ai parcouru le code source et découvert comment l'utiliser sans la ligne de commande. Voici un exemple de téléchargement:
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();
Le plus gros inconvénient est que ce n'est pas dans un repo Maven (que j'ai pu trouver). Mais, la facilité d'utilisation en vaut la peine pour moi.
J'utilise cette API SFTP qui a SCP appelé Zehon, c'est génial, si facile à utiliser avec beaucoup d'exemples de code. Voici le site http://www.zehon.com
Comme certains ici, j'ai fini par écrire un wrapper autour de la bibliothèque JSch.
Cela s'appelle way-secshell et il est hébergé sur 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 est une bibliothèque agréable à utiliser. Il a une réponse assez simple à votre question.
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);
}
}
Vous pouvez trouver le code complet sur
http://faisalbhagat.blogspot.com/2013/09/Java-uploading-file-remotely-via-scp.html
Voici un exemple pour télécharger un fichier en utilisant 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();
}
}
J'ai écrit un serveur scp qui est beaucoup plus facile que les autres. J'utilise le projet Apache MINA (Apache SSHD) pour le développer. Vous pouvez jeter un œil ici: https://github.com/boomz/JSCP Vous pouvez également télécharger le fichier jar depuis /jar
répertoire. Comment utiliser? Jetez un œil sur: https://github.com/boomz/JSCP/blob/master/src/Main.Java
jsCH a très bien fonctionné pour moi. Voici un exemple d'une méthode qui se connectera au serveur sftp et téléchargera les fichiers dans le répertoire spécifié. Il est recommandé de ne pas désactiver StrictHostKeyChecking. Bien qu'un peu plus difficile à configurer, pour des raisons de sécurité, la spécification des hôtes connus devrait être la norme.
jsch.setKnownHosts ("C:\Users\test\known_hosts"); recommandé
JSch.setConfig ("StrictHostKeyChecking", "no"); - non recommandé
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();
}
}
}
J'ai besoin de copier le dossier de manière récursive, après avoir essayé différentes solutions, pour finir par ProcessBuilder + expect/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();
}