# jsch copy ist das möglich



## Joob (7. Apr 2021)

Ich würde gerne mit jsch auf meinem Server kopieren.
Leider habe ich nur etwas gefunden wobei die Datei erst hochgeladen wird und dann wieder herunter.

Es gibt aber doch den Befehl setcommand
kann man da nicht direkt auf den Server den Befehl zum kopieren absetzen kann .

Berechtigungen liegen dabei bei dem gleichen ServerUser.


----------



## VfL_Freak (7. Apr 2021)

Hmm, eine konkrete Frage sehe ich jetzt nicht 🤔
und bitte was ist *jsch* ??


----------



## kneitzel (7. Apr 2021)

jsch ist eine SSH Library.

Aber die Frage verstehe ich nicht. "Auf den Server kopieren" bedeutet doch "hochladen". Also Gratulation: Du hast etwas gefunden, das dies macht.
Das herunter laden ist das "Vom Server auf den lokalen Rechner kopieren" - den Part brauchst Du also nicht.


----------



## temi (7. Apr 2021)

Es gibt mehrere Möglichkeiten des Datenflusses:


Vom Client zum Server (hochladen)
Vom Server zum Client (runterladen)
Innerhalb des Servers
Innerhalb des Clients
Bitte wähle, was davon du machen möchtest.


----------



## kneitzel (7. Apr 2021)

Ach so - evtl. eine Datei auf dem Server kopieren? Dann nutz nicht die Transfer-Methode sondern setz den entsprechenden Befehl ab. Also den "exec" channel und als Befehl dann sowas wie "cp sourcefile targetfile" - um eine einfache Möglichkeit zu nennen.


----------



## Joob (7. Apr 2021)

Mir geht es um einen Kopiervorgang innerhalb des Servers. 
Und das was kneitzel vorgeschlagen hat ist genau das was ich gesucht habe.
Ich schau mir das mal an und hoffe das ich damit klarkomme.

Schönen Dank erst mal.


----------



## temi (7. Apr 2021)

Kannst du dich nicht einfach per ssh mit dem Server verbinden und arbeiten?


----------



## Joob (7. Apr 2021)

Leider haut das nicht hin und ich weiß nicht warum

connect klappt
Wenn ich mich mit Putty einlooge unter dem User kann ich den Befehl in der Konsole ausführen,

wenn aber das Programm es macht dann passiert nichts.


```
channelExec = (ChannelExec) session.openChannel( "exec" );
                    if( channelExec == null )
                    {
                        logoutSftp();
                        String errMes = "Fehler beim Oeffnen des Exec-Channel zur Session mit '" + session.getUserName() + "' an '" + session.getHost() + "'. " ;
                        Logger.getLogger(SFtpToolsClass.class.getName()).log(Level.WARNING, errMes, errMes);
                        throw new IOException( );
                    }   
                    channelExec.connect();
```

und der Befehl:

```
boolean copyJobDone = false;
        try {
            connectServer(alternativAccess, 2);
            
            String copyCommand = "cp -u " + source + " " + destination;
            
            ((ChannelExec)channelExec).setCommand(copyCommand);
             copyJobDone = true;
            
        } catch (IOException ex) {
            Logger.getLogger(SFtpToolsClass.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
        
        } finally
        {
            logoutExec();
        }
        return copyJobDone;
```

kann jemand den Fehler erkennen, 
der Commandstring ist : cp -u /home/....../H-7.pdf /home/...../TASK_64.pdf und der läuft wie gesagt unter dem User im Terminal


----------



## Joob (7. Apr 2021)

Vielleicht hat jemand eine Tip wie ich das testen kann.


----------



## kneitzel (7. Apr 2021)

Also irgendwie finde ich Deinen Code extrem schlecht lesbar ... Von welchem Typ ist die Variable channelExec?

Die ganzen Casts sollten so nicht notwendig sein - bei der Variable ist es aber deutlich,,dass die Casts zumindest teilweise so Unsinn sind ...


```
channelExec = (ChannelExec) session.openChannel( "exec" );
((ChannelExec)channelExec).setCommand(copyCommand);
```

Wenn channelExec vom Typ (ChannelExec) ist, dann könnte der erste Cast notwendig sein, aber dann bräuchte es den zweiten nicht ... oder umgekehrt ... Egal wie dem auch sei: Schwer zu lesen ... openChannel gibt einen Channel zurück .. und von dem Typ würde ich die Variable dann auch nutzen ...

Und nach meinem ersten Verständnis ist das so nicht korrekt. Der Ablauf ist doch, du erstellst den channel, setzt die Werte (command, in/out streams, ...) und dann machst Du den connect.

Bei sowas würde ich mich ansonsten etwas nach Beispielen richten, die es zu einem Projekt gibt und dann mit denen erst einmal rumspielen und dann durch Anpassungen die Funktionalität im Detail zu verstehen. Dann kann man sich auch überlegen, wie das in die eigene Applikation rein passt und was man ggf. noch für weitere Klassen benötigt ...

Und dann ist ggf. auch der err und der out Stream interessant - die würde ich auch auslesen - bei den Tests dann ruhig wie in dem Beispiel mit System.out und System.err nutzen .... Dann bekommt Du ggf. Probleme mit, wie Befehl nicht im Pfad oder so ... (Wobei cp in der Regel in /bin/cp ist und das sollte gefunden werden...)


----------



## Joob (7. Apr 2021)

Ich habe meinen Fehler gesehen, 
ich darf das Connect erst machen nachdem ich den Befehl gesetzt habe.
So haut das hin.

Gibt es vielleicht noch was zu verbessern ?


----------



## Joob (7. Apr 2021)

Das casten habe ich entfernt, danke für den Tip.

Das mit der Lesbarkeit liegt vielleicht daran, das ich alle FileTransferfunktionalitäten in einer Klasse habe.
Der obere Teil ist ein Auszug aus der Methode die die Verbindung herstellt.
Ist schwierig alles mitzugeben.

Der untere ist die Methode die die Funktionalität abbildet.

Ich habe das jetzt so verstanden, 
ich definieren einen Channel zum Ausführen eines Befehls.
Dann setzt ich den Befehl.
Danach mache ich den Connect.
Dabei wird der Befehl auf dem Server ausgeführt.
Dann schließe ich die Verbindung wieder.

Liege ich da falsch ?


----------

