Connection SSH en Java avec protocole SCP
Bonjour,
Je vous explique tout d'abord mon projet :
Je possède un ordi composé de linux (mais sans interface graphique, ni rien, toutes les commandes à l'intérieur se font via WinSCP) et un ordi Windows.
J'aimerais créer une application Java qui ouvre un connexion SSH pour discuter avec cet ordi, faire deux trois lignes de commandes, transférez un fichier, et refaire deux trois lignes de commandes. Mais je suis perdu dans tout ça :aie::aie::aie:
J'ai télécharger la librairie Java JSch, qui permet d'ouvrir une connexion SSH mais j'ai l'impression que ça ne marche pas. Je dis bien j'ai l'impression, car je ne sais pas encore les commandes Java qui permettent de lire le contenu, ajouter ou en supprimer.
J'ai donc essayé plein de choses (ça fais deux jours que je cherche, mais j'arrive pas à avancer) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
| package fr.geekplayground.scp;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.lang.Exception;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
/**
* Cette classe permert de transférer via SCP un fichier vers une host distant utilisant
* le protocole SSH.
*
* @author Meher Abdellatif
*
*/
public class TransfertScp {
/**
* Dépose un fichier se trouvant en local sur une machine distante.
*
* @param sourceFile
* Chemin relatif du fichier en local
* @param destFile
* Chemin complet du fichier a déposer sur la machine cible
* @param host
* Machine cible
* @param user
* Nom d'utilisateur permettant de se conecter a la machine cible
* @param password
* Mot de passe permettant de se conecter a la machine cible
* @throws Exception exception
*/
public void scpTo(final String sourceFile, final String destFile,
final String host, final String user, final String password)
throws Exception {
FileInputStream fis = null;
try {
// Initialiser la librairie JSch
final JSch jsch = new JSch();
// Créer la session avec les données du host, user, et port utilisés
// pour l'authentification SSH
final Session session = jsch.getSession(user, host, 22);
// Paramètre nécessaire à la connection pour sauter la vérification
// de .ssh/known_hosts
final Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
// Affecter le mot de passe
session.setPassword(password);
// Connection !
session.connect();
// Exécution des commande de copie de fichier a distance
final boolean ptimestamp = true;
// exec 'scp -t rfile' remotely
String command = "scp " + (ptimestamp ? "-p" : "") + " -t "
+ destFile;
final Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
// get I/O streams for remote scp
final OutputStream out = channel.getOutputStream();
final InputStream in = channel.getInputStream();
channel.connect();
// Vérification par checksum que le fichier n'a pas été altéré au
// cours du transfert
if (checkAck(in) != 0) {
System.exit(0);
}
final File _lfile = new File(sourceFile);
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);
}
}
// send "C0644 filesize filename", where filename should not include
// '/'
final long filesize = _lfile.length();
command = "C0644 " + filesize + " ";
if (sourceFile.lastIndexOf('/') > 0) {
command += sourceFile
.substring(sourceFile.lastIndexOf('/') + 1);
} else {
command += sourceFile;
}
command += "\n";
out.write(command.getBytes());
out.flush();
if (checkAck(in) != 0) {
System.exit(0);
}
// send a content of lfile
fis = new FileInputStream(sourceFile);
final byte[] buf = new byte[1024];
while (true) {
final int len = fis.read(buf, 0, buf.length);
if (len <= 0)
break;
out.write(buf, 0, len); // out.flush();
}
fis.close();
fis = null;
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
if (checkAck(in) != 0) {
System.exit(0);
}
out.close();
channel.disconnect();
session.disconnect();
System.exit(0);
} catch (final Exception e) {
if (fis != null) {
try {
fis.close();
} catch (final IOException ee) {
// Déclencher une exception
throw new Exception(ee);
}
}
// Déclencher une exception
throw new Exception(e);
}
}
/**
* Permet la vérification par taille que le fichier envoyé n'a pas été
* altéré pendant son transfert.
*
* @param in
* fichier a vérifier
* @return entier : 0 = OK, 1 ou 2 = erreur
* @throws IOException
*/
private int checkAck(final InputStream in) throws IOException {
final int b = in.read();
// b may be 0 for success,
// 1 for error,
// 2 for fatal error,
// -1
if (b == 0)
return b;
if (b == -1)
return b;
if (b == 1 || b == 2) {
final StringBuffer sb = new StringBuffer();
int c;
do {
c = in.read();
sb.append((char) c);
} while (c != '\n');
if (b == 1) { // error
System.out.print(sb.toString());
}
if (b == 2) { // fatal error
System.out.print(sb.toString());
}
}
return b;
}
} |
J'ai trouvé ce code là, modifier à ce que je voulais, mais ne fonctionne pas car quand je veux lancer il me dis "Selectionnez une classe principale" et il y en a aucune.
J'ai aussi essayé de comprendre et utiliser les exemples fourni par JSch, mais je ne comprends pas tous les principes. J'ai trouvez ensuite cette solution :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| import com.jcraft.jsch.*;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
/**
* @author World
*/
public class SSHReadFile {
public static void main(String args[]) {
String user = "john";
String password = "mypassword";
String host = "192.168.100.23";
int port = 22;
String remoteFile = "/home/john/test.txt";
try {
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
System.out.println("Establishing Connection...");
session.connect();
System.out.println("Connection established.");
System.out.println("Crating SFTP Channel.");
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
System.out.println("SFTP Channel created.");
InputStream inputStream = sftpChannel.get(remoteFile);
try (Scanner scanner = new Scanner(new InputStreamReader(inputStream))) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
}
} catch (JSchException | SftpException e) {
e.printStackTrace();
}
}
} |
Cependant lorsque je test ce programme, voici le résultat de ma console :
Code:
1 2 3
| Etablishing connection...
Connection established.
Crating SFTP Channel. |
puis plus rien.. donc mon channel SFTP n'est pas créer.
Là je suis vraiment perdu, j'ai l'impression de ne pas bien comprendre ce que je fais, je vous demande donc de l'aide.
Merci d'avance.