Zdalne polecenie PuTTY zawierające pętlę while

0

Próbuję zautomatyzować kilka typowych zadań, które wykonuję SSH do zdalnego serwera. W tym celu używam PuTTY i jego opcji „polecenia zdalnego” (Połączenie> SSH) w kilku zapisanych sesjach. Moje zdalne polecenie wygląda mniej więcej tak:

~/scripts/test; $SHELL -l

Wykonywany skrypt różni się w zależności od zapisanej sesji i wykonuje różne zadania. $SHELL -lutrzymuje sesję PuTTY aktywną po zakończeniu wykonywania skryptu.

Wszystko to działa idealnie dla większości skryptów, które uruchamiam. Mam jednak taki, który używa pętli while do wykonania szeregu poleceń, dopóki nie zakończy się kombinacją Ctrl + C. Skrypt uruchamia się dobrze, ale powłoka PuTTY nie pozostaje aktywna po zakończeniu. $SHELL -lnie wydaje się być wykonywany.

Przykładowy skrypt z takim zachowaniem jest następujący:

while true; do
echo "."
sleep 2
done

Poniższe działa dobrze wykonane ręcznie, widzę oczekiwane dane wyjściowe z drugiego polecenia:

~/scripts/test; echo "done"

Jednak drugie polecenie „polecenia zdalnego” PuTTY nie jest wykonywane. Rzeczywiście, jeśli zmienię komendę zdalną na „an” echo, nie zostanie ona wyświetlona.

~/scripts/test; echo "done"; $SHELL -l

Myślę więc, że moje pytanie brzmi: dlaczego drugie polecenie na liście nie jest wykonywane przez polecenie zdalne, podczas gdy jest uruchamiane ręcznie? A co ważniejsze, co mogę z tym zrobić?

Jeśli to istotne, używam PuTTY na Ubuntu 14.04.

oogles
źródło
Dlaczego nie po prostu użyć ssh(OpenSSH)? To powinno być domyślnie zainstalowane na Ubuntu. Lub jeśli naprawdę musisz korzystać z PuTTY, użyj plink, który jest specjalnie zaprojektowany do automatyzacji.
Bob
Zastanawiałem się nad rozwiązaniem tego problemu jako części pytania, pomyślałem, że może się pojawić :). Znam sesje zapisane w kitach i dostępne opcje, od używania ich pod Windows. A ponieważ Kit był obsługiwany w Linuksie, nie widziałem potrzeby odejścia od tego, co wiem. Ale przyjrzę się plink, dzięki :).
oogles

Odpowiedzi:

2

Kiedy uruchomisz puttylub ssh- nie sądzę, żeby w tym kontekście istniała jakaś różnica - z poleceniem do uruchomienia w systemie zdalnym, zdalny serwer ssh uruchamia polecenie jako polecenie powłoki:

/bin/bash -c '~/scripts/test; $SHELL -l'

Więc masz bashinstancję w zdalnym systemie wykonującą ten potok. Masz także inną bashinstancję uruchomioną przez pierwszą instancję, która wykonuje ten skrypt „testowy”.

Po wpisaniu Control-C puttywysyła znak do zdalnego systemu, gdzie jest interpretowany przez TTY jako znak przerwania. Powoduje to wysłanie SIGINT (sygnał przerwania) do procesów dołączonych do TTY. Przerywa to oba procesy powłoki, powodując ich zamknięcie. Chcesz, aby instancja powłoki nadrzędnej ignorowała SIGINT.

Polecenie bash, aby zignorować SIGINT, to:

trap "" INT

Aby wyłączyć SIGINT dla potoku, zmień oryginalne polecenie na:

trap '' INT; ~/scripts/test; $SHELL -l

Ale to wyłącza SIGINT również dla procesów potomnych, co uczyniłoby skrypt „testowy” odpornym na Ctrl-C. Musisz więc ponownie włączyć SIGINT dla skryptu testowego. Polecenie to brzmi:

trap INT

Możesz dodać ten wiersz do samego skryptu testowego lub możesz dodać go do potoku:

trap '' INT; ( trap INT; ~/scripts/test ); $SHELL -l

Teraz, kiedy naciśniesz Ctrl-C, powinieneś przerwać proces „testowy”, ale nie proces nadrzędny, który wykonuje potok poleceń.

Możesz to przetestować bez użycia putta lub ssh. Wystarczy uruchomić te polecenia i nacisnąć Ctrl-C podczas wykonywania „uśpienia”:

bash -c 'sleep 15; echo foo'                  # Ctrl-C kills sleep; doesn't print "foo"
bash -c 'trap "" INT ; sleep 15; echo foo'    # Ctrl-C has no effect
bash -c 'trap "" INT; ( trap INT; sleep 15 ); echo foo'    # Kills sleep, prints "foo"
Kenster
źródło
Dziękuję za tak pouczającą odpowiedź. Działa to doskonale :).
oogles
0

ctrl + c dla komendy putty faktycznie przerywa sesję ssh, więc należy się spodziewać, że nie wykonuje ona pozostałych komend zdalnych. Jeśli Twoim celem jest, aby sesja nadal była aktywna, Twoja nieskończona pętla powinna wystarczyć.

Faiz R.
źródło
Głównym powodem, dla którego chcę wrócić do interaktywnej powłoki, jest to, że polecenie zapętlenia czasami wymaga zatrzymania i ponownego uruchomienia, i byłoby miło zrobić to w tej samej sesji. W przeciwnym razie tak, wystarczy tylko pętla :).
oogles