Mam if
instrukcję do obliczania plików i usuwania wszystkich oprócz trzech ostatnich plików. Ale chcę uruchomić to polecenie zdalnie. Jak mogę połączyć ssh
z if
warunkiem?
Próbowałem tego, ale bez powodzenia.
#!/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"
Wystąpił błąd:
ls: nie można uzyskać dostępu * .tgz: nie ma takiego pliku ani katalogu
command-line
bash
ssh
Janith
źródło
źródło
$(
)
Część polecenia jest wykonywany przez lokalną powłoce, zanim jeszcze rozpoczniessh
komendę. Dotyczy to zarówno sytuacji$(
)
samodzielnych, jak i otoczonych przez"
s. Jednak gdyby$(
)
był w środku'
, nie byłby wykonywany przez lokalną powłokę.Odpowiedzi:
UWAGA: w rzeczywistości pytanie ma dwie warstwy. Jednym z nich jest „Chcę wykonać nietrywialne zadanie na zdalnym serwerze dostępnym za pośrednictwem SSH”. Drugi to „Próbuję przekazać złożony ciąg do polecenia, a argument jest inny niż zamierzony”. Odpowiadam na pytanie niskiego poziomu, nie dyskutując, czy zastosowane podejście jest „właściwe” (wygodne, nie podatne na błędy, bezpieczne itp.) Do rozwiązania wysokiego poziomu. Jak wskazują inne odpowiedzi i komentarze, prawdopodobnie nie jest.
Twoja linia poleceń ma w większości rację; musisz tylko trochę zmienić cytat.
Główny problem polega na tym, że łańcuchy cudzysłowów są rozszerzane przez lokalną powłokę, a zatem
$(...)
części będą oceniane w systemie lokalnym. Aby przekazać je do systemu zdalnego, musisz umieścić skrypt w pojedynczym cudzysłowie.Masz również osadzone znaki cudzysłowu. W twoim oryginalnym skrypcie istnieją argumenty za tymi dwoma
echo
; jeśli zmienisz zewnętrzny cytat na pojedyncze, będzie to skrypt awk. Skutecznie skutkuje to pominięciem cudzysłowu, co nie przeszkadzaecho
s, ale zepsuje skrypt awk, ponieważ znak większy niż stanie się przekierowaniem wyjścia. Więc po zmianie zewnętrznych znaków cudzysłowu na pojedyncze cudzysłowy zmień je na podwójne cudzysłowy.To jest twój skrypt ze stałym cytowaniem. Skrypt może mieć inne problemy, właśnie naprawiłem składnię.
źródło
/var/www/test.com/backup
do zmiennej o nazwie „BACKUPDEST” icd $BACKUPDEST
czy możesz mi powiedzieć, jak to zrobić?BACKUPDEST
? Jeśli zdarzy się to po stronie zdalnej, po prostu włącz go normalnie do skryptu. Jeśli chcesz ustawić go lokalnie (np. Obliczyć w skrypcie lokalnym lub przekazać jako argument wiersza poleceń), możesz zmienić pierwszy wiersz na np."cd $BACKUPDEST"' ;
- powłoka rozwija część podwójnego cudzysłowu, zachowuje cudzysłowy część nienaruszona, łączy dwa i przekazuje wynik jako ostatni argument dossh
."cd '$BACKUPDEST'"' ;
jeśli ścieżka w tej zmiennej zawiera jakieś dziwności (np. Spację). Ponownie: po prostu mówiąc, że można to zrobić w ten sposób, a nie że należy to zrobić w ten sposób.Tak, możesz wyekstrahować złożone skrypty za pośrednictwem
ssh
W tym przykładzie użyto dokumentu bash tutaj do wygenerowania ciągu poleceń. W każdym razie przekazywanie skryptów przez ssh jest podatne na błędy, ponieważ cytowanie i ucieczka zmiennych jest trudne (zwróć uwagę na odwrotny ukośnik przed poleceniami). Jeśli skrypt staje się zbyt skomplikowany, lepiej go skopiować,
scp
a następnie uruchomić na hoście docelowym.Nie próbowałem naprawić skryptu , ale oto przykład, jak może działać liczenie i usuwanie na zdalnym hoście:
ls -t *.tgz
Nie będzie działać, ponieważ masek dzieje się tylko w systemie lokalnym. Korzystając równieżls
dla plików liczenia nie jest dobrym pomysłem, ponieważ również zwraca wpisy jak.
,..
i katalogów.źródło
syntax error near unexpected token elif'
,elif [ $(ls -t |awk 'NR >3'|xargs rm -f) ]; then'
;
pierwszej instrukcji if brakowało. Ale nie naprawiłem ci skryptu! Jest o wiele więcej problemów, np.ls *.tgz
$(...)
tekst w cudzysłowie, więc lokalna powłoka go oceniła. Ucieczka od niego, jak\$(...)
pokazano w pierwszym przykładzie, lub użycie pojedynczych cudzysłowów wokół całego skryptu, zapobiega rozszerzeniu go przez lokalną powłokę, więc zostaje on wysłany do systemu zdalnego, jest rozszerzony przez zdalną powłokę i skrypt działa jak zamierzono.printf
rozwinąć zmienne - nadal będzie to łatwiejsze do zarządzania niż próba ucieczki od wszystkich zmiennych powłoki w całym tekście. Ponadto uniknęłoby to użyciacat
tylko do przechwycenia dokumentu tutaj w zmiennej!Myślę, że całe to skomplikowane cytowanie jest wystarczającym dowodem, aby go nie używać, ale zamiast tego użyć skryptu. Jeśli chcesz uniknąć wielu
ssh
połączeń, przenieś skrypt do drugiego hosta i pozwól mu działać w jednym poleceniu:Plik lokalny, powiedz
myscript.sh
:Następnie:
Lub (unikając bezużytecznego użycia kota ):
Spowoduje to przeniesienie lokalnego skryptu
myscript.sh
na stronę zdalną, gdzie zostanie przekierowany do (tymczasowego) pliku/tmp/ms.sh
, wykonany i ostatecznie usunięty.Uwaga: nie sprawdziłem oryginalnego skryptu pod kątem błędów, ale chciałem tylko pokazać pomysł. Nie jest konieczne cytowanie podatne na błędy, a wszystkie polecenia w skrypcie są wykonywane po stronie zdalnej.
źródło
ssh user@host bash <myscript.sh
.mktemp
lub czegoś podobnego bezpiecznego.Wolałbym umieścić skrypt w zdalnej instancji i po prostu wykonać go za pomocą ssh, ale oto moja sugestia, jak można to zrobić tak, jak chcesz:
Uwagi:
-lt
jest zastępowane przez-le
.eval
- konstruuj polecenia, łącząc argumenty.\"
w$COMMAND{1..3}
wyrażeniu, ale postanawiam je dodać.źródło