Uma abordagem poderia ser usar namespaces de PID:
Inicialize seu sistema com um parâmetro init=/some/cmd
as kernel, onde /some/cmd
bifurca um processo em um novo namespace ( CLONE_NEWPID
) e executa /sbin/init
nele (ele terá PID 1 nesse novo namespace e pid 2 no namespace raiz), então no pai, execute seu "programa".
Você provavelmente desejará uma forma de controlar seu programa de uma forma ou de outra (soquete TCP ou ABSTRACT Unix, por exemplo).
Você provavelmente desejará mlocar seu programa na memória e fechar a maioria das referências ao sistema de arquivos para que ele não dependa de nada.
Esse processo não será visto no resto do sistema. O resto do sistema será executado como em um container.
Se esse processo morrer, o kernel entrará em pânico, o que lhe dará uma garantia extra.
Um efeito colateral inconveniente é que não veremos os encadeamentos do kernel na saída de ps
.
Como uma prova de conceito (usando este truque para inicializar uma cópia do seu sistema em uma máquina virtual qemu ):
Crie um /tmp/init
como:
#! /bin/sh -
echo Starting
/usr/local/bin/unshare -fmp -- sh -c '
umount /proc
mount -nt proc p /proc
exec bash <&2' &
ifconfig lo 127.1/8
exec socat tcp-listen:1234,fork,reuseaddr system:"ps -efH; echo still running"
(você precisa de unshare
de uma versão recente do util-linux (2.14)). Acima estamos usando socat
como o "programa" que apenas responde em conexões TCP na porta 1234 com a saída de ps -efH
.
Em seguida, inicialize sua VM como:
kvm -kernel /boot/vmlinuz-$(uname -r) -initrd /boot/initrd.img-$(uname -r) \
-m 1024 -fsdev local,id=r,path=/,security_model=none \
-device virtio-9p-pci,fsdev=r,mount_tag=r -nographic -append \
'root=r rootfstype=9p rootflags=trans=virtio console=ttyS0 init=/tmp/init rw'
Então, vemos:
Begin: Running /scripts/init-bottom ... done.
Starting
[...]
root@(none):/# ps -efH
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 14:24 ? 00:00:00 bash
root 4 1 0 14:24 ? 00:00:00 ps -efH
root@(none):/# telnet localhost 1234
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
UID PID PPID C STIME TTY TIME CMD
root 2 0 0 14:24 ? 00:00:00 [kthreadd]
root 3 2 0 14:24 ? 00:00:00 [ksoftirqd/0]
[...]
root 1 0 2 14:24 ? 00:00:00 socat tcp-listen:1234,fork,reuseaddr system:ps -efH; echo still running
root 204 1 0 14:24 ? 00:00:00 /usr/local/bin/unshare -fmp -- sh -c umount /proc mount -nt proc p /proc exec bash <&2
root 206 204 0 14:24 ? 00:00:00 bash
root 212 206 0 14:25 ? 00:00:00 telnet localhost 1234
root 213 1 0 14:25 ? 00:00:00 socat tcp-listen:1234,fork,reuseaddr system:ps -efH; echo still running
root 214 213 0 14:25 ? 00:00:00 socat tcp-listen:1234,fork,reuseaddr system:ps -efH; echo still running
root 215 214 0 14:25 ? 00:00:00 sh -c ps -efH; echo still running
root 216 215 0 14:25 ? 00:00:00 ps -efH
still running
Connection closed by foreign host.
root@(none):/# QEMU: Terminated