Wie kann ich ein lokales Skript auf einem Remote-Computer ausführen und Argumente einschließen?


116

Ich habe ein Skript geschrieben, das bei lokaler Ausführung einwandfrei funktioniert:

./sysMole -time Aug 18 18

Die Argumente "-time" , "Aug" , "18" und "18" werden erfolgreich an das Skript übergeben.

Dieses Skript kann jetzt auf einem Remotecomputer ausgeführt werden, jedoch in einem lokalen Verzeichnis auf dem lokalen Computer. Beispiel:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole

Das funktioniert auch gut. Das Problem tritt jedoch auf, wenn ich versuche, die oben genannten Argumente einzubeziehen (-time Aug 18 18) , zum Beispiel:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole -time Aug 18 18

Nach dem Ausführen dieses Skripts erhalte ich die folgende Fehlermeldung:

bash: cannot set terminal process group (-1): Invalid argument
bash: no job control in this shell

Bitte sag mir, was ich falsch mache, das ist sehr frustrierend.


1
"Bash -s" ist eine der Möglichkeiten, ein Skript über die Standardeingabe (dh eine Datei) auszuführen.
AllenD

Antworten:


160

Sie waren Ihrem Beispiel ziemlich nahe. Es funktioniert einwandfrei, wenn Sie es mit Argumenten wie diesen verwenden.

Beispielskript:

$ more ex.bash 
#!/bin/bash

echo $1 $2

Beispiel, das funktioniert:

$ ssh serverA "bash -s" < ./ex.bash "hi" "bye"
hi bye

Bei folgenden Argumenten schlägt dies jedoch fehl:

$ ssh serverA "bash -s" < ./ex.bash "--time" "bye"
bash: --: invalid option
...

Was ist los?

Das Problem, auf das Sie stoßen, besteht darin, dass das Argument -timeoder --timein meinem Beispiel als Wechsel zu interpretiert wird bash -s. Sie können beruhigen, bashindem Sie beenden, indem Sie eines der verbleibenden Befehlszeilenargumente mit dem Argument für sich selbst übernehmen --.

So was:

$ ssh root@remoteServer "bash -s" -- < /var/www/html/ops1/sysMole -time Aug 18 18

Beispiele

# 1:

$ ssh serverA "bash -s" -- < ./ex.bash "-time" "bye"
-time bye

# 2:

$ ssh serverA "bash -s" -- < ./ex.bash "--time" "bye"
--time bye

#3:

$ ssh serverA "bash -s" -- < ./ex.bash --time "bye"
--time bye

# 4:

$ ssh  < ./ex.bash serverA "bash -s -- --time bye"
--time bye

ANMERKUNG: Nur um zu verdeutlichen, dass die Umleitung in der Befehlszeile keinen Unterschied macht, da das sshAufrufen einer Remote-Shell mit der Verkettung ihrer Argumente ohnehin keinen großen Unterschied macht, es sei denn, Sie müssen in der Remote-Shell zitieren wie in Beispiel # 4:

$ ssh  < ./ex.bash serverA "bash -s -- '<--time bye>' '<end>'"
<--time bye> <end>

4
Du bist ein Genie! Was muss ich tun, um auf dein Level zu kommen? Ich habe eine Menge Arbeit ausgeschnitten. Vielen Dank.
AllenD,

14
@AllenD - stellen Sie einfach weiter Fragen und versuchen Sie, so viel wie möglich an der Website teilzunehmen. Ich versuche immer, jeden Tag etwas Neues zu lernen. Vor Ihrer Frage wusste ich auch nicht, wie ich das machen sollte. 8-). Danke für deine Frage!
slm

5
Beachten Sie, dass die Umleitung an jeder Stelle im Befehl erscheinen kann: zum Beispiel bash -s -- --time bye < ./ex.bashoder sogar < ./ex.bash bash -s -- --time bye. Dies liegt daran, dass die Shell zuerst die Umleitungsanweisung ausführt (unabhängig davon, wo sie sich im Befehl befindet), dann die Umleitung einrichtet und dann den Rest der Befehlszeile mit der Umleitung ausführt.
Lesmana

@sim Ich versuche, genau dasselbe zu tun, aber innerhalb eines Skripts, nicht über die Befehlszeile. Irgendeine Idee, wie das geht? Aus irgendeinem Grund funktioniert es überhaupt nicht, Ihre exakte Antwort in Backticks einzuschließen. Stattdessen wird das lokal angegebene Skript ausgeführt und die Ausgabe als Befehl über ssh
krb686 am

@ krb686 - Ich würde es als neues Q fragen.
slm

5

Zum Umgang mit willkürlichen Argumenten

Wenn Sie wirklich nur eine einzige Zeichenfolge verwenden, z. -time Aug 18 18Dann können Sie es einfach hart codieren, und vorhandene Antworten zeigen Ihnen, wie Sie dies angemessen tun können. Wenn Sie dagegen unbekannte Argumente weitergeben müssen (z. B. eine Nachricht, die auf dem anderen System angezeigt werden soll, oder den Namen einer Datei, die erstellt wurde, um den Namen des Endbenutzers zu steuern), ist mehr Sorgfalt erforderlich.


Mit bashoder kshals/bin/sh

Wenn Ihre Fernbedienung /bin/shvon bash oder ksh bereitgestellt wird, können Sie mit einer nicht vertrauenswürdigen Argumentliste sicher Folgendes tun, sodass auch böswillige Namen (wie $(rm -rf $HOME).txt) sicher als Argumente übergeben werden können:

runRemote() {
  local args script

  script=$1; shift

  # generate eval-safe quoted version of current argument list
  printf -v args '%q ' "$@"

  # pass that through on the command line to bash -s
  # note that $args is parsed remotely by /bin/sh, not by bash!
  ssh user@remote-addr "bash -s -- $args" < "$script"
}

Mit allen POSIX-konformen /bin/sh

Um sicher zu gehen, dass keine hinreichend böswilligen Argumentdaten (z. B. oder ) verwendet werden, die nicht POSIX-konform printf %qsind, wenn in der zu maskierenden Zeichenfolge nicht druckbare Zeichen enthalten sind ) wird ein bisschen interessanter:/bin/shdashash

runRemote() {
  local script=$1; shift
  local args
  printf -v args '%q ' "$@"
  ssh user@remote-addr "bash -s" <<EOF

  # pass quoted arguments through for parsing by remote bash
  set -- $args

  # substitute literal script text into heredoc
  $(< "$script")

EOF
}

Verwendung (für eine der oben genannten Möglichkeiten)

Die oben angegebenen Funktionen können dann wie folgt aufgerufen werden:

# if your time should be three arguments
runRemote /var/www/html/ops1/sysMole -time Aug 18 18

...oder...

# if your time should be one string
runRemote /var/www/html/ops1/sysMole -time "Aug 18 18"

-3

say aa ist eine lokale Datei, die ls enthält

$ssh servername "cat | bash" < a.a

ändere 127.0.0.1 auf deine entfernte IP

Diese beiden geben eine Nachricht über die Pseudotty-Zuweisung, funktionieren aber.

$ cat a.a | ssh 127.0.0.1

$ ssh 127.0.0.1 <a.a

Oder

$ cat a.a | ssh 127.0.0.1 bash or

$ ssh 127.0.0.1 bash < a.a


2
Ich habe Mühe zu sehen, inwieweit dies die Frage beantwortet.
ChrisWue

Die Qualität und Formatierung ist zweifelhaft. Ich sehe keine neuen nützlichen Informationen, die auch in der akzeptierten Antwort nicht vorhanden sind.
Julie Pelletier

@ JuliePelletier Ich gab einige "Katze" Beispiele nicht in der akzeptierten Antwort. Es ist gut, alternative Methoden zu kennen.
Barlop

Das ist keine gute Sache; Ihre Katzen sind nutzlos.
Scott

2
Du meine Güte. Ich habe den Link zum nutzlosen Gebrauch von Katze weggelassen, weil ich davon ausgegangen bin, dass inzwischen jeder von dem Satz gehört hat. anscheinend war das eine schlechte annahme von meiner seite.
Scott
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.