base: add shutdown script to be called from systemd
authorHarald Hoyer <harald@redhat.com>
Mon, 30 May 2011 15:27:36 +0000 (17:27 +0200)
committerHarald Hoyer <harald@redhat.com>
Tue, 31 May 2011 13:50:43 +0000 (15:50 +0200)
NEWS
dracut-functions
dracut.conf.d/fedora.conf.example
modules.d/99shutdown/module-setup.sh [new file with mode: 0755]
modules.d/99shutdown/shutdown [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 47d5d2c..cb80df8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ dracut-011
 ==========
 - use udev-168 features for shutting down udev
 - introduce "--prefix" to put all initramfs files in /run/initramfs
+- new shutdown script
 
 dracut-010
 ==========
index 4d5a78a..e3e0392 100755 (executable)
@@ -461,7 +461,7 @@ inst() {
 
 [[ $hookdirs ]] || {
     hookdirs="cmdline pre-udev pre-trigger netroot initqueue pre-mount"
-    hookdirs+=" pre-pivot mount emergency"
+    hookdirs+=" pre-pivot mount emergency emergency-shutdown shutdown"
     export hookdirs
 }
 
index 122f657..8ca67d4 100644 (file)
@@ -2,5 +2,6 @@
 
 # i18n
 i18n_vars="/etc/sysconfig/keyboard:KEYTABLE-KEYMAP /etc/sysconfig/i18n:SYSFONT-FONT,FONTACM-FONT_MAP,FONT_UNIMAP"
-add_dracutmodules+=" rpmversion "
+add_dracutmodules+=" rpmversion shutdown "
 stdloglvl=3
+prefix=/run/initramfs
diff --git a/modules.d/99shutdown/module-setup.sh b/modules.d/99shutdown/module-setup.sh
new file mode 100755 (executable)
index 0000000..c4d2bb5
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+check() {
+    return 255
+}
+
+depends() {
+    echo base
+    return 0
+}
+
+install() {
+    local _d
+    dracut_install umount
+    dracut_install poweroff reboot halt
+    dracut_install -o kexec
+    inst "$moddir/shutdown" "$prefix/shutdown"
+    [ -e "${initdir}/lib" ] || mkdir -m 0755 -p ${initdir}/lib
+    mkdir -m 0755 -p ${initdir}/lib/dracut
+    mkdir -m 0755 -p ${initdir}/lib/dracut/hooks
+    for _d in $hookdirs shutdown shutdown-emergency; do
+        mkdir -m 0755 -p ${initdir}/lib/dracut/hooks/$_d
+    done
+}
+
diff --git a/modules.d/99shutdown/shutdown b/modules.d/99shutdown/shutdown
new file mode 100755 (executable)
index 0000000..bff29b9
--- /dev/null
@@ -0,0 +1,87 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+#
+# Licensed under the GPLv2
+#
+# Copyright 2011, Red Hat, Inc.
+# Harald Hoyer <harald@redhat.com>
+
+#!/bin/sh
+. /lib/dracut-lib.sh
+export TERM=linux
+
+emergency_shell()
+{
+    set +e
+    if [ "$1" = "-n" ]; then
+        _rdshell_name=$2
+        shift 2
+    else
+        _rdshell_name=dracut
+    fi
+    echo ; echo
+    warn $@
+    source_hook shutdown-emergency
+    echo
+    if getargbool 1 rd.shell -y rdshell || getarg rd.break rdbreak; then
+        [ -x /lib/udev/console_init ] && /lib/udev/console_init /dev/console
+        echo "Dropping to debug shell."
+        echo
+        export PS1="$_rdshell_name:\${PWD}# "
+        [ -e /.profile ] || echo "exec 0<>/dev/console 1<>/dev/console 2<>/dev/console" > /.profile
+        sh -i -l
+    else
+        exec /lib/systemd/systemd-shutdown "$@"
+        warn "Shutdown has failed. To debug this issue add \"rdshell\" to the kernel command line."
+        # cause a kernel panic
+        exit 1
+    fi
+}
+
+trap "emergency_shell Signal caught!" 0
+
+getarg 'rd.break=pre-shutdown' && emergency_shell -n cmdline "Break before pre-shutdown"
+
+umount_a() {
+    local _did_umount="n"
+    while read a mp a; do
+        if strstr "$mp" oldroot; then
+            if umount "$mp"; then
+                _did_umount="y"
+                echo "Unmounted $mp."
+            fi
+        fi
+    done </proc/mounts
+    [ "$_did_umount" = "y" ] && return 0
+    return 1
+}
+
+_cnt=0
+while [ $_cnt -le 40 ]; do
+    umount_a 2>/dev/null || break
+    _cnt=$(($_cnt+1))
+done
+[ $_cnt -ge 40 ] && umount_a
+
+check_finished() {
+    local f
+    for f in $hookdir/shutdown/*.sh; do
+        [ -e "$f" ] || continue
+        ( . "$f" ) || return 1
+    done
+    return 0
+}
+
+_cnt=0
+while [ $_cnt -le 40 ]; do
+    check_finished 2>/dev/null && break
+    _cnt=$(($_cnt+1))
+done
+[ $_cnt -ge 40 ] && check_finished 
+
+getarg 'rd.break=shutdown' && emergency_shell -n cmdline "Break before shutdown"
+[ "$1" = "reboot" ] && reboot -f -d -n --no-wall
+[ "$1" = "poweroff" ] && poweroff -f -d -n --no-wall
+[ "$1" = "halt" ] && halt -f -d -n --no-wall
+[ "$1" = "kexec" ] && kexec -e