дальнейшее чтение

дальнейшее чтение

man 7 daemon

Когда запускается традиционный демон SysV, он должен выполнить следующие шаги в рамках инициализации. Обратите внимание, что эти шаги не нужны для демонов нового стиля (см. ниже) и должны быть реализованы только в том случае, если совместимость с SysV имеет важное значение.

[...]

6. В дочернем процессе вызовите setsid(), чтобы отсоединиться от любого терминала и создать независимый сеанс.

7. В дочернем процессе снова вызовите fork(),чтобы гарантировать, что демон никогда больше не сможет повторно захватить терминал.

но сравните это с процессами, запущенными без малейшего признака совместимости с SysV:

$ ps -efj
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
root         1     0     1     1  0 May10 ?        00:06:44 /sbin/init
...
root       185     1   185   185  0 May10 ?        00:09:48 /lib/systemd/systemd-journald
root     16434     1 16434 16434  0 May26 ?        00:00:11 /usr/sbin/rsyslogd -n

Процессы для обоих rsyslog.serviceи systemd-journal.serviceявляются лидерами сеансов (SID = PID).

Кажется, что если бы такие программы были настроены на запись в TTY, они бы получили TTY в качестве управляющего терминала и получили бы нежелательный / фатальный сигнал, когда TTY зависает / получает Ctrl+C, соответственно. Если только они не вспомнят установить O_NOCTTY при открытии файла TTY.

Кажется, это небольшая ловушка при написании или конвертации программы для запуска в качестве службы systemd без какой-либо совместимости с SysV, если ваша программа поддерживает запись сообщений в пользовательские файлы. Похоже, что в этом документе, который пропагандирует стиль systemd, на это не указано. Документ скорее подразумевает обратное, настаивая на том, что double-fork необходим для избежания этого в SysV, а затем не упоминая это как проблему при описании шагов, которые будет использовать собственная служба systemd.

Это правильно? Предоставляет ли systemd какую-то защиту от этого, о чем я умолчал, или проблема указана в другом месте в документации systemd?

решение1

Обеспечивает ли systemd какую-либо защиту от этого […]?

Вы предполагаете, что это должно быть так. Напротив, рассмотрите такие настройки, как TTYPathи такие услуги, как [email protected]. Возможность получить управляющий терминал на самом деленеобходимый, чтобы управление услугами могло охватывать услуги входа в систему TTY, которые должны делать именно это.

На самом деле от этого защищает отход от автоматического выделения управляющего терминала в open()и отказ от старой семантики. Илибызащитить от этого. Это не относится к Linux, но в FreeBSD, NetBSD, OpenBSD и Hurd в настоящее время флаг O_NOCTTYto open()совершенно излишен.толькоспособ получить управляющий терминал — явно потребовать его, с помощью ioctl(…TIOSCTTY). Это фактически имело место в течение почти четверти века, со времен 4.4BSD.

В то же время, привычка работать с Linux — это привычка, которая существовала уже долгое время, задолго до systemd:O_NOCTTYповсюду. ☺

(Да, библиотеки GNU и musl C не предоставляют вам этого fopen(). Это одна из нескольких причин, по которым fdopen()этот механизм по-прежнему полезен.)

Управление службами с помощью набора инструментов nosh service-managerпринимает несколько иной подход. Вместо того, чтобы всегда делать процессы демонов лидерами сеансов, каждая служба выделяет свой собственный объект сеанса ядра, который затем не видит использования, только определенные службы также setsidявно объединяются в цепочку; например, службы, которые используют , службы, где, конечно, устанавливается управляющий терминал, и службы. (Как отмечено в исходном коде службы, вызывает себя.)ttylogin@*open-controlling-ttyagetty@*agettygetty@*mgettysetsid()

дальнейшее чтение

решение2

systemd не защищает служебные программы от получения управляющего терминала. Они должны защищать себя при открытии указанных пользователем файлов журналов, используя флаг O_NOCTTY.

$ rpm -q systemd
systemd-238-8.git0e0aa59.fc28.x86_64

$ systemctl cat test
# /etc/systemd/system/test.service
[Service]
Type=simple
ExecStart=/bin/sh -c "exec cat </dev/tty10 >/dev/tty10"

$ systemctl status test
● test.service
   Loaded: loaded (/etc/systemd/system/test.service; static; vendor preset: disabled)
   Active: active (running) since Fri 2018-06-01 11:28:41 BST; 1min 35s ago
 Main PID: 12173 (cat)
    Tasks: 1 (limit: 4915)
   Memory: 180.0K
   CGroup: /system.slice/test.service
           └─12173 cat

Jun 01 11:28:41 alan-laptop systemd[1]: Started test.service.

$ ps -ejf
UID        PID  PPID  PGID   SID  C STIME TTY          TIME CMD
...
root     12173     1 12173 12173  0 11:28 tty10    00:00:00 cat

Я также подтвердил, что переключение на tty10 и нажатие Ctrl+C останавливает catпроцесс.

Связанный контент