LINUX.ORG.RU

bash, docker, sleep

 ,


0

1

Есть bash-скрипт, который запускает чего-то там в background и дальше делает sleep 100000d. Смысл в том, что юзер жмет ctrl+c, скрипт завершает выполнение и фоновые процессы прибиваются.

В докере это не работает. На ctrl+c реакции нет, stop не останавливает (ну точней останавливает тупо прибивая, когда таймаут выходит).

Пробовал: trap, trap с короткими sleep в цикле, trap с sleep в фоне и wait.

Последняя попытка:

    trap 'echo trap 0' 0
    trap 'echo trap 1' 1
    trap 'echo trap 2' 2
    trap 'echo trap 3' 3
    trap 'echo trap 13' 13
    trap 'echo trap 15' 15
    trap 'echo trap INT' INT
    trap 'echo trap STOP' STOP
    trap 'echo trap TERM' TERM
#    trap 'jobs -p | xargs --no-run-if-empty kill' STOP
    
#    sleep 100000d || true
    sleep 1 &
    while wait $!
    do
        sleep 1 &
    done

Ничего не работает. Как это правильно сделать?

Т.е. если упростить, то:

test.sh:

#!/bin/sh -eu

trap 'echo trap INT' INT

sleep 100000d || true

Dockerfile

FROM node:16

WORKDIR /root
COPY test.sh .
CMD ./test.sh
docker build -t test .
docker run --rm --name test test

Тут надо, чтобы он на Ctrl+C среагировал, напечатав что-нибудь и остановившись. Или на docker stop test в соседней вкладке. Хотя кажется это одно и то же.

Запускать docker run -t не предлагать. Оно должно в конечном итоге работать как сервис.

★★★★★

Последнее исправление: Legioner (всего исправлений: 1)

Ответ на: комментарий от urxvt

Для процесса нет, но вот драйвер терминала по Ctrl-C умеет делать рассылку сигнала по правильному списку процессов, а вручную надо будет этот список эмулировать.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Утилита docker (в команде docker run), запуская контейнер, запускает его через docker-демон. Она не становится родителем всех процессов контейнера. Следовательно передача CTRL+C дойдёт только до этой утилиты, но не до процессов контейнера. Для передачи процессам контейнера (docker run -> dockerd -> контейнер) и служит опция -t, иначе никак.

При остановке контейнера его начальному процессу сигнал SIGTERM приходит, его можно перехватывать и обрабатывать. Но вот с CTRL+C без явного заявления работы с терминалом (-t) похоже никак.

spirit ★★★★★
()
Ответ на: комментарий от Legioner

с ними ничего не делает

насколько я понимаю. в норме если нет выставленного обработчика INT, процесс киллается (дефолтное действие), но пид=1 - это особый случай, ядро вызовет обработчик, но если его нет, ничего не будет делать (не применяет дефолтного действия). entrypoint программа в докере пид=1.

ну и да, без [списоко-синтаксиа] скамливается в промежуточный шел (зато удобно).

ну и еще то, что когда шлёт терминал, он шлет не один сигнал, а всем процессам foreground group или как-то так, возможно поэтому оно и работает так хорошо с терминала.

покажи если не сложно, как ты подписываешься на SIGINT в баш-скрипте entrypoint? мне тоже может потом понадобится.

anonymous
()
Ответ на: комментарий от anonymous

насколько я понимаю. в норме если нет выставленного обработчика INT, процесс киллается (дефолтное действие)

bash точно не киляется.

$ ps 
    PID TTY          TIME CMD
 690968 pts/10   00:00:00 bash
 691052 pts/10   00:00:00 ps
$ kill 690968
$ kill -TERM 690968
$ echo lol
lol

покажи если не сложно, как ты подписываешься на SIGINT в баш-скрипте entrypoint? мне тоже может потом понадобится.

trap 'echo TERM; exit' TERM

Но важно, чтобы управление было у самого скрипта. Если тупо запустить sleep 10000d, то пока sleep не доработает, обработчик не выполнится. Поэтому я сделал трюк с wait.

Legioner ★★★★★
() автор топика
Последнее исправление: Legioner (всего исправлений: 5)
Ответ на: комментарий от Legioner

да, всё как-то запутано. возможно у него обработчик есть на терм.

https://www.gnu.org/software/bash/manual/html_node/Signals.html

кстати про sleep.

есть еще wait, но там надо вчитываться, там вроде был вариант «разблокировать по выходу любого первого субпроцесса» без явного их перечисления.

https://ahmet.im/blog/minimal-init-process-for-containers/ (там крути вниз где wait)

https://stackoverflow.com/questions/19948149/can-i-run-multiple-programs-in-a-docker-container/56663151#56663151

anonymous
()
Ответ на: комментарий от Legioner

этот легионер порвался, несите следующего.

сначала они микроскопом забивают, а отом говорят, что гвозди гнутся. ахаха, прекрати!

aol ★★★★★
()
Ответ на: комментарий от Legioner

хоспидаяяя, да где тебе всё они мерещатся? не пропускай таблетки осенью. пакааа!

aol ★★★★★
()
Ответ на: комментарий от aol

иди к черту сектант. надоели уже эти догматики-имбецилы «один-контейнер-один-кокококо». вам завтра скажут два контейнера-три-процесса - так вы будете дрочить на эту мантру, биться башкой об стену, жрать кактус и пр.

anonymous
()
Ответ на: комментарий от aol

кроме того «гвозди гнутся» точно так же когда один процесс, т.к. схема докера всё так же остаётся нестандартной: один процесс всё так же не готов к тому, чтобы быть pid=1. про зомби слышал? нет? только кукарекать можешь? тини - это костыль, внедренный впоследствии в сам докер - откуда он? оттуда что схема с одним процессом всё такая же кривая на практике, то есть она не более прямая.

вся эта мантра - один-контейнер-один-процесс философия - она не от того, что так «правильно», она идет из недостататков ну или «необычности» технологии. это же легко очень доказывается:

ваша программа пишет 5 логов, а докер умеет только stdout с stderr смешать и выплюнуть.

что предлагается? усложнить все внедрением еще 10 говнотехнологий (на изучение которых нужно еще год), не писать логи в файл, а программу объявить еретической. ну самом-то не смешно?

паттерн-то прослеживается: вся необычность докерного подхода, все его недостатки - всё это объявляется философски правильным, а всё что не соответствует или ломается - всё «кривое».

ну то есть внутри контейнера еретическая конфигурация, снаружи неправильный программист/адмни, и только один докер (контейнерный подход) стоит весь в белом.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.