Оператор bash && предотвращает фоновую обработку по ssh - PullRequest
7 голосов
/ 29 марта 2012

После попытки выяснить, почему задача Capistrano (которая пыталась запустить демон в фоновом режиме) зависла, я обнаружил, что использование && в bash over ssh предотвращает запуск последующей программы в фоновом режиме.Я пробовал это на bash 4.1.5 и 4.2.20.

В bash будет зависать следующее (т. Е. Ждать завершения sleep):

ssh localhost "cd /tmp && nohup sleep 10 >/dev/null 2>&1 &"

Следующее не будет:

ssh localhost "cd /tmp ; nohup sleep 10 >/dev/null 2>&1 &"

И этого не будет:

cd /tmp && nohup sleep 10 >/dev/null 2>&1 &

И zsh, и dash будут выполнять его в фоновом режиме во всех случаях, независимо от && и ssh.Это нормальное / ожидаемое поведение для bash или ошибка?

Ответы [ 2 ]

4 голосов
/ 30 марта 2012

Одним из простых решений является использование:

ssh localhost "(cd /tmp && nohup sleep 10) >/dev/null 2>&1 &"

(это также работает, если вы используете фигурные скобки, см. Второй пример ниже).

Я не экспериментировал дальше, но я разумно убежден, что это связано с открытыми дескрипторами файлов. Возможно, zsh и dash связывают && так, что это означает, что должно быть записано как:

{ cd /tmp && nohup sleep 10; } >/dev/null 2>&1

в bash.


Нет, быстрый эксперимент в dash показывает, что echo foo && echo bar >file только перенаправляет последнее. Тем не менее, это как-то связано с длительным открытием fd, заставляющим ssh ждать большего вывода; Я сталкивался с этим много в прошлом.
Еще один трюк, который не нужен, если вы используете скобки или фигурные скобки для этого конкретного случая, но может быть полезен в более общем контексте, где набор команд для && более сложный. Поскольку bash, похоже, неправильно использует дескриптор файла с &&, но не с ;, вы можете превратить a && b && c в a || exit 1; b || exit 1; c. Это работает с тестовым примером:
ssh localhost "true || exit 1; echo going on; nohup sleep 10 >/dev/null 2>&1 &"

Заменить true на false, и эхо "происходит" пропущено.

(Вы также можете set -e, хотя иногда это больше, чем хотелось бы.)

1 голос
/ 30 марта 2012

Это похоже на работу:

ssh localhost "(exec 0>&- ; exec 1>&-; exec 2>&-; cd /tmp; sleep 20&)"
...