Używanie SSH do zdalnego uruchamiania procesu

18

Napisałem skrypt, którego używam do wypychania i wdrażania nowej usługi na kilku maszynach pod moją kontrolą, a do wykonania procesu używam ssh do zdalnego uruchomienia procesu. Niestety, ilekroć używam SSH do uruchomienia procesu, polecenie SSH nigdy nie zwraca wartości, powodując zatrzymanie skryptu.

Polecenie jest określone jako: ssh $ użytkownik @ $ host "/ root / command &". Ilekroć uruchamiam proste polecenia, takie jak ps lub who, polecenie SSH natychmiast wraca, jednak gdy próbuję rozpocząć proces, nie zwraca. Próbowałem sztuczek, takich jak zawijanie mojego procesu w prosty skrypt bash, który uruchamia proces, a następnie kończy działanie, jednak powoduje to także zawieszenie polecenia SSH (nawet jeśli skrypt bash wyświetla komunikat o powodzeniu i kończy działanie normalnie).

Czy ktoś ma wgląd w to, co powoduje takie zachowanie i jak mogę uzyskać polecenie SSH, aby powróciło, gdy tylko proces się rozpocznie?

Dzięki za wgląd!

rmrobins
źródło
Opublikuj dokładny wiersz polecenia, którego używasz ... pomiń hasła / nazwy użytkownika / adresy IP
Joseph Kern
ssh $ SSH_USER @ $ HOST_ADDR "/ root / AppName &"
rmrobins
Powinienem wspomnieć, że skonfigurowałem klucze SSH, więc nie trzeba używać haseł do uruchamiania poleceń w zdalnych systemach.
rmrobins
@rmrobins, bardzo dobry krok - ustawienie autoryzacji klucza publicznego.
nik

Odpowiedzi:

28

SSH łączy stdin, stdout i stderr zdalnej powłoki z lokalnym terminalem, dzięki czemu można wchodzić w interakcje z poleceniem działającym po stronie zdalnej.

Jako efekt uboczny będzie działał do momentu zamknięcia tych połączeń, co dzieje się tylko wtedy, gdy zdalne polecenie i wszystkie jego elementy potomne (!) Zostaną zakończone (ponieważ elementy potomne, czyli to, co zaczyna się od „&”, dziedziczą std * po ich proces nadrzędny i pozostaw go otwartym).

Musisz więc użyć czegoś takiego

ssh user@host "/script/to/run < /dev/null > /tmp/mylogfile 2>&1 &"

<,> I 2> i 1 przekierowują stdin / stdout / stderr z twojego terminala. „&” Powoduje następnie przejście skryptu w tło. Podczas produkcji przekierowałbyś oczywiście stdin / err do odpowiedniego pliku dziennika.

Widzieć

http://osdir.com/ml/network.openssh.general/2006-05/msg00017.html

Edytować:

Właśnie dowiedziałem się, że < /dev/nullpowyższe nie jest konieczne (ale przekierowanie stdout / err jest ). Nie mam pojęcia, dlaczego ...

Śleske
źródło
Dzięki, to jest dokładnie to, czego szukałem - nie przyszło mi do głowy, że proces odziedziczy std * nawet podczas używania i uruchamiania go w tle.
rmrobins
+1! Pracuje dla mnie. Możesz także wydrukować dane wyjściowe za pomocą echa pliku dziennika: ssh user@host "/script/to/run > /tmp/ssh.stdout 2>&1 && cat /tmp/ssh.stdout && rm -f /tmp/ssh.stdout"
Fishdrowned
5

Możesz spróbować nohup . Człowieku nohup po więcej szczegółów.

ssh host "nohup script &"

Jeśli chcesz zachować dane wyjściowe na zdalnym komputerze, oto wariant .

ssh user@host 'export REMOTE=myname; nice nohup ./my-restart >
logfile.log 2>&1 &'
Jauder Ho
źródło
5

Inną alternatywą byłoby odpalenie wolnostojącego screen(1), coś takiego:

ssh -l user host "screen -d -m mycommand"

Spowoduje to uruchomienie odłączonego ekranu (który przechwytuje wszystkie zawarte w nim interakcje), a następnie natychmiast powróci, kończąc sesję ssh.

Przy odrobinie pomysłowości możesz w ten sposób rozwiązywać dość złożone zdalne polecenia.

towo
źródło
4
 -f      Requests ssh to go to background just before command execution.
         This is useful if ssh is going to ask for passwords or
         passphrases, but the user wants it in the background.  This
         implies -n.  The recommended way to start X11 programs at a
         remote site is with something like ssh -f host xterm.

         If the ExitOnForwardFailure configuration option is set to “yes”,
         then a client started with -f will wait for all remote port for‐
         wards to be successfully established before placing itself in the
         background.
Miś
źródło
1
Problem z tą metodą polega na tym, że polecenie SSH nie jest faktycznie zakończone, jest po prostu ukryte w tle, więc host uruchamiający skrypt będzie miał w tle dużą liczbę poleceń SSH, które nigdy nie powrócą, ponieważ polecenia SSH nigdy nie zwracają ( tzn. główny problem, który chcę rozwiązać)
rmrobins
-1

Myślę, że byłby to właściwy sposób

ssh user@host exec script.sh &
nik
źródło
Nie, to mi nie działa. Dlaczego warto
sleske,
Nie użyłem push-up w tle nad ssh, próbowałem bez terminu. mój błąd.
nik