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.txt
und file2.txt
für völlig unterschiedliche Dinge innerhalb des Programms verwendet, daher kann ich sie nicht einfach cat
zusammenfügen. In meinem Fall existieren die file1.txt
und 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.txt
auch dorthin bringen. Ich denke, das könnte durch Missbrauch von Umgebungsvariablen und kreative Verwendung von cat
und sed
zusammen 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 cat
ist 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 EOT
durch 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, tmpfs
der 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, program
ein Tarball als einzelne Eingabe zu verwenden und dessen Inhalt in den Speicher zu entpacken. Wenn es sich beispielsweise program
um ein Python-Skript handelt, könnte dies mithilfe des integrierten tarfile
Moduls 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 ( $serv
ist 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 ssh
Zugriff haben , können Sie beispielsweise Folgendes tun:wget
busybox
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 $!
( cat
als Beispiel wird ein Programm verwendet, das zwei Dateiargumente annimmt).
Wichtig ist nur die Möglichkeit, Ports über weiterzuleiten. -R
Statt http können Sie auch andere Methoden verwenden, z. B. wenn Ihr Unternehmen die Optionen und netcat
unterstü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.