Một cách tiếp cận có thể là sử dụng không gian tên PID:
Khởi động hệ thống của bạn với init=/some/cmd
tham số kernel, trong đó tạo /some/cmd
một tiến trình trong không gian tên mới ( CLONE_NEWPID
) và chạy /sbin/init
trong nó (nó sẽ có PID 1 trong không gian tên mới đó và pid 2 trong không gian tên gốc), sau đó trong cha mẹ, thực thi " chương trình".
Bạn có thể muốn có một cách để kiểm soát chương trình của mình bằng cách này hay cách khác (ví dụ như socket TCP hoặc ABSTRACT Unix).
Bạn có thể muốn khóa chương trình của mình trong bộ nhớ và đóng hầu hết các tham chiếu đến hệ thống tập tin để nó không phụ thuộc vào bất cứ điều gì.
Quá trình đó sẽ không được nhìn thấy từ phần còn lại của hệ thống. Phần còn lại của hệ thống sẽ có hiệu lực chạy như trong một container.
Nếu quá trình đó chết, kernel sẽ hoảng loạn mang đến cho bạn một sự đảm bảo thêm.
Một tác dụng phụ bất tiện là chúng ta sẽ không thấy các luồng nhân trong đầu ra của ps
.
Như một bằng chứng về khái niệm (sử dụng thủ thuật này để khởi động một bản sao hệ thống của bạn trong máy ảo qemu):
Tạo một lượt /tmp/init
thích:
#! /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"
(bạn cần unshare
từ một phiên bản gần đây của linux-linux (2.14)). Ở trên chúng tôi đang sử dụng socat
làm "chương trình" chỉ trả lời các kết nối TCP trên cổng 1234 với đầu ra của ps -efH
.
Sau đó khởi động VM của bạn dưới dạng:
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'
Sau đó, chúng ta thấy:
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