Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

What's the best way to tell from a shell script if the host has restarted since the last time the script was run? I can think of storing the uptime in a file on each run, and checking if it has decreased, but that doesn't seem completely robust (a server might restart start quickly, store a low uptime, then reboot slowly and come up with a higher uptime).

Is there something like a "started at" value which would be guaranteed to change only on a reboot? Or some other good way of detecting a restart?

share|improve this question
add comment

7 Answers

If you don't want to use cron, you could also create a directory in /dev/shm. Since that location is in memory, it will always be empty when the computer starts up. If it's not empty, you haven't rebooted.

share|improve this answer
add comment
  • Create a directory somewhere when the system starts.
  • When your script runs if the directory exists then the system has restarted otherwise not.
  • Get your script to remove the directory.

Use the @reboot directive in /etc/crontab to create the directory when the system starts.

share|improve this answer
1  
Same idea, just didn't know about the @reboot entry point. Like it. –  Decado Apr 5 '11 at 14:57
    
@Decado, just be aware that not all systems support the @reboot parameter. Test it before relying on it. –  John Gardeniers Apr 6 '11 at 2:41
add comment

Another approach would be to touch a file somewhere in the startup scripts and search for that in the script, the script could then delete once it's run the first time.

Just be careful you deal with runtime level changes and so forth nicely.

share|improve this answer
add comment

sar command will help you in this.

http://linux.die.net/man/1/sar

share|improve this answer
add comment

The sysinfo() OS call gives you the time since the last reboot. This is where uptime gets it data before performing some formatting - its simpler to write you're own wrapper around this than parsing the output of uptime / working out how to read the start time of init (pid 1).

#include <stdio.h>
#include <time.h>
#include <errno.h>

int main(int argc, char **argv)
{
   struct sysinfo info;
   int status;

   status=sysinfo(&info);
   if (status==0) {
      printf("%d\n", info.uptime);
   } else {
      fprintf(STDERR,"error %d occurred\n", errno);
   }
   exit (status);
}

You'll also need to touch a file from your script and poll its mtime (using stat(1) from your script or stat(2) from C)

share|improve this answer
add comment
#!/bin/bash
#
# usage: $(basename $0) FILE
# returns TRUE if the file has been run since last boot
#
[[ $# -ne 1 ]] && { grep 'usage' "$0"; exit 255; }

# access time of script/program
atime="$(stat -c %X "$1")" 

# Last boot as unix timestamp
btime="$(date -d "$(who -b | awk '{ print $3, $4 }')" +%s)" 

if [[ $atime -gt $btime ]]; then
    exit 0 # true
else
    exit 1 # false
fi
share|improve this answer
    
CAVEAT: This will improperly return TRUE also, if the script/executable has been edited/built since the last reboot. This can also be used against nonexecutables/scripts to test whether they've been accessed since boot. –  JeffG Apr 6 '11 at 21:54
add comment

This will virtually get you there, this will check if a file has been accessed since the last boot.

#!/bin/bash

unixTimestamp () {
    date --utc --date "$1" +%s
}

if [ "$1" == "" ];then
        echo "You must specify a filename (e.g. './lastRun.sh foobar.sh')"
        exit 255
fi

FILENAME=$1

if [ -f ${FILENAME} ]; then

        if [ -n ${FILENAME} ]; then
                LASTRUN=`ls -laru ${FILENAME}|cut -f6,7,8 -d' '|sed 's/'${FILENAME}'//g'|sed 's/^ *//;s/ *$//'`
                LASTBOOT=`who -b|sed 's/.*system boot//g'|sed 's/^ *//;s/ *$//'`
                echo "Last Run: '${LASTRUN}'"
                echo "Last Boot: '${LASTBOOT}'"
                if [ "$(unixTimestamp ${LASTRUN})" -lt "$(unixTimestamp ${LASTBOOT})" ]; then
                        echo "${FILENAME} has not been run since last boot."
                        exit 1
                else
                        echo "${FILENAME} has been run since last boot"
                        exit 0
                fi
        fi
else
        echo "Unable to find file '${FILENAME}'..."
        exit 255
fi

If you have run the file it will have been accessed, but it also may have been edited by somebody and not run, or maybe touched.

EDIT

A bit of explanation:

LASTRUN=ls -laru ${FILENAME}|cut -f6,7,8 -d' '|sed 's/'${FILENAME}'//g'|sed 's/^ *//;s/ *$//'

For the above command:

ls -laru ${FILENAME}|cut -f6,7,8 -d' '     # Will take the filename and display the last access time   
|sed 's/'${FILENAME}'//g'                  # Will strip the filename out to leave you with the date and time 
|sed 's/^ *//;s/ *$//'                     # Will strip out whitespace before and after the date/time

This will leave you a date/time ready to convert to a unix timestamp

LASTBOOT=who -b|sed 's/.*system boot//g'|sed 's/^ *//;s/ *$//'

For the above command:

who -b                                     # Will show the time the system last booted
|sed 's/.*system boot//g'                  # Will strip out the text "system boot" to leave you with a date/time
|sed 's/^ *//;s/ *$//'                     # Will strip out whitespace before and after the date/time

This will leave you a date/time ready to convert to a unix timestamp

the unixTimestamp function takes the Date/TIME variable and converts it to a unix timestamp and then it's just a case of seeing which is the higher number. The higher number is the most recent, so we can work out if the last thing that happened was a reboot or a file access.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.