Ich habe eine if
Anweisung Dateien zu berechnen und alle außer spätestens drei Dateien zu löschen. Ich möchte diesen Befehl jedoch remote ausführen. Wie kann ich ssh
mit einer if
Bedingung kombinieren ?
Ich habe es versucht, aber keinen Erfolg.
#!/bin/bash
ssh -t test@192.168.94.139 "cd /var/www/test.com/backup ;
if [ $(ls | wc -l) -lt 3 ]
then
echo "Less"
else [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]
echo "deleted"
fi"
Der Fehler, den ich bekam:
ls: kann nicht auf * .tgz zugreifen: Keine solche Datei oder kein solches Verzeichnis
command-line
bash
ssh
Janith
quelle
quelle
$(
)
Teil des Befehls wird von der lokalen Shell ausgeführt, bevor derssh
Befehl überhaupt gestartet wird . Das gilt sowohl für$(
)
sich allein als auch für"
s. Wenn es sich$(
)
jedoch in'
s befindet, wird es nicht von der lokalen Shell ausgeführt.Antworten:
HINWEIS: Die Frage besteht aus zwei Ebenen. Eine lautet: "Ich möchte eine nicht triviale Aufgabe auf einem Remote-Server ausführen, auf den über SSH zugegriffen werden kann." Das andere ist: "Ich versuche, eine komplexe Zeichenfolge an einen Befehl zu übergeben, und das Argument unterscheidet sich letztendlich von dem, was ich beabsichtigt habe." Ich beantworte die Frage auf niedriger Ebene, ohne zu diskutieren, ob der verwendete Ansatz "richtig" ist (praktisch, nicht fehleranfällig, sicher usw.), um die Frage auf hoher Ebene zu lösen. Wie aus den anderen Antworten und Kommentaren hervorgeht, ist dies möglicherweise nicht der Fall.
Ihre Befehlszeile ist größtenteils richtig. Sie müssen das Zitat nur ein wenig ändern.
Das Hauptproblem besteht darin, dass Zeichenfolgen in doppelten Anführungszeichen von Ihrer lokalen Shell erweitert werden und die
$(...)
Teile daher auf Ihrem lokalen System ausgewertet werden. Um sie an das Remote-System weiterzuleiten, müssen Sie das Skript in einfache Anführungszeichen setzen.Sie haben auch einige eingebettete Anführungszeichen. In Ihrem ursprünglichen Skript gibt es die Argumente für die beiden
echo
s; Wenn Sie das äußere Anführungszeichen in einfache Anführungszeichen ändern, handelt es sich um das awk-Skript. Diese führen effektiv dazu, dass die Anführungszeichen weggelassen werden, was dasecho
s nicht stört , aber das awk-Skript durcheinander bringt, da das Größer-als-Zeichen zur Ausgabeumleitung wird. Nachdem Sie die äußeren Anführungszeichen in einfache Anführungszeichen geändert haben, ändern Sie diese in doppelte Anführungszeichen.Dies ist Ihr Skript mit festem Zitat. Das Skript kann andere Probleme haben, ich habe nur die Syntax behoben.
quelle
/var/www/test.com/backup
eine Variable namens "BACKUPDEST" zuweisen undcd $BACKUPDEST
können Sie mir sagen, wie das geht?BACKUPDEST
? Wenn dies auf der Remote-Seite geschieht, fügen Sie es normalerweise normal in das Skript ein. Wenn Sie es lokal (zB berechnen sie im lokalen Skript oder es in als Kommandozeilen - Argument übergeben) festlegen möchten, können Sie die erste Zeile zB ändern"cd $BACKUPDEST"' ;
- die Shell den doppelten Anführungszeichen Teil erweitert wird , hält die einfachen Anführungszeichen Teil intakt, verkettet die beiden und übergibt das Ergebnis als letztes Argument anssh
."cd '$BACKUPDEST'"' ;
der Pfad in dieser Variablen eine gewisse Verrücktheit enthält (z. B. ein Leerzeichen). Nochmals: Ich sage nur, dass es so gemacht werden kann, nicht, dass es so gemacht werden sollte.Ja, Sie können komplexe Skripte über ausführen
ssh
In diesem Beispiel wird ein Bash- Here-Dokument verwendet , um die Befehlszeichenfolge zu generieren. In jedem Fall ist das Übergeben von Skripten über ssh fehleranfällig, da das Zitieren und Escapezeichen von Variablen schwierig ist (beachten Sie den Backslash vor den Befehlen). Wenn das Skript zu komplex wird, ist es besser, es über zu kopieren
scp
und dann auf dem Zielhost auszuführen.Ich habe nicht versucht, Ihr Skript zu reparieren , aber hier ist ein Beispiel dafür, wie das Zählen und Löschen auf einem Remote-Host funktionieren kann:
Das
ls -t *.tgz
wird nicht funktionieren, da das Globbing nur auf dem lokalen System stattfindet. Auch unter Verwendung vonls
Dateien für das Zählen ist keine gute Idee, da es auch wieder Einträge wie.
,..
und Verzeichnisse.quelle
syntax error near unexpected token elif'
,elif [ $(ls -t |awk 'NR >3'|xargs rm -f) ]; then'
;
In der ersten if-Anweisung fehlte ein . Aber ich habe dein Skript nicht repariert! Es gibt viele weitere Probleme, z. B. diels *.tgz
$(...)
in einer Zeichenfolge in doppelten Anführungszeichen, daher wurde sie von der lokalen Shell ausgewertet. Wenn Sie es wie\$(...)
im ersten Beispiel gezeigt maskieren oder einfache Anführungszeichen für das gesamte Skript verwenden, wird verhindert, dass die lokale Shell es erweitert, sodass es an das Remote-System gesendet wird, von der Remote-Shell erweitert wird und das Skript funktioniert wie beabsichtigt.printf
in einfachen Anführungszeichen zu verwenden und Variablen zu erweitern. Dies ist immer noch einfacher zu verwalten, als zu versuchen, alle Shell-Variablen durchgehend zu umgehen. Außerdem müsste vermieden werden, dasscat
nur das Dokument hier in einer Variablen erfasst wird!Ich denke, dieses ganze komplizierte Zitiermaterial ist Beweis genug, um es nicht zu verwenden, sondern stattdessen ein Skript zu verwenden. Wenn Sie mehrere
ssh
Verbindungen vermeiden möchten, leiten Sie das Skript an den anderen Host weiter und lassen Sie es dort mit einem Befehl ausführen:Lokale Datei, sagen Sie
myscript.sh
:Dann:
Oder (Vermeidung einen nutzlosen Einsatz von Katze ):
Dadurch wird das lokale Skript
myscript.sh
an die Remote-Seite weitergeleitet, wo es in eine (temporäre) Datei umgeleitet/tmp/ms.sh
, ausgeführt und schließlich entfernt wird.Hinweis: Ich habe das ursprüngliche Skript nicht auf Fehler überprüft, sondern wollte nur die Idee zeigen. Es ist kein fehleranfälliges Zitieren erforderlich, und alle Befehle im Skript werden auf der Remote-Seite ausgeführt.
quelle
ssh user@host bash <myscript.sh
. H.mktemp
oder ähnlich sicher.Ich würde es vorziehen, das Skript auf der Remote-Instanz zu platzieren und es einfach über ssh auszuführen, aber hier ist mein Vorschlag, wie dies auf die von Ihnen gewünschte Weise geschehen könnte:
Anmerkungen:
-lt
wird durch ersetzt-le
.eval
- Befehl konstruieren durch Verketten von Argumenten.\"
im$COMMAND{1..3}
Ausdruck wirklich brauchen , aber ich beschließe, sie hinzuzufügen.quelle