From: Lennart Poettering Date: Sun, 2 Mar 2025 20:43:12 +0000 (+0100) Subject: nspawn: add ability to poweroff container cleanly with ^]^]p X-Git-Tag: v258-rc1~1186^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F36583%2Fhead;p=thirdparty%2Fsystemd.git nspawn: add ability to poweroff container cleanly with ^]^]p It's sometimes very useful to be able to terminate a container quickly but cleanly while talking to it. Introduce a hotkey for that: ^]^]p for powering it off. In similar style add ^]^]r for rebooting it. --- diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml index 4484e878317..213f434fe77 100644 --- a/man/systemd-nspawn.xml +++ b/man/systemd-nspawn.xml @@ -1847,6 +1847,35 @@ After=sys-subsystem-net-devices-ens1.device + + Hotkeys + + When invoked in interactive mode (i.e. the default ), a few + special keyboard shortcuts are understood that control the container runtime. These shortcuts need to be + typed within 1s to have effect, otherwise they will be forwarded to the container as regular + keypresses. + + + + Ctrl-] Ctrl-] Ctrl-] + Immediately terminate the container, killing all processes. + + + + Ctrl-] Ctrl-] r + Issue a reboot request to the container. + + + + + Ctrl-] Ctrl-] p + Issue a shutdown request to the container. + + + + + + diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 1737d1ef0ae..952516bc78f 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -4692,6 +4692,37 @@ static void set_window_title(PTYForward *f) { (void) pty_forward_set_title_prefix(f, dot); } +static int ptyfwd_hotkey(PTYForward *f, char c, void *userdata) { + pid_t pid = PTR_TO_PID(userdata); + const char *word; + int sig = 0; + + assert(f); + + switch (c) { + case 'p': + sig = SIGRTMIN+4; + word = "power off"; + break; + + case 'r': + sig = SIGRTMIN+5; + word = "reboot"; + break; + + default: + log_info("Unknown hotkey sequence ^]^]%c, ignoring.", c); + return 0; + } + + if (kill(pid, sig) < 0) + log_error_errno(errno, "Failed to send %s (%s request) to PID 1 of container: %m", signal_to_string(sig), word); + else + log_info("Sent %s (%s request) to PID 1 of container.", signal_to_string(sig), word); + + return 0; +} + static int merge_settings(Settings *settings, const char *path) { int rl; @@ -5687,6 +5718,8 @@ static int run_container( (void) pty_forward_set_background_color(forward, arg_background); set_window_title(forward); + + pty_forward_set_hotkey_handler(forward, ptyfwd_hotkey, PID_TO_PTR(*pid)); break; default: @@ -6364,7 +6397,9 @@ static int run(int argc, char *argv[]) { special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), arg_machine, u ?: t, ansi_normal()); if (arg_console_mode == CONSOLE_INTERACTIVE) - log_info("%s %sPress %sCtrl-]%s three times within 1s to kill container.%s", + log_info("%s %sPress %sCtrl-]%s three times within 1s to kill container; two times followed by %sr%s\n" + "%s %sto reboot container; two times followed by %sp%s to poweroff container.%s", + special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), ansi_highlight(), ansi_grey(), ansi_highlight(), ansi_normal(), special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), ansi_grey(), ansi_highlight(), ansi_grey(), ansi_normal()); } diff --git a/tools/command_ignorelist b/tools/command_ignorelist index aca6b8c93bd..65602aab8a7 100644 --- a/tools/command_ignorelist +++ b/tools/command_ignorelist @@ -576,3 +576,4 @@ file-hierarchy.xml /refsect1[title="Home Directory"]/variablelist/varlistentry[t file-hierarchy.xml /refsect1[title="Home Directory"]/variablelist/varlistentry[term="~/.local/share/"] file-hierarchy.xml /refsect1[title="Home Directory"]/variablelist/varlistentry[term="~/.local/state/"] systemd-measure.xml /refsect1[title="Options"]/variablelist/varlistentry[term="--linux=PATH"] +systemd-nspawn.xml /refsect1[title="Hotkeys"]/variablelist/varlistentry[term="Ctrl-] Ctrl-] Ctrl-]"]