Що робить `<& -`?


20

Я скопіював фрагмент Bash у фонову команду ssh, що виконується віддалено:

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

Що робить <&-?
Я здогадуюсь, що це те саме, що< /dev/null

Моє наступне розуміння , що три основні файлові дескриптори ( stdin, stdout, stderr) повинні бути закриті , щоб запобігти:

  1. Робота, яку виконують у фоновому режимі, і сценарій, що виходить - якось конфліктують?
  2. Коли термінал закривається, всі процеси, які приймають stdin від терміналу, закриваються?

Обов’язкове перехресне посилання. Див., Що таке оператори управління та перенаправлення оболонки? - хоча все, що говорить про цього оператора, полягає в тому, що він "може використовуватися для закриття або копіювання дескрипторів файлів", і ви повинні "переглянути відповідний розділ керівництва вашої оболонки".
G-Man каже: "Відновіть Моніку"

Якщо я пам'ятаю правильно, ssh -nNT user@remote 'command'створить неінтерактивний сеанс SSH. Додайте &до фону, додайте nohupдо, commandщоб продовжувати працювати, якщо ваше з'єднання загине.
Марк К Коуан

1
@MarkKCowan man sshприпускає, що -N повністю відключає запуск віддаленої команди, і швидкий тест це підтримує.
Том Хант

Ага так, я використовував -nNTR для зворотного переадресації портів. Ігноруйте -N та -R тоді :)
Марк К Коуан

Відповіді:


30

<&-не зовсім те саме, що < /dev/null. <&-закриває fd 0, тоді як < /dev/nullперенаправляє його з пристрою /dev/null, який ніколи не надає жодних даних і завжди дає EOF при прочитанні. Різниця полягає в тому, що read(2)виклик із закритого FD ( <&-випадок) буде помилковим з EBADF, тоді як виклик з FD, перенаправлений з нулем, не повертає жодних байтів (стан кінця файлу). Якщо ваша програма ніколи не читає з stdin, відмінність не має значення.

Закриття FD - це хороша практика, якщо ви щось вирішуєте, оскільки фоновий процес зависне, якщо він намагається прочитати що-небудь з TTY. Цей приклад не повністю справляється з усім, що повинен; в ідеалі десь буде nohupабо setsidвиклик, щоб повністю роз'єднати фоновий процес.


Тому мені слід використовувати nohupдодатково закриття дескрипторів файлів?
Ерік Френсіс

2
Найбільш ретельний метод (який наслідує те, як програми демонструють себе) - це щось подібне setsid some process <&- >path/to/log 2>path/to/error. Швидший метод - це щось на кшталт nohup some process &.
Том Хант

2
@EricFrancis: Використовувати nohupтут немає сенсу. nohupзапобігти прийому HUPсигналу процесу, коли його керуючий термінал закритий. Але у вас в цьому випадку не було жодного терміналу.
cuonglm

@TomHunt: фоновий процес не висів, ssh сесія.
cuonglm

2
не гарна ідея закрити Fds 0, 1 і 2 ... ви не хочете, щоб наступний fd, створений для отримання одного з цих значень. краще перенаправити їх на / dev / null
Мюррей Дженсен

7

Дивіться man bash:

  [n]<&word

використовується для дублювання дескрипторів вхідних файлів. Якщо wordрозгортається до однієї або декількох цифр, дескриптор файлу, позначений символом, nробиться копією цього дескриптора файлу. Якщо в цифрах word не вказано дескриптор файлу, відкритий для введення, виникає помилка перенаправлення. Якщо слово оцінюється на -, дескриптор файлу nзакритий. Якщо nце не вказано, використовується стандартний вхід (дескриптор файлу 0).


Правильне визначення полягає в тому, що не визначено, що відбувається, коли у вас є, [n]<&wordа слово містить більше однієї цифри.
schily

Що ви маєте на увазі? Є man bashнеправильним?
Ерік Френсіс

@EricFrancis, оскільки він не визначений у стандарті, bashобирає його реалізовувати здоровим способом (для певного визначення поняття "здоровий"). Інші снаряди можуть чи не можуть цього робити.
муру

@muru Питання позначене тегом bash, ні posix-shell.
Бармар

@Barmar добре. Так...?
муру

7

<&- закрити стандартний вхід.

Загальний вигляд, який визначається POSIX , є:

[n]<&word

Її мета виготовити дескриптор файлу n- це копія дескриптора файлу, позначена символом word. Стандартний в припускається, якщо nвін пропущений, а якщо wordє -, дескриптор файлу nбуде закритий.

Це не те саме, що </dev/null, коли в разі </dev/null, стандартний вхід все-таки відкривався і був перенаправлений на інше місце.

Потрібно закрити всі дескриптори файлів процесів, які були прикріплені до ssh socket, інакше ssh сеанс не може закритися.

Ви можете запустити команду на віддаленій машині, не додаючи її до ssh сесії, використовуючи екран або tmux :

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

Чому голосування проти?
cuonglm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.