int create_shutdown_run_nologin_or_warn(void) {
int r;
- /* This is used twice: once in systemd-user-sessions.service, in order to block logins when we actually go
- * down, and once in systemd-logind.service when shutdowns are scheduled, and logins are to be turned off a bit
- * in advance. We use the same wording of the message in both cases. */
+ /* This is used twice: once in systemd-user-sessions.service, in order to block logins when we
+ * actually go down, and once in systemd-logind.service when shutdowns are scheduled, and logins are
+ * to be turned off a bit in advance. We use the same wording of the message in both cases.
+ *
+ * Traditionally, there was only /etc/nologin, and we managed that. Then, in PAM 1.1
+ * support for /run/nologin was added as alternative
+ * (https://github.com/linux-pam/linux-pam/commit/e9e593f6ddeaf975b7fe8446d184e6bc387d450b).
+ * 13 years later we stopped managing /etc/nologin, leaving it for the administrator to manage.
+ */
r = write_string_file_atomic_label("/run/nologin",
"System is going down. Unprivileged users are not permitted to log in anymore. "
#include "string-util.h"
static int run(int argc, char *argv[]) {
- int r, k;
+ int r;
if (argc != 2)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
if (r < 0)
return r;
- if (streq(argv[1], "start")) {
- r = unlink_or_warn("/run/nologin");
- k = unlink_or_warn("/etc/nologin");
- if (r < 0)
- return r;
- return k;
+ /* We only touch /run/nologin. See create_shutdown_run_nologin_or_warn() for details. */
- } else if (streq(argv[1], "stop"))
+ if (streq(argv[1], "start"))
+ return unlink_or_warn("/run/nologin");
+ if (streq(argv[1], "stop"))
return create_shutdown_run_nologin_or_warn();
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown verb '%s'.", argv[1]);