Pobieranie ssh w celu wykonania polecenia w tle na maszynie docelowej

304

To jest kolejne pytanie: Jak używać ssh w skrypcie powłoki? pytanie. Jeśli chcę wykonać polecenie na zdalnym komputerze, który działa w tle na tym komputerze, w jaki sposób mogę zwrócić polecenie ssh? Kiedy próbuję po prostu wstawić znak ampersand (&) na końcu polecenia, po prostu się zawiesza. Dokładna forma polecenia wygląda następująco:

ssh user@target "cd /some/directory; program-to-execute &"

Jakieś pomysły? Należy zwrócić uwagę na to, że logowanie do komputera docelowego zawsze tworzy baner tekstowy i mam skonfigurowane klucze SSH , więc hasło nie jest wymagane.

dagorym
źródło

Odpowiedzi:

315

Miałem ten problem w programie napisanym rok temu - okazuje się, że odpowiedź jest dość skomplikowana. Musisz użyć nohup, jak również przekierowania danych wyjściowych, jak wyjaśniono w artykule na Wikipedii o nohup , skopiowanym tutaj dla twojej wygody.

Zadania bez tła są przydatne na przykład po zalogowaniu przez SSH, ponieważ zadania w tle mogą powodować zawieszanie się powłoki podczas wylogowywania z powodu wyścigu [2]. Problem ten można również rozwiązać poprzez przekierowanie wszystkich trzech strumieni we / wy:

nohup myprogram > foo.out 2> foo.err < /dev/null &
Jax
źródło
1
Te pliki są tworzone w bieżącym katalogu. Zatem limitem jest ilość wolnego miejsca na partycji. Oczywiście możesz również przekierować na /dev/null.
Frank Kusters
2
Jakieś pomysły na tło procesu po jego zakończeniu z pytaniami? (jak gpg - deszyfrowanie, które zakończyło się pytaniem o hasło)
isaaclw
Próba uruchomienia procesu resque w tle za pomocą nohup, ale to nie działa; .. :(
Infant Dev
1
Czy możesz wyjaśnić, co to < /dev/nullznaczy? Dzięki.
Qian Chen,
1
Również z artykułu w Wikipedii o nohup: „Zauważ też, że zamykająca sesja SSH nie zawsze wysyła sygnał HUP do zależnych procesów. Między innymi zależy to od tego, czy pseudo-terminal został przydzielony, czy nie”. Tak więc, chociaż nie zawsze konieczne jest nohup, lepiej z nim korzystać na dłuższą metę niż bez niego.
Jax
254

To był dla mnie najczystszy sposób: -

ssh -n -f user@host "sh -c 'cd /whereever; nohup ./whatever > /dev/null 2>&1 &'"

Jedyne, co działa po tym, to rzeczywiste polecenie na zdalnym komputerze

Russ
źródło
7
-nnie jest potrzebne, jak -fsugeruje-n
blissini
6
ssh -fpozostawia proces ssh podłączony, tylko w tle. Rozwiązania / dev / null pozwalają ssh na szybkie rozłączenie, co może być preferowane.
Beni Cherniavsky-Paskin
To rozwiązanie działa również w przypadku wysyłania poleceń za pośrednictwem ssh na serwer NAS firmy Syonology
Stefan F
Potrzebuję wyników „ls -l”, aby pokazać się na moim pilocie, to polecenie tego nie robi.
Siddharth,
@ Siddharth Następnie przekieruj do nazwanego pliku zamiast / dev / null.
sherrellbc
29

Przekieruj fd's

Wyjście musi zostać przekierowane, za pomocą &>/dev/nullktórego przekierowuje zarówno stderr, jak i stdout do / dev / null i jest synonimem >/dev/null 2>/dev/nulllub >/dev/null 2>&1.

Parantheses

Najlepszym sposobem jest użycie sh -c '( ( command ) & )'wszędzie tam, gdzie polecenie jest czymkolwiek.

ssh askapache 'sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Nohup Shell

Możesz także użyć nohup bezpośrednio do uruchomienia powłoki:

ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'

Niezły start

Inną sztuczką jest użycie nicea do uruchomienia polecenia / powłoki:

ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/askapache.com &>/dev/null ) & )"'
AskApache Webmaster
źródło
8
Wiem, że jest to bardzo stara odpowiedź, ale czy mógłbyś dodać kilka uwag na temat tego, dlaczego nawiasy są najlepszym sposobem, jakie (jeśli w ogóle) różnice dodaje nohupi dlaczego i kiedy chcesz je wykorzystać nice? Myślę, że wiele by to dodało do tej odpowiedzi.
Dr K
Może częściowo odpowiedzieć na to pytanie: W przypadku nohup nie trzeba dołączać polecenia & do polecenia, aby uruchomić.
Cadoiz,
21

Jeśli nie możesz / nie możesz pozostawić otwartego połączenia, możesz użyć ekranu , jeśli masz uprawnienia do jego zainstalowania.

user@localhost $ screen -t remote-command
user@localhost $ ssh user@target # now inside of a screen session
user@remotehost $ cd /some/directory; program-to-execute &

Aby odłączyć sesję ekranu: ctrl-a d

Aby wyświetlić listę sesji ekranowych:

screen -ls

Aby ponownie dołączyć sesję:

screen -d -r remote-command

Pamiętaj, że screen może również tworzyć wiele powłok w ramach każdej sesji. Podobny efekt można uzyskać dzięki tmux .

user@localhost $ tmux
user@localhost $ ssh user@target # now inside of a tmux session
user@remotehost $ cd /some/directory; program-to-execute &

Aby odłączyć sesję tmux: ctrl-b d

Aby wyświetlić listę sesji ekranowych:

tmux list-sessions

Aby ponownie dołączyć sesję:

tmux attach <session number>

Domyślny klucz kontrolny tmux, ' ctrl-b', jest nieco trudny w użyciu, ale istnieje kilka przykładowych konfiguracji tmux dostarczanych z tmux, które możesz wypróbować.

hometoast
źródło
3
jak by to wykorzystać screen?
Quamis
18

Chciałem tylko pokazać działający przykład, który możesz wyciąć i wkleić:

ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\""
cmcginty
źródło
Bardzo pomocny. Dzięki.
Michael Martinez,
8

Najszybszym i najłatwiejszym sposobem jest użycie polecenia „at”:

ssh user @ target "at now -f /home/foo.sh"

neil
źródło
2
Byłoby to świetne ogólne rozwiązanie, gdyby atzaakceptowano argumenty wiersza poleceń po czasie, a nie tylko z pliku.
Tyler Collier
3
Możesz symulować plik za pomocą <<< jak w: ssh user @ target "at -f <<< 'my_comnads'"
Nico
6

Myślę, że będziesz musiał połączyć kilka z tych odpowiedzi, aby uzyskać to, czego chcesz. Jeśli użyjesz nohup w połączeniu ze średnikiem i zawiniesz całość w cudzysłów, otrzymasz:

ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null"

co wydaje mi się działać. Bez nohup nie musisz dołączać polecenia & do polecenia, aby je uruchomić. Ponadto, jeśli nie musisz czytać żadnych danych wyjściowych polecenia, możesz użyć

ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1"

przekierować wszystkie dane wyjściowe do / dev / null.


źródło
5

To działało dla mnie razy:

ssh -x remoteServer "cd yourRemoteDir; ./yourRemoteScript.sh </dev/null >/dev/null 2>&1 & " 
fs82
źródło
2

Możesz to zrobić w ten sposób ...

sudo /home/script.sh -opt1 > /tmp/script.out &
użytkownik889030
źródło
Idealnie, współpracuje z sesją PuTTY SSH. Mogę wyjść, a skrypt kontynuuje działanie na komputerze. Dziękuję Ci.
Satria,
1

Właściwie za każdym razem, gdy muszę uruchomić polecenie na skomplikowanym komputerze zdalnym, lubię umieścić polecenie w skrypcie na komputerze docelowym i po prostu uruchomić ten skrypt za pomocą ssh.

Na przykład:

# simple_script.sh (located on remote server)

#!/bin/bash

cat /var/log/messages | grep <some value> | awk -F " " '{print $8}'

A potem po prostu uruchamiam to polecenie na maszynie źródłowej:

ssh user@ip "/path/to/simple_script.sh"
PaulT
źródło
0

Próbowałem zrobić to samo, ale z dodatkową złożonością próbowałem to zrobić z Javy. Tak więc na jednej maszynie z Javą próbowałem uruchomić skrypt na innej maszynie w tle (bez nohup).

Z wiersza poleceń oto, co zadziałało: (możesz nie potrzebować pliku „-i keyFile”, jeśli nie potrzebujesz go do ssh na hoście)

ssh -i keyFile user@host bash -c "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\""

Zauważ, że w moim wierszu poleceń po „-c” jest jeden argument, który jest w cudzysłowie. Ale żeby zadziałał na drugim końcu, wciąż potrzebuje cytatów, więc musiałem umieścić w nim cytaty uciekające.

Z Java: oto, co zadziałało:

ProcessBuilder b = new ProcessBuilder("ssh", "-i", "keyFile", "bash", "-c",
 "\"nohup ./script arg1 arg2 > output.txt 2>&1 &\"");
Process process = b.start();
// then read from process.getInputStream() and close it.

Minęło trochę prób i błędów, aby to działało, ale wydaje się, że teraz działa dobrze.

Randy Wilson
źródło
0

Wydawało mi się dość wygodne mieć zdalną sesję tmux przy użyciu następującej tmux new -d <shell cmd>składni:

ssh someone@elsewhere 'tmux new -d sleep 600'

Spowoduje to uruchomienie nowej sesji na elsewherehoście, a polecenie ssh na komputerze lokalnym powróci niemal natychmiast do powłoki. Następnie możesz ssh do zdalnego hosta i tmux attachdo tej sesji. Zauważ, że nie ma nic o działającym lokalnym tmuxie, tylko zdalny!

Ponadto, jeśli chcesz, aby sesja trwała po zakończeniu zadania, po prostu dodaj program uruchamiający powłokę po komendzie, ale nie zapomnij dołączyć cudzysłowu:

ssh someone@elsewhere 'tmux new -d "~/myscript.sh; bash"'
zebrilo
źródło
0
YOUR-COMMAND &> YOUR-LOG.log &    

Powinno to uruchomić komendę i przypisać identyfikator procesu, który możesz po prostu -f YOUR-LOG.log, aby zobaczyć zapisane wyniki. możesz się wylogować w dowolnym momencie, a proces będzie kontynuowany

richprice316
źródło
0

Możesz to zrobić bez nohup:

ssh user@host 'myprogram >out.log 2>err.log &'
ijt
źródło
-2

Myślę, że właśnie tego potrzebujesz: Najpierw musisz zainstalować sshpassna swoim komputerze. możesz napisać własny skrypt:

while read pass port user ip; do
sshpass -p$pass ssh -p $port $user@$ip <<ENDSSH1
    COMMAND 1
    .
    .
    .
    COMMAND n
ENDSSH1
done <<____HERE
    PASS    PORT    USER    IP
      .      .       .       .
      .      .       .       .
      .      .       .       .
    PASS    PORT    USER    IP    
____HERE
MLSC
źródło
-3

Najpierw wykonaj tę procedurę:

Zaloguj się jako użytkownik A i wygeneruj parę kluczy uwierzytelniających. Nie wpisuj hasła:

a@A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa): 
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A

Teraz użyj ssh, aby utworzyć katalog ~ / .ssh jako użytkownik b na B. (katalog może już istnieć, co jest w porządku):

a@A:~> ssh b@B mkdir -p .ssh
b@B's password: 

Na koniec dołącz nowy klucz publiczny a do b @ B: .ssh / Author_keys i wprowadź hasło b po raz ostatni:

a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
b@B's password: 

Od teraz możesz zalogować się do B jako b z A jako bez hasła:

a@A:~> ssh b@B

to zadziała bez wprowadzania hasła

ssh b @ B "katalog cd / some /; program do wykonania &"

Kevin Duterne
źródło
1
Pytanie mówi, że dagorym już ustawił klucze tak, aby nie wymagały hasła, ale nadal się zawiesza
Max Nanasy