mirror of
https://github.com/troglobit/finit.git
synced 2026-10-08 00:24:17 +07:00
Add support for a rescue (recovery) mode from kernel cmdline
This patch adds a rescue (revovery) mode to Finit. Simply add `rescue` to the kernel cmdline at boot and the following steps at bootstrap will be skipped: - Load of services/run/task/etc in /etc/finit.conf + /etc/finit.d/*.conf - fsck of filesystems in /etc/fstab - Remount of / to read-write - Mount of all filesystems in /etc/fstab - swapon - A few plugin hooks: - HOOK_ROOTFS_UP - HOOK_MOUNT_ERROR - HOOK_BASEFS_UP - `runparts DIR` - /etc/rc.local Instead of loading /etc/finit.conf and /etc/finit.d/*.conf Finit loads the file /lib/finit/rescue.conf, which can be overridden by the operator if needed. If this file is removed (or lost), Finit falls back to start a simple root shell, without any login. Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
@@ -217,6 +217,9 @@ AC_EXPAND_DIR(plugin_path, "$libdir/finit/plugins")
|
||||
AC_SUBST(plugin_path)
|
||||
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
|
||||
|
||||
AC_EXPAND_DIR(rescue_conf, "$libdir/finit/rescue.conf")
|
||||
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
|
||||
|
||||
# Generate all files
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
@@ -21,9 +21,6 @@ can also be used.
|
||||
General
|
||||
-------
|
||||
|
||||
* Add support for `rescue` on the kernel command line, start rescue mode
|
||||
if enabled with `configure` script. Could mean skip `/etc/finit.conf`
|
||||
et al and jump straight to a single getty login on console.
|
||||
* Add support for timed shutdown in Finit, including cancelled shutdown.
|
||||
* SysV init and systemd use SIGUSR1 to restart their FIFO/D-Bus. Add
|
||||
API restart to SIGHUP callback for the same functionality in Finit.
|
||||
|
||||
@@ -58,6 +58,7 @@ REBOOT_LNKS = shutdown halt poweroff suspend
|
||||
|
||||
# Hook in install to add finit and reboot symlink(s)
|
||||
install-exec-hook:
|
||||
@$(INSTALL_DATA) $(srcdir)/rescue.conf $(DESTDIR)$(pkglibdir)
|
||||
@for file in $(INIT_LNKS); do \
|
||||
lnk=$(DESTDIR)$(sbindir)/$$file; \
|
||||
if [ -e $$lnk ]; then \
|
||||
@@ -80,6 +81,7 @@ install-exec-hook:
|
||||
fi
|
||||
|
||||
uninstall-hook:
|
||||
@$(RM) $(DESTDIR)$(pkglibdir)/rescue.conf
|
||||
@for file in $(INIT_LNKS); do \
|
||||
lnk=`readlink $(DESTDIR)$(sbindir)/$$file`; \
|
||||
if [ "$$lnk" != "finit" ]; then \
|
||||
|
||||
+20
@@ -78,6 +78,9 @@ void conf_parse_cmdline(void)
|
||||
/* Catches finit_debug (deprecated), --debug, and debug */
|
||||
if (strstr(tok, "debug"))
|
||||
dbg = 1;
|
||||
|
||||
if (strstr(tok, "rescue") || strstr(tok, "recover"))
|
||||
rescue = 1;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
@@ -551,6 +554,19 @@ int conf_reload(void)
|
||||
svc_mark_dynamic();
|
||||
tty_mark();
|
||||
|
||||
if (rescue) {
|
||||
int rc;
|
||||
char line[80] = "tty [12345] @console noclear nologin";
|
||||
|
||||
/* If rescue.conf is missing, fall back to a root shell */
|
||||
rc = parse_conf(RESCUE_CONF);
|
||||
if (rc)
|
||||
tty_register(line, global_rlimit, NULL);
|
||||
|
||||
print(rc, "Entering rescue mode");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* First, read /etc/finit.conf */
|
||||
parse_conf(FINIT_CONF);
|
||||
|
||||
@@ -795,6 +811,10 @@ int conf_monitor(uev_ctx_t *ctx)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* Skip second run, when called from finit.c in rescue mode */
|
||||
if (ctx && rescue)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If only one watcher fails, that's OK. A user may have only
|
||||
* one of /etc/finit.conf or /etc/finit.d in use, and may also
|
||||
|
||||
+29
-20
@@ -53,6 +53,7 @@ int wdogpid = 0; /* No watchdog by default */
|
||||
int runlevel = 0; /* Bootstrap 'S' */
|
||||
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
|
||||
int prevlevel = -1;
|
||||
int rescue = 0; /* rescue mode from kernel cmdline */
|
||||
char *sdown = NULL;
|
||||
char *network = NULL;
|
||||
char *hostname = NULL;
|
||||
@@ -262,18 +263,20 @@ static void finalize(void)
|
||||
/*
|
||||
* Network stuff
|
||||
*/
|
||||
_d("Setting up networking ...");
|
||||
networking();
|
||||
umask(022);
|
||||
if (!rescue) {
|
||||
_d("Setting up networking ...");
|
||||
networking();
|
||||
|
||||
/* Hooks that rely on loopback, or basic networking being up. */
|
||||
_d("Calling all network up hooks ...");
|
||||
plugin_run_hooks(HOOK_NETWORK_UP);
|
||||
/* Hooks that rely on loopback, or basic networking being up. */
|
||||
_d("Calling all network up hooks ...");
|
||||
plugin_run_hooks(HOOK_NETWORK_UP);
|
||||
}
|
||||
umask(022);
|
||||
|
||||
/*
|
||||
* Run startup scripts in the runparts directory, if any.
|
||||
*/
|
||||
if (runparts && fisdir(runparts)) {
|
||||
if (runparts && fisdir(runparts) && !rescue) {
|
||||
_d("Running startup scripts in %s ...", runparts);
|
||||
run_parts(runparts, NULL);
|
||||
if (conf_any_change())
|
||||
@@ -296,7 +299,7 @@ static void finalize(void)
|
||||
service_step_all(SVC_TYPE_ANY);
|
||||
|
||||
/* Convenient SysV compat for when you just don't care ... */
|
||||
if (!access(FINIT_RC_LOCAL, X_OK)) {
|
||||
if (!access(FINIT_RC_LOCAL, X_OK) && !rescue) {
|
||||
run_interactive(FINIT_RC_LOCAL, "Calling %s", FINIT_RC_LOCAL);
|
||||
if (conf_any_change())
|
||||
service_reload_dynamic();
|
||||
@@ -385,7 +388,7 @@ int main(int argc, char* argv[])
|
||||
/*
|
||||
* Check file filesystems in /etc/fstab
|
||||
*/
|
||||
for (int pass = 1; pass < 10; pass++) {
|
||||
for (int pass = 1; pass < 10 && !rescue; pass++) {
|
||||
if (fsck(pass))
|
||||
break;
|
||||
}
|
||||
@@ -479,12 +482,14 @@ int main(int argc, char* argv[])
|
||||
/*
|
||||
* Mount filesystems
|
||||
*/
|
||||
if (!rescue) {
|
||||
#ifdef REMOUNT_ROOTFS
|
||||
run("mount -n -o remount,rw /");
|
||||
run("mount -n -o remount,rw /");
|
||||
#endif
|
||||
#ifdef SYSROOT
|
||||
mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
|
||||
mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Debian has this little script to copy generated rules while the system was read-only */
|
||||
if (fexist("/lib/udev/udev-finish"))
|
||||
@@ -493,15 +498,17 @@ int main(int argc, char* argv[])
|
||||
/* Bootstrap conditions, needed for hooks */
|
||||
cond_init();
|
||||
|
||||
_d("Root FS up, calling hooks ...");
|
||||
plugin_run_hooks(HOOK_ROOTFS_UP);
|
||||
if (!rescue) {
|
||||
_d("Root FS up, calling hooks ...");
|
||||
plugin_run_hooks(HOOK_ROOTFS_UP);
|
||||
|
||||
umask(0);
|
||||
if (run_interactive("mount -na", "Mounting filesystems"))
|
||||
plugin_run_hooks(HOOK_MOUNT_ERROR);
|
||||
umask(0);
|
||||
if (run_interactive("mount -na", "Mounting filesystems"))
|
||||
plugin_run_hooks(HOOK_MOUNT_ERROR);
|
||||
|
||||
run("swapon -ea");
|
||||
umask(0022);
|
||||
run("swapon -ea");
|
||||
umask(0022);
|
||||
}
|
||||
|
||||
/* Base FS up, enable standard SysV init signals */
|
||||
sig_setup(&loop);
|
||||
@@ -512,8 +519,10 @@ int main(int argc, char* argv[])
|
||||
*/
|
||||
conf_monitor(&loop);
|
||||
|
||||
_d("Base FS up, calling hooks ...");
|
||||
plugin_run_hooks(HOOK_BASEFS_UP);
|
||||
if (!rescue) {
|
||||
_d("Base FS up, calling hooks ...");
|
||||
plugin_run_hooks(HOOK_BASEFS_UP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initalize state machine and start all bootstrap tasks
|
||||
|
||||
@@ -96,6 +96,7 @@ extern int wdogpid;
|
||||
extern int runlevel;
|
||||
extern int cfglevel;
|
||||
extern int prevlevel;
|
||||
extern int rescue;
|
||||
extern char *rcsd;
|
||||
extern char *sdown;
|
||||
extern char *network;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
runlevel 1
|
||||
hostname rescue
|
||||
tty [12345] @console noclear nologin
|
||||
Reference in New Issue
Block a user