ssh i shell przez ssh: jak wyjść?


22

Uruchamiam odległy skrypt za pośrednictwem SSH w następujący sposób:

ssh user@ipaddress '~/my_script.sh'

Wszystko idzie dobrze, ale po zakończeniu skryptu połączenie nie jest zamykane. Muszę nacisnąć CTRL-C, aby przerwać bieżące połączenie.

Próbowałem polecenia „exit” w pliku „~ / my_script.sh” i jest to bezużyteczne. Wypróbowałem polecenie „wyloguj się” w pliku „~ / my_script.sh” i otrzymuję komunikat:

logout: not login shell: use exit

...

Masz pomysł, jak mogę zrobić automatyczne i prawidłowe zamknięcie SSH po zakończeniu skryptu?

(Modyfikacja w celu wyjaśnienia :) Oto, co jest w moim skrypcie:

#!/bin/sh
path_sources_qas=/sources/QuickAddress/
path_qas_bin=/usr/bin/qas

umount_disque_qas()
{
  # Umount du disque 'qas' s'il n'avait pas été 'umount' :
  nom_disque_monte=`cat /etc/mtab | grep qas | awk '{ print $2}'`
  if [ "$nom_disque_monte" != "" ]
  then
    echo "For safety, umount : $nom_disque_monte"
    umount $nom_disque_monte
  fi

}

# Umount twice (we never know if a st***d guy mounted it twice) :
umount_disque_qas
umount_disque_qas

echo "--------------------------------"
echo "Install ISO quick address..."
nom_fichier_iso=`ls -t $path_sources_qas | awk '{if (NR==1) {print $1}}'`
echo "Mount disk $nom_fichier_iso..."
mount -o loop -t iso9660 $path_sources_qas/$nom_fichier_iso /mnt/qas
echo "Done."

# All the folders are like this :
# /usr/bin/qas/Data.old.10
# /usr/bin/qas/Data.old.11
# /usr/bin/qas/Data.old.12
# ...

echo "--------------------------------"
echo "Stopping QuickAdress server..."
cd $path_qas_bin/apps/
./wvmgmtd shutdown qaserver:2021
sleep 3
echo "Done."

# Get last number of the folder:
num_dernier_dossier_backup=`ls -Atd $path_qas_bin/Data.old* | awk '{if (NR==1) {print $1}}' | awk -F . '{print $NF}'`
# Add 1 :
let "num_dernier_dossier_backup += 1"
# Full name :
nom_dossier_backup=Data.old.$num_dernier_dossier_backup
echo "--------------------------------"
echo "Saving Data to $nom_dossier_backup..."
cd $path_qas_bin
mv Data $nom_dossier_backup
echo "Done."


echo "--------------------------------"
echo "Copying new folder Data..."
cd $path_qas_bin
cp -r /mnt/qas/Data .
echo "Done."

echo "--------------------------------"
echo "Deleting unused datas..."
cd $path_qas_bin/apps/
rm -f $path_qas_bin/Data/frxmos.dap
echo "Done."

echo "--------------------------------"
echo "Restart server..."
cd $path_qas_bin/apps/
./qaswvd &
sleep 3
echo "Done."
sleep 3

echo "--------------------------------"
echo "Check: server state: you should read 'OK':"
./wvmgmtd srvlist
echo "Done."

echo "--------------------------------"
echo "Check: active licences (only one here):"
./wvmgmtd licencelistread qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: counters: number of addresses left:"
./wvmgmtd counterinforead qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: Datasets avalaibles:"
./wvmgmtd datalistread current qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Check: "meters" for "licence by click":"
./wvmgmtd meterslistread current qaserver:2021
echo "Done."

echo "--------------------------------"
echo "Removing virtual disk..."
umount_disque_qas
echo "Done."

echo "All done"
echo "Click 'Ctrl-C' to quit."

exit

Kiedy uruchamiam go za pośrednictwem SSH, działa, a na koniec czytam „Wszystko gotowe”. oznacza to, że osiąga ostatnie 2 linie .

Każdy pomysł, jak mogę zrobić, aby zamknąć automatycznie i pr


1
Co jest w skrypcie?
Ignacio Vazquez-Abrams,

@Olivier: Czy przekazujesz jakieś porty (w tym agent i X)? Połączenie ssh zostaje zamknięte, gdy polecenie zostanie zakończone, a wszystkie połączenia TCP zostaną zamknięte.
Gilles „SO- przestań być zły”

@Gilles: nie, po prostu nawiązuję połączenie z powłoką, aby uruchomić skrypt, nic nie jest przekazywane.
Olivier Pons,

1
@Olivier: Jeśli masz ~/.ssh/config, spróbuj bez niego i podaj opcje -a -x(i nie -o), sshaby upewnić się, że nie będzie dalej przekazywane. Jeśli nadal nie działa, pokaż zawartość skryptu.
Gilles „SO- przestań być zły”

@Olivier: czy skrypt uruchamia jakieś zadanie w tle, na które może czekać? Niestety zadania nie wydają się niczego zwracać w skrypcie ssh. Przykład: ssh <yourusername>@localhost '(ls; sleep 10 &); echo Done; jobs'wyświetli listę plików, wyświetli gotowe i zaczeka 10 sekund przed powrotem.
asoundmove,

Odpowiedzi:


19

Wyjście w skrypcie powłoki nie działa, ponieważ wychodzi ze skryptu, a nie z powłoki. Aby wyjść z powłoki po zakończeniu skryptu, wykonaj

ssh user@ipaddress '~/my_script.sh && exit'

Spowoduje to uruchomienie skryptu, a następnie wyjście z powłoki.


3
Powinno być ekscytujące. Skrypt jest powłoką.
Wstrzymano do odwołania.

@Dennis: To nie działa dla niego, więc to może działać zamiast tego.
Wuffers,

2
@Pan. Mężczyzna: Twoje polecenie jest równoważne z oryginałem, z tym wyjątkiem, że zmusza powłokę do istnienia między sshdpowłoką i działającą powłoką myscript.sh. exitNapisałeś będzie działać, gdy wyjść skrypt, który nie pomaga. Jedynym sposobem, w jaki twoje rozwiązanie mogłoby działać, jest skrypt, który robi coś dziwnego, gdy jego rodzic jest, sshdi nie robi tego dziwnego, gdy jego rodzic jest powłoką.
Gilles „SO- przestań być zły”

Jak to nie pomaga? Wyjście zamknie powłokę i zakończy połączenie, prawda? I czy nie tego chce plakat?
Wuffers

3
@MrMan: ~/my_script.sh && exitwychodzi, gdy tylko ~/my_script.shwychodzi. Gdyby skrypt powłoki nie zakończył działania, twoje polecenie i tak nigdy by się nie udało exit. Więc to jest po prostu bezużyteczne.
Gilles „SO- przestań być zły”

12

Połączenie ssh pozostaje otwarte po zakończeniu procesu uruchomionego przez ssh (tutaj powłoka), jeśli istnieją inne procesy, które nadal go używają. Nie znam dokładnych zasad, których przestrzega demon ssh, ale połączenie jest używane, przynajmniej jeśli standardowe wyjście dowolnego procesu potomnego jest nadal podłączone do pierwotnego potoku dostarczonego przez ssh. Porównać:

ssh somehost 'sleep 5 &'  # exits after 5 seconds
ssh somehost 'sleep 5 >/dev/null &'  # exits immediately seconds

Po uruchomieniu demona powinieneś go ustawić w tle i zamknąć deskryptory plików. Przynajmniej użyj tego:

./qaswvd </dev/null >/dev/null 2>/dev/null &

Możesz dodać nohupz przodu; nie zrobi to żadnej różnicy, ale przydałoby się, gdyby skrypt był uruchamiany z terminala. Wiele programów zaprojektowanych do działania jako demony ma opcje wiersza polecenia umożliwiające rozwidlenie, zamknięcie deskryptorów plików, zignorowanie sygnałów i innych drobiazgów. Sprawdź w qaswvddokumentacji, jeśli ma taką. Możesz także zbadać narzędzia „demonizatora”.


Miałem ten sam problem i to działa. Akceptowana odpowiedź nie działa.
Andy,

5

Widziałem ten post, gdy szukałem rozwiązania tej samej sytuacji. Chociaż jest trochę za późno na rozwiązanie problemu @ Oliver, ponieważ zaakceptowana odpowiedź najwyraźniej nie działała ani dla OP, ani dla mnie (nie wiem, dlaczego została zaakceptowana), nadal chciałbym opublikować własne rozwiązanie dla przyszłego googlera. To proste: dodaj -fopcję w sshpoleceniu:

ssh -f user@ipaddress '~/my_script.sh'

EDYTOWAĆ

Efektem tej -fopcji jest umieszczenie jej sshw tle, więc bez żadnej dodatkowej opcji możliwe jest, że połączenie wciąż żyje, nawet jeśli wydaje się, że jest zerwane. W razie zainteresowania można odnieść się do odpowiedzi udzielonej w innym poście na tej stronie.


Uwaga: To (-f) nie będzie działać, jeśli oryginalny skrypt ma monit (y) o podanie danych przez użytkownika.
madD7

3

Podobnie jak Ignacio, ciekawi mnie, co jest w twoim skrypcie.

Być może mógłbyś spróbować zredukować skrypt do najmniejszego możliwego przykładu, który powoduje wystąpienie błędu.

Lub zacznij od pustego skryptu i dodaj polecenie na raz, aż zobaczysz problem, a wtedy będziesz wiedział, które polecenie powoduje zablokowanie skryptu.

Jeśli pusty skrypt powoduje problem, możesz sprawdzić konfigurację ssh, na przykład .bash_logout lub inne wywołane przy wyjściu, które może powodować problem?


Dziękuję za sugestię, teraz dodałem próbkę mojego skryptu do mojego pytania.
Olivier Pons,

@Olivier: Dodano tylko nieistotne części skryptu. Opublikuj skrypt (i instrukcje użytkowania, jeśli to konieczne), które pozwolą czytelnikom odtworzyć Twój problem . Uprość skrypt tak bardzo, jak to możliwe, ale nie dalej.
Gilles 'SO - przestań być zły'

@Gilles Dziękuję. Zmodyfikowałem moje pytanie i dodałem cały skrypt. Mam nadzieję że to pomoże. Wygląda na to, że problemem może być fakt, że uruchamiam proces w tle ( wiersz „./qaswvd &” ). Czy to może być przyczyna problemu?
Olivier Pons,

1
@Olivier: Tak, główny proces będzie czekał na zakończenie procesu w tle przed zakończeniem. Jeśli chcesz, aby coś nadal działało po wyjściu, możesz spróbować nohup. Nie jestem pewien, czy to działa z ssh, ale spróbuj, nie zaszkodzi.
asoundmove 20.01.11

2

Prawdopodobnie możesz użyć zadań w swoim skrypcie. W takim przypadku shell po prostu czeka na zakończenie zadań i nie chce się odłączyć.

Nie zamierzam ponownie publikować, po prostu prześlę Ci http://en.wikipedia.org/wiki/Nohup#Existing_jobs


Zmodyfikowałem moje pytanie i dodałem cały skrypt. Mam nadzieję że to pomoże. Wygląda na to, że problemem może być to, że uruchamiam proces w tle (wiersz „./qaswvd &”). Jeśli masz rację, może to być przyczyna problemu?
Olivier Pons,

Problemem jest proces w tle, ale nohupnie jest on bezpośrednio problemem, ponieważ nie ma terminala po stronie serwera: Myślę, że winowajcą jest konkretnie deskryptor otwartego pliku.
Gilles „SO- przestań być zły”

Tak, myślę, że to jest problem, możesz spróbować to skomentować lub zastosować hack z linku powyżej
Oleksiy Khilkevich


0

Problem jest prawdopodobnie następujący.

./qaswvd &

To polecenie prawdopodobnie nadal działa i utrzyma otwartą rurkę ssh, dopóki stdin oraz stdout i stderr nie zostaną zamknięte.

Użyj tego zamiast:

./qaswvd </dev/null >/dev/null 2>&1 &
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.