Co robi `<& -`?


20

Skopiowałem fragment Basha do tła polecenia ssh wykonanego zdalnie:

ssh user@remote <<CMD
some process <&- >log 2>error &
CMD

Co ma <&-zrobić?
Domyślam się, że to to samo co< /dev/null

Mój następny zrozumienie jest, że trzy główne deskryptory plików ( stdin, stdout, stderr) muszą być zamknięte, aby zapobiec:

  1. Zadanie jest w tle, a skrypt kończy się - jakoś sprzeczny?
  2. Kiedy terminal się zamyka, wszystkie procesy akceptujące standardowe wejście z terminala są zamykane?

Obowiązkowe odsyłacze: patrz Jakie są operatory kontroli i przekierowania powłoki? - chociaż wszystko, co mówi o tym operatorze, to to, że „można go używać do zamykania lub powielania deskryptorów plików” i powinieneś „zobaczyć odpowiednią sekcję instrukcji powłoki”.
G-Man mówi „Przywróć Monikę”

Jeśli dobrze pamiętam, ssh -nNT user@remote 'command'utworzę nieinteraktywną sesję SSH. Dołącz &do tła, dołącz nohupdo, commandaby utrzymać działanie, jeśli połączenie zostanie przerwane.
Mark K Cowan

1
@ MarkKCowan man sshsugeruje, że -N wyłącza całkowicie uruchomienie komendy zdalnej, a szybki test to obsługuje.
Tom Hunt

Ach tak, użyłem -nNTR do odwrotnego przekierowania portów. Zignoruj ​​wtedy -N i -R :)
Mark K Cowan

Odpowiedzi:


30

<&-nie jest całkiem tak samo jak < /dev/null. <&-zamyka fd 0, natomiast < /dev/nullprzekierowuje je z urządzenia /dev/null, które nigdy nie dostarcza żadnych danych i zawsze podaje EOF podczas odczytu. Różnica polega głównie na tym, że read(2)wywołanie z zamkniętego FD ( <&-przypadek) spowoduje błąd w EBADF, podczas gdy wywołanie z przekierowanego na zero FD nie zwróci odczytanych bajtów (warunek końca pliku). Jeśli twój program nigdy nie czyta ze standardowego wejścia, rozróżnienie nie ma znaczenia.

Zamykanie FD jest dobrą praktyką, jeśli tworzysz coś w tle, ponieważ proces w tle zawiesi się, jeśli spróbuje odczytać cokolwiek z TTY. Ten przykład nie obsługuje jednak wszystkiego, co powinien; idealnie byłoby gdzieś nohuplub setsidinwokacja, aby całkowicie oddzielić proces tła.


Więc powinienem używać nohupoprócz zamykania deskryptorów plików?
Eric Francis,

2
Najdokładniejsza metoda (naśladująca sposób demonizacji samych programów) jest podobna do setsid some process <&- >path/to/log 2>path/to/error. Szybsza metoda jest podobna nohup some process &.
Tom Hunt

2
@EricFrancis: Używanie nohupnie ma tutaj sensu. nohupuniemożliwić procesowi odbieranie HUPsygnału, gdy jego terminal kontrolny jest zamknięty. Ale w tym przypadku nie miałeś żadnego terminalu.
cuonglm,

@TomHunt: Proces w tle nie zawiesił się, sesja ssh się zawiesiła.
cuonglm,

2
nie jest dobrym pomysłem na zamknięcie Fds 0, 1 i 2 ... nie chcesz, aby następny FD utworzył jedną z tych wartości. lepiej przekierować ich do / dev / null
Murray Jensen,

7

Zobacz man bash:

  [n]<&word

służy do powielania deskryptorów plików wejściowych. Jeśli zostanie wordrozwinięte do jednej lub więcej cyfr, deskryptor pliku oznaczony jako njest tworzony jako kopia tego deskryptora pliku. Jeśli podane cyfry word nie określają deskryptora pliku otwartego do wprowadzenia, występuje błąd przekierowania. Jeśli słowo ma wartość -, deskryptor pliku njest zamknięty. Jeśli nnie jest określony, używane jest standardowe wejście (deskryptor pliku 0).


Prawidłowa definicja jest taka, że ​​nie jest określone, co się dzieje, gdy masz, [n]<&worda słowo zawiera więcej niż jedną cyfrę.
schily

Co masz na myśli? Czy to man bashnieprawda?
Eric Francis

@EricFrancis, ponieważ nie jest określony w standardzie, bashdecyduje się na wdrożenie go w rozsądny sposób (dla pewnej odpowiedniej definicji „rozsądny”). Inne powłoki mogą, ale nie muszą.
muru

@muru Pytanie jest oznaczony bash, nie posix-shell.
Barmar

@Barmar ok. Więc...?
muru

7

<&- zamknij standardowe wejście.

Ogólny kształt, określony przez POSIX jest:

[n]<&word

Jego celem njest utworzenie deskryptora pliku to kopia deskryptora pliku oznaczona przez word. Standardowo przyjmuje się, jeśli nzostanie pominięte, a jeśli wordtak -, to deskryptor pliku nzostanie zamknięty.

To nie to samo, co </dev/nullw przypadku </dev/nullgdy standardowe wejście wciąż się otwierało i zostało przekierowane w inne miejsce.

Musisz zamknąć wszystkie deskryptory plików procesów dołączonych do gniazda ssh, w przeciwnym razie sesja ssh nie będzie mogła zostać zamknięta.

Możesz uruchomić polecenie na zdalnym komputerze bez dołączania go do sesji ssh, używając screen lub tmux :

ssh user@remote 'screen -S test -d -m command'

Dlaczego głosowanie w dół?
cuonglm,
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.