mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
nspawn: Allow specifying custom init program
This allows for example forcing to use /sbin/init instead of always using /usr/lib/systemd/systemd if it exists. Or it allows using a different path altogether.
This commit is contained in:
parent
d3f0b4f3d2
commit
ce2291730d
@ -566,7 +566,7 @@
|
||||
|
||||
<row>
|
||||
<entry><option>--boot</option> specified</entry>
|
||||
<entry>An init program is automatically searched for and run as PID 1 in the container. The passed parameters are used as invocation parameters for this process.</entry>
|
||||
<entry>An init program is automatically searched for (unless the <option>--init=</option> is used) and run as PID 1 in the container. The passed parameters are used as invocation parameters for this process.</entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
@ -578,6 +578,14 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--init=</option></term>
|
||||
|
||||
<listitem><para>Invoke the specified path as the init program in the container when <option>--boot</option> is used.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--chdir=</option></term>
|
||||
|
||||
|
@ -101,6 +101,16 @@
|
||||
<xi:include href="version-info.xml" xpointer="v226"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Init=</varname></term>
|
||||
|
||||
<listitem><para>Takes an absolute path specifying the init program to invoke in the container when
|
||||
<varname>Boot=</varname> is enabled. This setting corresponds to the <option>--init=</option> option
|
||||
on the <command>systemd-nspawn</command> command line.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Ephemeral=</varname></term>
|
||||
|
||||
|
@ -74,7 +74,7 @@ _systemd_nspawn() {
|
||||
--pivot-root --property --private-users --private-users-ownership --network-namespace-path
|
||||
--network-ipvlan --network-veth-extra --network-zone -p --port --system-call-filter --overlay
|
||||
--overlay-ro --settings --rlimit --hostname --no-new-privileges --oom-score-adjust --cpu-affinity
|
||||
--resolv-conf --timezone --root-hash-sig --background --oci-bundle --verity-data'
|
||||
--resolv-conf --timezone --root-hash-sig --background --oci-bundle --verity-data --init'
|
||||
)
|
||||
|
||||
_init_completion || return
|
||||
|
@ -21,6 +21,7 @@ _arguments \
|
||||
'(--ephemeral -x)'{--ephemeral,-x}'[Run container with snapshot of root directory, and remove it after exit.]' \
|
||||
'(--image -i)'{--image=,-i+}'[Disk image to mount the root directory for the container from.]:disk image: _files' \
|
||||
'(--boot -b)'{--boot,-b}'[Automatically search for an init binary and invoke it instead of a shell or a user supplied program.]' \
|
||||
'--init=[Invoke the specified program as init in the container.]: : _message "path to init"' \
|
||||
'(--user -u)'{--user=,-u+}'[Run the command under specified user, create home directory and cd into it.]:user:_users' \
|
||||
'(--machine -M)'{--machine=,-M+}'[Sets the machine name for this container.]: : _message "container name"' \
|
||||
'--uuid=[Set the specified uuid for the container.]: : _message "container UUID"' \
|
||||
|
@ -20,6 +20,7 @@ struct ConfigPerfItem;
|
||||
%includes
|
||||
%%
|
||||
Exec.Boot, config_parse_boot, 0, 0
|
||||
Exec.Init, config_parse_path, 0, offsetof(Settings, init)
|
||||
Exec.Ephemeral, config_parse_tristate, 0, offsetof(Settings, ephemeral)
|
||||
Exec.ProcessTwo, config_parse_pid2, 0, 0
|
||||
Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
|
||||
|
@ -125,9 +125,10 @@ typedef enum SettingsMask {
|
||||
SETTING_CREDENTIALS = UINT64_C(1) << 30,
|
||||
SETTING_BIND_USER = UINT64_C(1) << 31,
|
||||
SETTING_SUPPRESS_SYNC = UINT64_C(1) << 32,
|
||||
SETTING_RLIMIT_FIRST = UINT64_C(1) << 33, /* we define one bit per resource limit here */
|
||||
SETTING_RLIMIT_LAST = UINT64_C(1) << (33 + _RLIMIT_MAX - 1),
|
||||
_SETTINGS_MASK_ALL = (UINT64_C(1) << (33 + _RLIMIT_MAX)) -1,
|
||||
SETTING_INIT = UINT64_C(1) << 33,
|
||||
SETTING_RLIMIT_FIRST = UINT64_C(1) << 34, /* we define one bit per resource limit here */
|
||||
SETTING_RLIMIT_LAST = UINT64_C(1) << (34 + _RLIMIT_MAX - 1),
|
||||
_SETTINGS_MASK_ALL = (UINT64_C(1) << (34 + _RLIMIT_MAX)) - 1,
|
||||
_SETTING_FORCE_ENUM_WIDTH = UINT64_MAX
|
||||
} SettingsMask;
|
||||
|
||||
@ -159,6 +160,7 @@ typedef struct OciHook {
|
||||
typedef struct Settings {
|
||||
/* [Exec] */
|
||||
StartMode start_mode;
|
||||
char *init;
|
||||
int ephemeral;
|
||||
char **parameters;
|
||||
char **environment;
|
||||
|
@ -139,6 +139,7 @@ static char *arg_slice = NULL;
|
||||
static bool arg_private_network = false;
|
||||
static bool arg_read_only = false;
|
||||
static StartMode arg_start_mode = START_PID1;
|
||||
static char *arg_init = NULL;
|
||||
static bool arg_ephemeral = false;
|
||||
static LinkJournal arg_link_journal = LINK_AUTO;
|
||||
static bool arg_link_journal_try = false;
|
||||
@ -244,6 +245,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_supplementary_gids, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_machine, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_hostname, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_slice, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_init, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_setenv, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_network_interfaces, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_network_macvlan, strv_freep);
|
||||
@ -347,6 +349,7 @@ static int help(void) {
|
||||
"\n%3$sExecution:%4$s\n"
|
||||
" -a --as-pid2 Maintain a stub init as PID1, invoke binary as PID2\n"
|
||||
" -b --boot Boot up full system (i.e. invoke init)\n"
|
||||
" --init=PATH Path to init to invoke\n"
|
||||
" --chdir=PATH Set working directory in the container\n"
|
||||
" -E --setenv=NAME[=VALUE] Pass an environment variable to PID 1\n"
|
||||
" -u --user=USER Run the command under specified user or UID\n"
|
||||
@ -695,6 +698,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_PRIVATE_NETWORK,
|
||||
ARG_INIT,
|
||||
ARG_UUID,
|
||||
ARG_READ_ONLY,
|
||||
ARG_CAPABILITY,
|
||||
@ -762,6 +766,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "private-network", no_argument, NULL, ARG_PRIVATE_NETWORK },
|
||||
{ "as-pid2", no_argument, NULL, 'a' },
|
||||
{ "boot", no_argument, NULL, 'b' },
|
||||
{ "init", required_argument, NULL, ARG_INIT },
|
||||
{ "uuid", required_argument, NULL, ARG_UUID },
|
||||
{ "read-only", no_argument, NULL, ARG_READ_ONLY },
|
||||
{ "capability", required_argument, NULL, ARG_CAPABILITY },
|
||||
@ -982,6 +987,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_settings_mask |= SETTING_START_MODE;
|
||||
break;
|
||||
|
||||
case ARG_INIT:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_init);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
arg_settings_mask |= SETTING_INIT;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
if (arg_start_mode == START_BOOT)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
@ -1776,6 +1789,9 @@ static int verify_arguments(void) {
|
||||
if (arg_userns_mode == USER_NAMESPACE_NO && !strv_isempty(arg_bind_user))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--bind-user= requires --private-users");
|
||||
|
||||
if (arg_start_mode != START_BOOT && arg_init)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --init= without --boot");
|
||||
|
||||
/* Drop duplicate --bind-user= entries */
|
||||
strv_uniq(arg_bind_user);
|
||||
|
||||
@ -3588,15 +3604,21 @@ static int inner_child(
|
||||
memcpy_safe(a + 1, arg_parameters, m * sizeof(char*));
|
||||
a[1 + m] = NULL;
|
||||
|
||||
FOREACH_STRING(init,
|
||||
"/usr/lib/systemd/systemd",
|
||||
"/lib/systemd/systemd",
|
||||
"/sbin/init") {
|
||||
a[0] = (char*) init;
|
||||
if (arg_init) {
|
||||
a[0] = arg_init;
|
||||
execve(a[0], a, env_use);
|
||||
}
|
||||
exec_target = arg_init;
|
||||
} else {
|
||||
FOREACH_STRING(init,
|
||||
"/usr/lib/systemd/systemd",
|
||||
"/lib/systemd/systemd",
|
||||
"/sbin/init") {
|
||||
a[0] = (char*) init;
|
||||
execve(a[0], a, env_use);
|
||||
}
|
||||
|
||||
exec_target = "/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init";
|
||||
exec_target = "/usr/lib/systemd/systemd, /lib/systemd/systemd, /sbin/init";
|
||||
}
|
||||
} else if (!strv_isempty(arg_parameters)) {
|
||||
const char *dollar_path;
|
||||
|
||||
@ -4583,6 +4605,9 @@ static int merge_settings(Settings *settings, const char *path) {
|
||||
strv_free_and_replace(arg_parameters, settings->parameters);
|
||||
}
|
||||
|
||||
if ((arg_settings_mask & SETTING_INIT) == 0 && settings->init)
|
||||
free_and_replace(arg_init, settings->init);
|
||||
|
||||
if ((arg_settings_mask & SETTING_EPHEMERAL) == 0 &&
|
||||
settings->ephemeral >= 0)
|
||||
arg_ephemeral = settings->ephemeral;
|
||||
|
@ -973,6 +973,36 @@ testcase_check_os_release() {
|
||||
rm -fr "$root" "$base"
|
||||
}
|
||||
|
||||
testcase_init() {
|
||||
local root common_opts
|
||||
|
||||
root="$(mktemp -d /var/lib/machines/TEST-13-NSPAWN.init.XXX)"
|
||||
create_dummy_container "$root"
|
||||
|
||||
cat >"$root/sbin/custom-init" <<EOF
|
||||
#!/bin/bash
|
||||
echo "Hello from custom init, beautiful day, innit?"
|
||||
ip link
|
||||
EOF
|
||||
chmod +x "$root/sbin/custom-init"
|
||||
|
||||
common_opts=(
|
||||
--boot
|
||||
--register=no
|
||||
--directory="$root"
|
||||
--machine=foo-bar
|
||||
)
|
||||
|
||||
(! systemd-nspawn "${common_opts[@]}" --init /not/really/there)
|
||||
systemd-nspawn "${common_opts[@]}" --init /sbin/custom-init |& grep "Hello from custom init, beautiful day, innit?"
|
||||
|
||||
mkdir -p /run/systemd/nspawn/
|
||||
echo -ne "[Exec]\nInit=/sbin/custom-init" >/run/systemd/nspawn/foo-bar.nspawn
|
||||
systemd-nspawn "${common_opts[@]}" --settings=yes |& grep "Hello from custom init, beautiful day, innit?"
|
||||
|
||||
rm -fr "$root"
|
||||
}
|
||||
|
||||
run_testcases
|
||||
|
||||
for api_vfs_writable in yes no network; do
|
||||
|
Loading…
Reference in New Issue
Block a user