вторник, 1 сентября 2015 г.

Внезапный ступор от ssh, su, nohup и &

Сегодня одна вещь заставила поломать голову.
Допустим, у нас есть сервер, на котором есть какой-то шелл-скрипт, который хотят выполнять вот так:

$ ssh user@host sudo ./test.sh


Скрипт, например, содержит строку вида
su -c 'nohup daemon &'


Для проверки концепции я применяю sleep 100, но это не имеет значения:

#!/bin/bash

set -x
su -c 'nohup sleep 100 2>&1 > /dev/null &' root

exit 0


Логично для обычного обывателя предположить, что при выполнении скрипта он запустит некоторую команду, отвяжет ее от терминала и выйдет. Если запустить его из обычного терминала. так и произойдет:



[root@test ~]# /home/stasikos/test.sh
+ su -c 'nohup sleep 100 2>&1 > /dev/null &' root
+ exit 0
[root@test ~]# 



Однако, при запуске через ssh это работает не так :)

% ssh stasikos@172.20.1.26 sudo ./test.sh
>>> Started at 18:42:29
+ su -c 'nohup sleep 100 2>&1 > /dev/null &' root
+ exit 0

>>> elapsed time 1m41s
%



В чем же дело? После некоторых размышлений на тему, по каким словам гуглить этот случай, я набрел на http://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t
Оказалось, что шелл при запуске без терминала оказывается привязан к потокам ввода-вывода ssh, а ssh, в свою очередь, ждет их закрытия. Что не происходит из-за su -c в котором создался шелл с job-ами.

Добавление обязательного псевдотерминала в ssh этому помогает.
% ssh -t stasikos@172.20.1.26 sudo ./test.sh
>>> Started at 18:42:29
+ su -c 'nohup sleep 100 2>&1 > /dev/null &' root
+ exit 0
%


Однако, в решаемой задаче такой ключ нельзя было добавить, потому что соединение по ssh выполнялось с помощью сторонней библиотеки. Так что пришлось придумать что-то еще. А именно:

Новый скрипт:
#!/bin/bash

set -x
su -c 'nohup sleep 100 2>&1 > /dev/null &' root < /dev/null 2>&1 > /dev/null
exit 0


Пришлось отвязать su от потоков ввода-вывода, и все стало хорошо. Так же, как и при использовании ssh -t. Для меня это все было очень неочевидно. :)

3 комментария:

  1. setsid su -c 'nohup daemon &'

    по идее должно помочь.

    ОтветитьУдалить
    Ответы
    1. В следующий раз попробую, но пока и такой изврат устраивает. :)

      Удалить
    2. Нет, почему-то не помогает :( все равно приходится устраивать извраты с перенаправлениями

      Удалить