Übergeben mehrerer Dateien über stdin (über ssh)

Übergeben mehrerer Dateien über stdin (über ssh)

Ich habe ein Programm auf einem Remote-Host, dessen Ausführung ich automatisieren muss. Der Befehl, dieses Programm auf derselben Maschine auszuführen, sieht ungefähr so ​​aus:

/path/to/program -a file1.txt -b file2.txt

In diesem Fall werden file1.txtund file2.txtfür völlig unterschiedliche Dinge innerhalb des Programms verwendet, daher kann ich sie nicht einfach catzusammenfügen. In meinem Fall existieren die file1.txtund file2.txt, die ich an das Programm übergeben möchte, jedoch nur auf meinem Gerät, nicht auf dem Host, auf dem ich das Programm ausführen muss. Ich weiß, dass ich mindestens eine Datei über SSH einspeisen kann, indem ich sie durchgebe stdin:

cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt

aber da ich keine Dateien auf dem Host speichern darf, muss ich die Dateien file2.txtauch dorthin bringen. Ich denke, das könnte durch Missbrauch von Umgebungsvariablen und kreative Verwendung von catund sedzusammen möglich sein, aber ich kenne die Tools nicht gut genug, um zu verstehen, wie ich sie verwenden würde, um das zu erreichen. Ist das machbar und wie?

Antwort1

Wenn es sich bei den Dateien, die Sie Ihrem Programm als Argumente übergeben, um Textdateien handelt und Sie deren Inhalt steuern können (also eine Zeile angeben, die in ihnen nicht vorkommt), können Sie mehrere Here-Dokumente verwenden:

{
    echo "cat /dev/fd/3 3<<'EOT' /dev/fd/4 4<<'EOT' /dev/fd/5 5<<'EOT'"
    cat file1
    echo EOT
    cat file2
    echo EOT
    cat file3
    echo EOT
} | ssh user@host sh

Hier catist ein Beispielbefehl, der Dateinamen als Argumente verwendet. Stattdessen könnte er lauten:

echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'

Ersetzen Sie jedes EOTdurch etwas, das in den einzelnen Dateien nicht vorkommt.

Antwort2

Vielleicht nicht genau das, was Sie möchten ... Aber vielleicht sollten Sie ein Tarball über die von SSH geöffnete Pipe senden?

Du hast das gesagt:

Ich darf keine Dateien auf dem Host speichern.

Möglicherweise verfügen Sie nicht über ein beschreibbares Home-Verzeichnis oder einen anderen geeigneten Speicherort zum langfristigen Speichern von Dateien, aber ich würde sagen, dass es unwahrscheinlich ist, dass Sie keinen beschreibbaren Speicherort haben, selbst wenn es sich um einen temporären Speicherort handelt, tmpfsder nur für Ihre bestimmte Verbindung zur Verfügung gestellt wird.

Viele Programme (und sogar libc-Routinen) erfordern einen beschreibbaren /tmp, daher ist es sehr wahrscheinlich, dass Ihnen einer zur Verfügung steht.

Anschließend können Sie ein Skript verwenden, das das Tarball in ein temporäres Verzeichnis entpackt, Ihr Programm ausführt und über die SSH-Verbindung bereinigt.

Etwas wie:

$ tar cf - file1.txt file2.txt |
  ssh host.name '
      set -e
      tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX)
      cleanup () { rm -rf "$tmpdir"; }
      trap cleanup EXIT
      cd "$tmpdir"
      tar xf -
      /path/to/program -a file1.txt -b file2.txt
  '

Dies erfordert möglicherweise besondere Sorgfalt bei den Dateipfaden und es gibt einige Sonderfälle, die berücksichtigt werden müssen (testen Sie diese), aber der allgemeine Ansatz sollte funktionieren.

Wenn kein beschreibbares Verzeichnis verfügbar ist, wäre eine mögliche Vorgehensweise, programein Tarball als einzelne Eingabe zu verwenden und dessen Inhalt in den Speicher zu entpacken. Wenn es sich beispielsweise programum ein Python-Skript handelt, könnte dies mithilfe des integrierten tarfileModuls problemlos erreicht werden.

Antwort3

Wenn Sie einen TCP-Listener einrichten können (kann ein höherer Port sein), können Sie eine zweite SSH-Sitzung verwenden, um die zweite Eingabequelle mit einzurichten nc.

Beispiel:

Auf dem Server befindet sich dieses Skript ( ~/script.bash):

#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'

Und lokal gibt es diese beiden Dateien:

$ cat a 
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb

Nun starten Sie zunächst die zweite Quelle ( $servist der Server):

ssh "$serv" nc -l -p 2222 -q1 <b &

Und führen Sie den eigentlichen Befehl aus:

$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+  Done                    ssh "$serv" nc -l -p 2222 -q1 < b

Antwort4

Wenn Sie Ports über weiterleiten dürfen und auf dem Remotecomputer auf und auf dem lokalen Computer sshZugriff haben , können Sie beispielsweise Folgendes tun:wgetbusybox

mkdir /tmp/test; cd /tmp/test
echo 1st_file > 1st_file
echo 2nd_file > 2nd_file

busybox httpd -f -p 127.0.0.1:11080 &
ssh USER@HOST -R 10080:127.0.0.1:11080 '
        cat <(wget -q -O- http://localhost:10080/1st_file) \
            <(wget -q -O- http://localhost:10080/2nd_file)
'
kill $!

( catals Beispiel wird ein Programm verwendet, das zwei Dateiargumente annimmt).

Wichtig ist nur die Möglichkeit, Ports über weiterzuleiten. -RStatt http können Sie auch andere Methoden verwenden, z. B. wenn Ihr Unternehmen die Optionen und netcatunterstützt :-d-N

nc -Nl localhost 11001 < 1st_file &
nc -Nl localhost 11002 < 2nd_file &
ssh USER@HOST -R 10001:localhost:11001 -R 10002:localhost:11002 '
        cat <(nc -d localhost 10001) <(nc -d localhost 10002)

Es gibt möglicherweise Möglichkeiten, die <(...)Prozessersetzungen zu ersetzen, wenn die Login-Shell auf dem Remote-Computer nicht ksh- oder bash-ähnlich ist.

Alles in allem ist das nicht so toll – bessere Kenntnisse über das genaue System/die Shells/die Konfiguration/die Berechtigungen (die Sie nicht bereitgestellt haben) könnten intelligentere Lösungen ermöglichen.

verwandte Informationen