2009-10-12 18:36:19 +02:00
|
|
|
|
{ config, pkgs, ... }:
|
2006-11-23 23:53:16 +01:00
|
|
|
|
|
2009-10-12 18:36:19 +02:00
|
|
|
|
with pkgs.lib;
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
2009-11-06 22:08:06 +01:00
|
|
|
|
{
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
2009-11-06 22:08:06 +01:00
|
|
|
|
jobs.shutdown =
|
|
|
|
|
{ name = "shutdown";
|
2009-10-12 18:36:19 +02:00
|
|
|
|
|
|
|
|
|
task = true;
|
|
|
|
|
|
2009-11-06 22:08:06 +01:00
|
|
|
|
environment = { MODE = "poweroff"; };
|
|
|
|
|
|
2009-10-12 18:36:19 +02:00
|
|
|
|
script =
|
|
|
|
|
''
|
2009-03-06 13:27:47 +01:00
|
|
|
|
set +e # continue in case of errors
|
2009-11-06 22:08:06 +01:00
|
|
|
|
|
|
|
|
|
${pkgs.kbd}/bin/chvt 1
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
2009-11-06 22:08:06 +01:00
|
|
|
|
exec < /dev/console > /dev/console 2>&1
|
2009-03-06 13:27:47 +01:00
|
|
|
|
echo ""
|
2009-11-06 22:51:28 +01:00
|
|
|
|
if test "$MODE" = maintenance; then
|
|
|
|
|
echo "[1;32m<<< Entering maintenance mode >>>[0m"
|
|
|
|
|
else
|
|
|
|
|
echo "[1;32m<<< System shutdown >>>[0m"
|
|
|
|
|
fi
|
2009-03-06 13:27:47 +01:00
|
|
|
|
echo ""
|
|
|
|
|
|
2009-11-06 22:08:06 +01:00
|
|
|
|
export PATH=${pkgs.utillinux}/bin:${pkgs.utillinux}/sbin:$PATH
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
2009-11-06 22:08:06 +01:00
|
|
|
|
|
2009-03-06 13:27:47 +01:00
|
|
|
|
# Set the hardware clock to the system time.
|
2009-08-11 23:08:05 +02:00
|
|
|
|
echo "setting the hardware clock..."
|
|
|
|
|
hwclock --systohc --utc
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Do an initial sync just in case.
|
2009-08-11 23:08:05 +02:00
|
|
|
|
sync
|
2009-11-06 22:08:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Stop all Upstart jobs.
|
2009-11-06 22:17:11 +01:00
|
|
|
|
initctl list | while IFS=", " read jobName status rest; do
|
|
|
|
|
if test "$jobName" != shutdown -a "$status" != "stop/waiting"; then
|
2009-11-06 22:08:06 +01:00
|
|
|
|
echo "stopping $jobName..."
|
|
|
|
|
stop "$jobName"
|
|
|
|
|
fi
|
|
|
|
|
done
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Kill all remaining processes except init and this one.
|
2009-08-11 23:08:05 +02:00
|
|
|
|
echo "sending the TERM signal to all processes..."
|
|
|
|
|
kill -TERM -1
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
|
|
|
|
sleep 1 # wait briefly
|
2009-08-11 23:08:05 +02:00
|
|
|
|
|
|
|
|
|
echo "sending the KILL signal to all processes..."
|
|
|
|
|
kill -KILL -1
|
2009-11-06 22:08:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# If maintenance mode is requested, start a root shell, and
|
|
|
|
|
# afterwards emit the "startup" event to bring everything
|
|
|
|
|
# back up.
|
|
|
|
|
if test "$MODE" = maintenance; then
|
|
|
|
|
echo ""
|
2009-11-06 22:51:28 +01:00
|
|
|
|
echo "[1;32m<<< Maintenance shell >>>[0m"
|
2009-11-06 22:08:06 +01:00
|
|
|
|
echo ""
|
|
|
|
|
while ! ${pkgs.bash}/bin/bash --login; do true; done
|
2009-11-06 22:38:40 +01:00
|
|
|
|
initctl emit -n startup
|
2009-11-06 22:08:06 +01:00
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
|
|
|
|
# Unmount helper functions.
|
|
|
|
|
getMountPoints() {
|
|
|
|
|
cat /proc/mounts \
|
|
|
|
|
| grep -v '^rootfs' \
|
|
|
|
|
| sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \
|
|
|
|
|
| grep -v '/proc\|/sys\|/dev'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getDevice() {
|
|
|
|
|
local mountPoint=$1
|
|
|
|
|
cat /proc/mounts \
|
|
|
|
|
| grep -v '^rootfs' \
|
|
|
|
|
| grep "^[^ ]\+ \+$mountPoint \+" \
|
|
|
|
|
| sed 's|^\([^ ]\+\).*|\1|'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Unmount file systems. We repeat this until no more file systems
|
|
|
|
|
# can be unmounted. This is to handle loopback devices, file
|
|
|
|
|
# systems mounted on other file systems and so on.
|
|
|
|
|
tryAgain=1
|
|
|
|
|
while test -n "$tryAgain"; do
|
|
|
|
|
tryAgain=
|
|
|
|
|
|
|
|
|
|
for mp in $(getMountPoints); do
|
|
|
|
|
device=$(getDevice $mp)
|
|
|
|
|
echo "unmounting $mp..."
|
2009-08-11 23:08:05 +02:00
|
|
|
|
|
|
|
|
|
# Note: don't use `umount -f'; it's very buggy.
|
|
|
|
|
# (For instance, when applied to a bind-mount it
|
|
|
|
|
# unmounts the target of the bind-mount.) !!! But
|
|
|
|
|
# we should use `-f' for NFS.
|
|
|
|
|
if umount -n "$mp"; then
|
2009-03-06 13:27:47 +01:00
|
|
|
|
if test "$mp" != /; then tryAgain=1; fi
|
|
|
|
|
else
|
2009-08-11 23:08:05 +02:00
|
|
|
|
# `-i' is to workaround a bug in mount.cifs (it
|
|
|
|
|
# doesn't recognise the `remount' option, and
|
|
|
|
|
# instead mounts the FS again).
|
|
|
|
|
mount -n -i -o remount,ro "$mp"
|
2009-03-06 13:27:47 +01:00
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Hack: work around a bug in mount (mount -o remount on a
|
|
|
|
|
# loop device forgets the loop=/dev/loopN entry in
|
|
|
|
|
# /etc/mtab).
|
|
|
|
|
if echo "$device" | grep -q '/dev/loop'; then
|
|
|
|
|
echo "removing loop device $device..."
|
2009-08-11 23:08:05 +02:00
|
|
|
|
losetup -d "$device"
|
2009-03-06 13:27:47 +01:00
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Final sync.
|
2009-08-11 23:08:05 +02:00
|
|
|
|
sync
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
|
|
|
|
|
2009-11-06 22:51:28 +01:00
|
|
|
|
# Either reboot or power-off the system.
|
2009-11-06 22:08:06 +01:00
|
|
|
|
if test "$MODE" = reboot; then
|
2009-08-11 23:08:05 +02:00
|
|
|
|
echo "rebooting..."
|
|
|
|
|
sleep 1
|
2009-03-06 13:27:47 +01:00
|
|
|
|
exec reboot -f
|
|
|
|
|
else
|
2009-08-11 23:08:05 +02:00
|
|
|
|
echo "powering off..."
|
|
|
|
|
sleep 1
|
2009-03-06 13:27:47 +01:00
|
|
|
|
exec halt -f -p
|
|
|
|
|
fi
|
2009-10-12 18:36:19 +02:00
|
|
|
|
'';
|
|
|
|
|
};
|
2009-03-06 13:27:47 +01:00
|
|
|
|
|
2009-11-06 22:08:06 +01:00
|
|
|
|
}
|