
man 7 daemon
Quando um daemon SysV tradicional é iniciado, ele deve executar as etapas a seguir como parte da inicialização. Observe que essas etapas são desnecessárias para daemons de novo estilo (veja abaixo) e só devem ser implementadas se a compatibilidade com SysV for essencial.
[...]
6. No filho, chame setsid() para desconectar de qualquer terminal e criar uma sessão independente.
7. Na criança, chame fork() novamente,para garantir que o daemon nunca mais possa readquirir um terminal.
mas compare isso com processos iniciados sem nenhum vestígio de compatibilidade com 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
Os processos para ambos rsyslog.service
e systemd-journal.service
são líderes de sessão (SID = PID).
Parece que se tais programas fossem configurados para registrar em um TTY, eles ganhariam o TTY como um terminal de controle e receberiam um sinal indesejado/fatal quando o TTY fosse desligado/recebesse Ctrl+C, respectivamente. A menos que eles se lembrem de definir O_NOCTTY ao abrir o arquivo TTY.
Parece que isso é uma pequena armadilha ao escrever ou converter um programa para ser executado como um serviço systemd sem qualquer compatibilidade com SysV, se o seu programa suportar a gravação de mensagens em arquivos personalizados. Isso não parece ser apontado por este documento que defende o estilo systemd. O documento implica o contrário, insistindo que o double-fork é necessário para evitar isso no SysV e depois não menciona isso como um problema ao descrever as etapas que um serviço nativo do systemd usaria.
Isso está correto? O systemd fornece alguma proteção contra isso que esqueci ou o problema foi apontado em outro lugar no documento do systemd?
Responder1
O systemd fornece alguma proteção contra isso […]?
Você está assumindo que deveria. Pelo contrário, considere configurações TTYPath
e serviços como [email protected]
. A capacidade de obter um terminal de controle é na verdadenecessário, para que o gerenciamento de serviços possa abranger os serviços de login TTY, que precisam fazer exatamente isso.
O que realmente protege contra isso é abandonar a alocação automática de um terminal de controle em open()
e descartar a semântica antiga. Ouseriaproteger contra isso. Não é o caso no Linux, mas no FreeBSD, NetBSD, OpenBSD e Hurd hoje em dia a O_NOCTTY
sinalização open()
é totalmente supérflua. OapenasA maneira de adquirir um terminal de controle é exigi-lo explicitamente, com ioctl(…TIOSCTTY)
. Na verdade, esse tem sido o caso há quase um quarto de século, desde os dias do 4.4BSD.
Enquanto isso, o hábito de adquirir no Linux é o hábito que também existe há muito tempo, muito antes do systemd:O_NOCTTY
em todos os lugares. ☺
(Sim, as bibliotecas GNU e musl C não fornecem isso para você fopen()
. Esse é um dos vários motivos pelos quais fdopen()
ainda é um mecanismo útil.)
O gerenciamento de serviços com o conjunto de ferramentas nosh service-manager
adota uma abordagem um pouco diferente sobre isso. Em vez de sempre transformar processos daemon em líderes de sessão, cada serviço recebendo seu próprio objeto de sessão do kernel que então não vê utilidade, apenas serviços específicos também se encadeiam setsid
explicitamente; como serviços que usam , serviços onde, claro, está configurando o terminal de controle e serviços. (Conforme observado na fonte do serviço, chama a si mesmo.)ttylogin@*
open-controlling-tty
agetty@*
agetty
getty@*
mgetty
setsid()
Leitura adicional
- Jonathan de Boyne Pollard (2018).
setsid
.guia nosh. Programas. - Jonathan de Boyne Pollard (2018).
open-controlling-tty
.guia nosh. Programas. - Jonathan de Boyne Pollard (2015). "Herança e a falácia da daemonização
".Não há mais problemas com o
service
comando. nossa sinopse. Programas. - Jonathan de Boyne Pollard (2001). "Não faça isso
fork()
para 'colocar o daemon em segundo plano'.".Erros a evitar ao projetar programas daemon Unix. Respostas dadas com frequência. - Jonathan de Boyne Pollard. "Login no terminal virtual".guia nosh. Programas.
- Jonathan de Boyne Pollard. "Login de terminal real".guia nosh. Programas.
- http://git.musl-libc.org/cgit/musl/tree/src/stdio/__fmodeflags.c
- https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/libio/fileops.c#L274
Responder2
O systemd não protege os programas de serviço contra a aquisição de um terminal de controle. Eles precisam se proteger ao abrir arquivos de log especificados pelo usuário, usando o O_NOCTTY
sinalizador.
$ 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
Também confirmei que mudar para tty10 e pressionar Ctrl+C interrompe o cat
processo.