<xi:include href="version-info.xml" xpointer="v226"/></listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--cleanup</option></term>
+
+ <listitem>
+ <para>Clean up left-over mounts and underlying mount points used by the container, and exit without
+ invoking any containers. This may be useful when the previous invocation of
+ <command>systemd-nspawn</command> was unexpectedly terminated. This requires at least one of
+ <option>-M/--machine=</option>, <option>-D/--directory=</option>, or <option>-i/--image=</option>
+ to determine the mounts to be cleaned up.</para>
+
+ <xi:include href="version-info.xml" xpointer="v257"/>
+ </listitem>
+ </varlistentry>
+
</variablelist>
<refsect2>
'(- *)'{-h,--help}'[Show this help.]' \
'(- *)--version[Print a short version string and exit.]' \
'(--quiet -q)'{--quiet,-q}'[Turns off any status output by the tool itself.]' \
+ '--cleanup[Cleanup left-over mounts and underlying mount points used by the container.]' \
'(--directory -D)'{--directory=,-D+}'[Directory to use as file system root for the namespace container. If omitted the current directory will be used.]:directories:_directories' \
'--template=[Initialize root directory from template directory, if missing.]:template:_directories' \
'(--ephemeral -x)'{--ephemeral,-x}'[Run container with snapshot of root directory, and remove it after exit.]' \
static ImagePolicy *arg_image_policy = NULL;
static char *arg_background = NULL;
static bool arg_privileged = false;
+static bool arg_cleanup = false;
STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
STATIC_DESTRUCTOR_REGISTER(arg_template, freep);
" -q --quiet Do not show status information\n"
" --no-pager Do not pipe output into a pager\n"
" --settings=BOOLEAN Load additional settings from .nspawn file\n"
+ " --cleanup Clean up left-over mounts and underlying mount\n"
+ " points used by the container\n"
"\n%3$sImage:%4$s\n"
" -D --directory=PATH Root directory for the container\n"
" --template=PATH Initialize root directory from template directory,\n"
ARG_SUPPRESS_SYNC,
ARG_IMAGE_POLICY,
ARG_BACKGROUND,
+ ARG_CLEANUP,
};
static const struct option options[] = {
{ "suppress-sync", required_argument, NULL, ARG_SUPPRESS_SYNC },
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
{ "background", required_argument, NULL, ARG_BACKGROUND },
+ { "cleanup", no_argument, NULL, ARG_CLEANUP },
{}
};
return r;
break;
+ case ARG_CLEANUP:
+ arg_cleanup = true;
+ break;
+
case '?':
return -EINVAL;
arg_private_network = !arg_privileged;
}
+static void cleanup_propagation_and_export_directories(void) {
+ const char *p;
+
+ if (!arg_machine || !arg_privileged)
+ return;
+
+ p = strjoina("/run/systemd/nspawn/propagate/", arg_machine);
+ (void) rm_rf(p, REMOVE_ROOT);
+
+ p = strjoina("/run/systemd/nspawn/unix-export/", arg_machine);
+ (void) umount2(p, MNT_DETACH|UMOUNT_NOFOLLOW);
+ (void) rmdir(p);
+}
+
+static int do_cleanup(void) {
+ int r;
+
+ if (arg_ephemeral)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot specify --ephemeral with --cleanup.");
+
+ r = determine_names();
+ if (r < 0)
+ return r;
+
+ cleanup_propagation_and_export_directories();
+ return 0;
+}
+
static int run(int argc, char *argv[]) {
bool remove_directory = false, remove_image = false, veth_created = false;
_cleanup_close_ int master = -EBADF, userns_fd = -EBADF, mount_fd = -EBADF;
if (r <= 0)
goto finish;
+ if (arg_cleanup)
+ return do_cleanup();
+
r = cant_be_in_netns();
if (r < 0)
goto finish;
(void) rmdir(p);
}
+ cleanup_propagation_and_export_directories();
+
expose_port_flush(&fw_ctx, arg_expose_ports, AF_INET, &expose_args.address4);
expose_port_flush(&fw_ctx, arg_expose_ports, AF_INET6, &expose_args.address6);