A simple shell script that will reboot right away

The following simple script will cause the kernel to do a warm reboot immediately. Notice that sync() is done first, in order to flush written blocks to disks, but that is no guarantee that the filesystems will actually survive. Most journalling systems will do just fine, but there is still a risk that this program will trash filesystems, especially on I/O-active systems (ie. production servers).

Use it at your own risk, obviously. Originally developed to solve the problem of hanging NFS-clients.

#!/bin/sh

tfile=`mktemp`
mv $tfile $tfile.c
tail -9 $0 > $tfile.c
gcc -Os -Wall -s $tfile.c -o $tfile.x
[ -x $tfile.x ] || exit 1
rm $tfile.c
$tfile.x

exit 0

#include <stdio.h>
#include <unistd.h>
#include <sys/reboot.h>
int main(int argc, char** argv) {
  unlink(argv[0]);
  sync();
  if (reboot(RB_AUTOBOOT)) { perror("on reboot()"); return 1; }
  return 0;
}

[ A script that will cause a Linux-system to reboot ]

You might notice that the script itself doesn't do the reboot, but it instead contains a small program written in C that gets compiled and executed. Unfortunately it is not possible to cause the reboot through any file under /proc/ or in any other way except the system call that is used in the program. Life is.

Eject & power off

A variation on the theme, this time without the shell script. We first eject the CD-ROM, then turn off the power, again without too much precautions. Mainly useful in scripts to prepare multiple systems for CD-based re-installation.

/**
 * To build:
gcc -Os -Wall -s poweroff.c -o poweroff

 */

#include <stdio.h>
#include <unistd.h>
#include <sys/reboot.h>

#include <linux/cdrom.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main(int argc, char** argv) {
  int fd;
  int err = 0;
  
  // check if we can access /dev/cdrom (whether it exists)
  if (access("/dev/cdrom", F_OK) != 0) {
    perror("on access('/dev/cdrom')");
    return 1;
  }
  // we need to open in non-blocking state, otherwise there needs to
  // be a CD-ROM disc inside. weirdness.
  if ((fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK)) == -1) {
    perror("on open('/dev/cdrom', O_RDONLY|O_NONBLOCK)");
    return 1;
  }
  // seems to exist. try to eject
  if (ioctl(fd, CDROMEJECT, &err) != 0) {
    perror("on ioctl(CDROMEJECT)");
    return 1;
  }
  
  // remove this executable (not really necessary in this case)
  unlink(argv[0]);
  // flush all dirty blocks to storage devices (at least ask for it)
  sync();
  // do the poweroff
  if (reboot(RB_POWER_OFF)) { perror("on reboot()"); return 1; }

  return 0;
}

[ Eject CD-ROM and poweroff ]

#!/bin/sh

# the following scriptlet causes poweroff to run on hosts
# 192.168.0.1 - 192.168.0.10
#
# this script assumes that ssh is used with public keys (so that it
# doesn't ask for passwords). also assumes that root login is permitted
# which it is not normally.

# start by blowing away known_hosts in case keys are mismatched
# note that this is relatively dangerous operation to do on a system
# that is used to ssh from !! (DANGER: read the notice before)
rm -f ~/.ssh/known_hosts

for a in `seq 10`; do
  # copy the executable on remote host
  # also tell ssh to ignore the fact that we might not have connected
  # to the system before and insert the host key blindly
  # again, very very insecure, but..
  scp -o StrictHostKeyChecking=no poweroff root@192.168.0.$a:.
  # execute poweroff over ssh and detach ssh so that it doesn't
  # wait for the program to terminate. since power will be cut off
  # without proper process termination, the SSH connection will
  # wait for 15 minutes otherwise.
  ssh -f root@192.168.0.$a ./poweroff
done

[ A simple script that uses the program ]

Download files

You must be crazy to download these, since they're DANGEROUS.. But since that doesn't seem to work, here are links to the files reboot.sh, poweroff.c, prepare.sh.

Epilog

All content copyright 2006 Aleksandr Koltsoff (including program sources). Use for personal education permitted, all other use must be negotiated (czr(at)iki(dot)fi).