• systemd-nspawn / machinectl

Systemd nspawn - machinectl cannot open shell

Mit machinectl shell <container> lässt sich auf einfache Weise eine shell innerhalb eines Containers starten. Das funktioniert allerdings nur wenn systemd als Init-Manager verwendet wird und die Version aktuell genug ist. Andernfalls wird folgender Fehler zurückgeliefert:

[root@c8-nspawn1 ~]# machinectl list
MACHINE CLASS     SERVICE        OS VERSION ADDRESSES   
ve123   container systemd-nspawn -  -       192.168.4.2…

[root@c8-nspawn1 ~]# machinectl shell ve123
Failed to get shell PTY: Protocol error

Um die Abschottung zu realisieren verwendet systemd Namespaces, die vom Linuxkernel bereitgestellt werden. Dadurch ist es alternativ möglich mit nsenter in den Namespace des Containers zu wechseln. Benötigt wird dazu die Prozess-ID (PID) des Init-Prozesses innerhalb des Containers:


[root@c8-nspawn1 ~]# systemctl status systemd-nspawn@ve123
● systemd-nspawn@ve123.service - Container ve123
   Loaded: loaded (/usr/lib/systemd/system/systemd-nspawn@.service; disabled; vendor preset: disabled)
   Active: active (running) since Sun 2021-01-24 00:22:39 CET; 6 days ago
     Docs: man:systemd-nspawn(1)
 Main PID: 1533 (systemd-nspawn)
   Status: "Container running."
    Tasks: 4 (limit: 16384)
   Memory: 2.4M
   CGroup: /machine.slice/systemd-nspawn@ve123.service
           ├─payload
           │ ├─1535 /sbin/init
           │ ├─1734 /sbin/syslogd -t
           │ └─1850 /sbin/getty 38400 console
           └─supervisor
             └─1533 /usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth -U --settings=override --machine=ve123

Die PID von init im Container ve123 ist 1535. Diese kann man auch wie folgt auslesen:

[root@c8-nspawn1 ~]# cat /sys/fs/cgroup/pids/machine.slice/systemd-nspawn@ve123.service/tasks
1533
1535
1734
1850

[root@c8-nspawn1 ~]# head -2 /sys/fs/cgroup/pids/machine.slice/systemd-nspawn@ve123.service/cgroup.procs | tail -1
1535

Eine Loginshell lässt sich folgendermaßen öffnen:

[root@c8-nspawn1 ~]# nsenter -t 1535 -a /bin/sh -l
ve123:/# 

Dabei versucht -a alle Namespaces einzubinden, sie können mit -{m,u,i,n,p,U,C} aber auch individuell genannt werden.


Bash Funktion mshell

Um die ganzen Schritte abzukürzen kann man der Shell (hier am Beispiel bashrc) eine kleine Funktion hinzufügen:

function mshell () {
    [ -z "$1" ] && { echo "Usage: mshell <veid>" >&2; return 1; }
    pid=$(head -q -n 2 "/sys/fs/cgroup/pids/machine.slice/systemd-nspawn@$1.service/cgroup.procs" 2>/dev/null | tail -1)
    [ -z "$pid" ] && { echo "Container not found" >&2; return 1; }
    nsenter -t $pid -a /bin/sh -l
}

Nach dem nächsten Login oder manuellem Laden der .bashrc kann man einfach in den Container wechseln:

[root@c8-nspawn1 ~]# mshell ve122
Container not found

[root@c8-nspawn1 ~]# mshell ve123
ve123:/# 
Information zum Datenschutz | Helfen Sie uns diese Seite zu optimieren und erlauben Sie Cookies - daraus gewonnene Informationen werden nicht an Dritte weitergegeben.
Ablehnen Erlauben