#!/bin/tcsh -f # If debugging, temporarily remove the # in the next line set echo_style='none' #; set echo verbose # There is absolutely no warranty of any type on this public-domain script. # Template script to back up the system disk. # This script must be edited before it can be used. See below for # more info. Requires dar_static, tcsh, and a compiled version # backupex of backupex.f. Encryption of the backups requires gpg. # Usage: backup POST 'BACKUP_DISK' TASK # Specifying TASK as --help gives a list of possible values for TASK. # If 'BACKUP_DISK' is left out, backup disk backdisk specified below is used. # Leave out POST unless you want post processing, then specify it as yes. # Key variables that *must* be set properly by the user (more info is below): set backdisk="" # Disk, USB or other, to store the backups set nam="backup" # Must be a single word; backups are put in backdisk/nam set fsroot="/" # Folder with the files to be backed up, *must* be / set marker=".$nam.bin" # Marker used to recognize fsroot and for encryption alias backcmd '$backprog' --create '"`pwd`/$fnm"' --fs-root '"$fsroot"' \ --noconf -Q --alter=atime --empty-dir --cache-directory-tagging \ --prune dev --prune lost+found --prune proc \ --prune run --prune sys --prune tmp \ --prune var/cache/apt/archives --prune var/log --prune var/tmp \ --prune media --prune mnt --prune '".$backdisk"' \ --slice 2G --mincompr 256 --gzip=6 --alter=no-case \ -Z '"*.gz"' -Z '"*.bz2"' -Z '"*.zip"' -Z '"*.deb"' \ -Z '"*.png"' -Z '"*.gif"' -Z '"*.jpg"' \ -Z '"*.wav"' -Z '"*.mpg"' -Z '"*.mp3"' -Z '"*.asf"' \ -Z '"*.rm"' -Z '"*.rar"' -Z '"*.avi"' -Z '"*.wmv"' \ --alter=case # backup command # This script must be edited before it can be used. The items to edit # are the key variables above, and possibly also other variables # below. Additional information is at http://www.dommelen.net/backup/ # or http://www.eng.fsu.edu/~dommelen/backup/ # First some notes about some of the key variables above: # The variable backdisk above must be set equal to the location on the # disk that is to hold the backups. In Ubuntu, if you right-click a # file or subfolder on the disk, and select "Properties", the correct # value of backdisk will be listed as "Location". Enter the # specification between the double quotes. Maybe something like # "/media/WHATEVER" if your disk is called WHATEVER on Ubuntu. You # can also append a subfolder on the disk to it, as long as it already # exists. Normally the disk is a USB disk. In principle it is # possible to put the backups on the same physical disk that is being # backed up. However, if that disk goes bad, you have no backups! # Unless you want to encrypt the backups, it is best to remove the # stuff between the double quotes in variable marker above. # Note that you do not normally want to change the first four lines # of the alias backcmd command above. # # However, it is quite possible that you want to modify other lines or # add lines. Using a terminal, see # man dar # dar_static --help | more # for further explanations of the arguments of the dar command. # # Note the need to avoid backing up the backups! To avoid backing up # the backups, use --prune '".$backdisk/$nam"'. To not back up that # disk at all, use --prune '".$backdisk"'. You probably also want to # prune media, where external disk are usually mounted. External # disks are best backed up separately using the backfol script. That # script deals better with the possibility that occasionally these # disks may not be mounted. # # The backup command above skips /dev. But on some non Debian or # Ubuntu systems, like Arch Linux, some files in /dev do need to be # backed up. Therefore, if you do not have a Debian or Ubuntu system, # it is recommended that you make at least one separate backup of /dev # using the backfol script, pruning /dev/pts. Then if you run into # trouble rebooting from your restored system disk, you can # custom-restore files in /dev as needed. Sun Solaris has quite a # different file structure, and usually specific folders are backed # up, (like with the backfol script), rather than the complete system. # # Note that if you prune a folder or exclude a file type whose name # contains spaces or other junk, you need to single-double quote it. # A couple of typical examples: # --prune '"./$HOME/Documents/Junk Folder"' --exclude '"*.tmp"' \ # Note also that prune specifications are relative to fsroot, (i.e. # leave the leading / away from the location). And that any line that # you add to the backcmd must be terminated by a backslash. Just like # the lines that are already there. You would probably want to put a # prune command like the one above before the --alter=no-case line, # but an exclude command like the one above after it. # It is a good idea to check that you are backing up what you think # you are backing up. After the first backup, look at the readme.txt # file in folder backdisk/nam (as defined above). This file will tell # you how you can restore single folders or files using dar_static. # If you append ' -e -v' at the end of the appropriate dar_static # line, (without the quotes), it will not actually restore the files, # just show you what would happen. That allows you to verify that the # important files *are* being backed up, and that you *are* able to # restore them when needed. # Note also that while .gvfs files produce error messages, pruning # them does no good. It is a wart in the operating system. Just # ignore the error messages; these files are created when needed and # need not be backed up. # Additional variables that may need to be adjusted: # The next variables to be set select how many and what backups are # kept. Before going into details, consider a typical example. # Suppose that the next variables are set as: # n1=Z, n2=0, n3=1, n4=2, n5=3, n6=4, n7=5, n8=, n9= # Also assume that this script is run every night as backup 7. That # means that a full system disk backup is done on Sundays and # incremental ones on the other days of the week. In that case, the # complete system disk, or a single file in it, can be restored to # what its status was on any day of the current or previous week, # counted from Sundays. If you created a file last week Tuesday, and # mistakenly deleted it or messed it up last week Wednesday, you can # get it back. Also, the first backup made will be kept for 17 years, # after which it will be replaced by one that is 3 years old. So you # can restore the system disk to its original condition for 17 years. # # More specifically, backup sets will be kept in folders 1/, 2/, ..., # /7. The age of the backups in these folders will be, in weeks: # 1/: current week 2/: last week 3/: 2-3 weeks ago # 4/: 4-9 weeks ago 5/: 10-33 weeks ago 6/: 34-153 weeks ago # 7/: 154-873 weeks ago (i.e. backup is 3 to 17 years old) # If you think backups going back 33 weeks are enough, leave n7 blank. # then folder 7 will not be created. If your USB disk does not have # space for 6 or 7 full backups, run backup auto instead of backup # 7. In that case, full backups are done roughly once a month, # instead of once a week. So "week" in the description above get # replaced by "month". Therefore you can probably safely blank out n6 # and n7. The drawback is that it will be a bit more elaborate to # restore files, processing all those incrementals. And you will be a # bit more vulnerable to a full backup getting damaged. Then again, # anything that lived for at least a day last month can be restored. # If changing n1, n2, ..., note that the values that are not blank # must be hexadecimal-style, upper-case, single digits in base 36, # i.e. they must be in the range 0, 1, ..., 9, A, B, ..., Z. # Maximum number of incremental backups to do for each nonincremental # one. Normally set to Z (= 35), the largest possible value: set n1=Z # How many full backups in folder 1/ *not* to move to folder 2/ for # each that is. # # If this is blank, no folder 2/ will be created to hold older backups # than the one in 1/. It is recommended that n2 is not blank, and is # set to 0, if you have space on the backup disk for more than one # full backup. The reason is that if a full backup fails, then if n2 # is not 0, you might up in a situation where you have no latest and # greatest backup at all. That is particularly bad if the reason that # the full backup failed is that the disk being backed up went bad # right in the middle of the backup. # # If you really want to keep only one full backup at a time, it is # recommended that you leave this at 0, and put variable delete_backup # below equal to "2". set n2=0 # How many full backups in folder 2/ *not* to move to folder 3/ for # each that is. (Note that you surely cannot keep every backup, # because the needed disk space would be horrendous.) set n3=1 # How many full backups in folder 3/ *not* to move to folder 4/ for # each that is. set n4=2 # How many full backups in folder 4/ *not* to move to folder 5/ for # each that is. set n5=3 # How many full backups in folder 5/ *not* to move to folder 6/ for # each that is. set n6=4 # How many full backups in folder 6/ *not* to move to folder 7/ for # each that is. set n7=5 # How many full backups in folder 7/ *not* to move to folder 8/ for # each that is. set n8= # How many full backups in folder 8/ *not* to move to folder 9/ for # each that is. set n9= # If this is not empty, backups in that folder will be deleted after a # backup believed to be successful. A "2" behind the equals sign has # the effect of keeping only a single full backup at any time. That # is regardless of what n3, n4, ... above are set at. Use with # caution. set delete_backup="" # Whether to skip backup if 'find -newer' cannot find any files in # $fsroot that have a later modification time than the current backup # set. Not recommended unless it is a backup you can afford to lose: # if something changes the modification time of the backup set, you # are out of luck. And so you are if someone mis-touches an important # file. Set to "inc" to skip incrementals or to "all" to also skip # new backups: set skip="" # Chmod executed on generated backup files and folders (but don't # count on it for Windows compatible disks): set chm='chmod go=' # Who to set as owner of the backups or blank for none. The value # `stat -c %u "$HOME"`:`stat -c %g "$HOME"` # makes the owner of the $HOME folder also owner of the backups. set owner=`stat -c %u "$HOME"`:`stat -c %g "$HOME"` # The variable mailprog below allows you to optionally specify a # script to email error messages to yourself. This script should take # the email subject from its argument and the text from standard # input. For the rest, the script can be anything. set mailprog="" # script to email yourself error messages # The following variables specify any desired postprocessing after the # script exits. Postprocessing is only done if the first script # argument is yes. To shut down the computer after execution put # goto shutdown # in between the double quotes. # # postprocessing if the script terminates successfully set post_on_success="" # postprocessing if the script terminates with error status set post_on_error="" # Additional variables that are probably OK for most users: # Place to put the error messages. This should normally be your # desktop so that you can keep track of what is going on. Must be a # fully specified path. Cannot be blank. Watch it: files with names # that start with backup, (or whatever nam is set equal to at the # start of this script, if not backup), may be overwritten in this # folder without notice. More specifically, files that may be # overwritten are backup_running, backup_disabled, backup_tmp, # backup_FAILED, and backup_nn-nn-nn, with n any decimal digit. # Specifying $HOME/Desktop puts the error messages on your desktop. set errdir="$HOME/Desktop" # Days after which to kill $nam_running lock files or empty for no killing. # For unattended systems, leaving this blank will cause an orphaned lock # file to abort backups indefinitely: set rmlock=2 # The number of lines to keep when truncating the log file: set maxlines=1000 # Some additional variables that should be OK on Debian and Ubuntu systems: # avoid language problems setenv LC_ALL C # Location where backupex can be found set backupex="$HOME/bin/backupex" # Location where dar_static can be found set dar_static="/usr/bin/dar_static" # Find command to search the current folder but preferably not its # subdirectories. It depends on your system what works; test it out # in tcsh using "alias fnd ... ; cd $HOME ; fnd -name '*e*'" alias fnd '/usr/bin/find "$cwd" -maxdepth 1' # Other possibilities to try, in order of decreasing desirability: # alias fnd '/usr/local/bin/find "$cwd" -maxdepth 1' # alias fnd 'find "$cwd" \! -name "$cwd:t" -prune' # alias fnd 'find "$cwd"' # echo command without line change alias echon 'set echo_style=bsd; echo -n \!*; set echo_style=none' # command to return the date of a file alias fdate '/bin/date -r \!* +"%m-%d-%y"' # Other possibilities to try, in order of decreasing desirability: # alias fdate '/usr/local/bin/date -r \!* +"%m-%d-%y"' # alias fdate 'date +"%m-%d-%y" ; echo \!* > /dev/null' # command to get password alias sp 'set password=`g "$e" -d "$m"`' # Some additional variables that should be OK if you use dar_static # List of files to copy to the backup folder, separated by spaces. It # is a very good idea to have a backup copy of dar_static in case the # disk that it is on crashes. set savefils="$dar_static $backupex" # Backup program return status values to ignore, should normally # include 0. set statign='0' # Backup program return status values for which an error notification # is send, but for which the backup is still accepted as valid. # Anything not listed in this string or statign above causes the # backup set to be marked as bad, to be deleted during the next # backup. According to 'man dar_static', exit status 5 indicates that # a file could not be opened or read, and 11 that a file changed while # dar was reading it and may be corrupt in the backup. If you decide # that an acceptable backup was bad after all or vice-versa, and want # to fix it manually, note that if the next backup that is performed # is incremental, the old good backup *must* be in $backdisk/$nam/1, # and its filename *must* be settable by sourcing file # $backdisk/$nam/oldfnm.src: set statnoti='5 11' # Lines to put in the readme file in the backup folder. Modify this # as needed. Note the trailing backslashes and watch the quotes: if (`echo " $*" | grep -c ' init$'` != 1) goto endrme set base="$backdisk/$nam" set basen="/USB_LOC/$nam" if ("$fsroot" != "/") then echo "*** The variable fsroot must be / in this script\!" exit 1 endif set readme=(\ "# TO RECOVER THE ENTIRE ENTIRE CRASHED OR MESSED UP SYSTEM DISK:"\ "# Recreate a new system disk if needed. Boot from a live linux CD."\ "# Open a terminal (menus, Ctl+Alt+t, or Computer/File System/usr/bin/xterm)."\ "# (In it pressing c holding Ctrl aborts, and Tab does completion.) Enter:"\ "sudo passwd root (enter a password twice)"\ "su (once again)"\ "whoami (must say root)"\ "# Find the USB disk and in it folder $nam with this readme.txt file and"\ "# folder 1 with the backups. Also find the system disk. If you cannot find"\ "# the system disk using the graphical interface, in the terminal try to"\ "# identify the device using 'gparted &' or 'fdisk -l', (look for type extN"\ "# or linux, not swap), and if it is, say, /dev/sdaN try mounting it using"\ "mkdir /sdaNmount"\ "mount /dev/sdaN /sdaNmount (see man mount for more on mounting)"\ "# When you have the two disks, enter"\ "mount -l"\ "# That should show up the USB and system disks something like"\ "/dev/sdBN on /USB_DISK type ..."\ "/dev/sdaN on /SYSTEM_DISK type extN ..."\ "# Write down /USB_DISK and /SYSTEM_DISK. /SYSTEM_DISK cannot be /, that is"\ "# the live CD. To check that you got it right, (otherwise try again), do"\ "ls '/USB_DISK' (MUST show the files on the USB disk)"\ "ls '/SYSTEM_DISK' (MUST show system files like bin, etc, lib, sbin, ...)"\ "cd '/SYSTEM_DISK' (MUST not produce complaints)"\ "pwd (MUST say /SYSTEM_DISK, *not* /)"\ "ls (MUST show system files like bin, etc, lib, sbin, ...)"\ "# /USB_LOC is the location of folder $nam, /USB_DISK or /USB_DISK/SUBFOLDER"\ "cp '$basen/dar_static' . (note the final point)"\ "chmod a+rx ./darstatic (note the point before the /)"\ "./dar_static -l '$basen/1/MMDDYY_NNNNNN0' (lists files to be restored)"\ "# (if encrypted add --key 'bf:PASSWORD' replacing any ! by \\! and ' by '"'"'"'"'"'"')"\ "mkdir saveorg (creates a directory to save any still existing files in)"\ "mv -i * saveorg/ (complains; use 'ls' to check the files are in fact moved)"\ "# (even if low on disk space, do not delete boot or etc from saveorg)"\ "./dar_static -x '$basen/1/MMDDYY_NNNNNN0' --verbose"\ "./dar_static -x '$basen/1/MMDDYY_NNNNNN1' --verbose --no-warn"\ "./dar_static -x '$basen/1/MMDDYY_NNNNNN2' --verbose --no-warn"\ "# and so on until there are no more incremental backups in folder 1."\ "mv -i etc/fstab etc/fstab_restored"\ "cp -i saveorg/etc/fstab etc/fstab"\ "grub-install --boot-directory=/SYSTEM_DISK/boot /dev/sda"\ "mkdir var/cache/apt/archives/partial"\ "# Restart and your system should be restored to the time of the last backup."\ "# When *sure* that you do not want any more files out of saveorg:"\ "rm -r '/saveorg' (MUST use quotes)"\ ""\ "# TO RECOVER A SINGLE SUBFOLDER OR SINGLE FILE:"\ "# Open a terminal (menus, Ctl+Alt+t, or Computer/File System/usr/bin/xterm)."\ "# (In it pressing c holding Ctrl aborts, and Tab does completion.) Enter:"\ "su (may need to do an sudo passwd root beforehand)"\ "cd / (check that you are in the right place with 'pwd' and 'ls')"\ "mkdir temporary_folder (folder to put the restored files in at first)"\ "cd temporary_folder (must not complain)"\ "pwd (MUST say /temporary_folder)"\ "chmod a+rx . (note the final point)"\ "dar_static -x '$base/1/MMDDYY_NNNNNN0' -g 'LOCATION/NAME' --verbose"\ "dar_static -x '$base/1/MMDDYY_NNNNNN1' -g 'LOCATION/NAME' --verbose --no-warn"\ "# (if encrypted add --key 'bf:PASSWORD' replacing any ! by \\! and ' by '"'"'"'"'"'"')"\ "# and so on to the date MMDDYY of the desired incremental backup."\ "# Here LOCATION/NAME is the folder or file to restore, relative to /"\ "# (leave out the leading / from the location in the right-click Properties)."\ "# (Replace /1/ by /2/ or /3/ or ... if you want to restore an older backup.)"\ "# Move the folder or file out of temporary_folder to its proper location,"\ "# making sure not to overwrite any files and folders that you want to keep:"\ "mv -i 'LOCATION/NAME' '../LOCATION' (or '../LOCATION/NAME_restored')"\ "# When all is OK, get rid of the temporary folder again:"\ "cd ; rm -r '/temporary_folder' (MUST use quotes)"\ "# (see also http://eng.fsu.edu/~dommelen/backup/ http://dommelen.net/backup/)"\ ) endrme: # Backup file filetype and grep regular expression for it: set ext='.1.dar' # first slice generated set exta='.[0-9]*.dar' # any slice of the backup set exts='\.1\.dar$' # first slice as grep string # End of variables to set. # Initial checks and actions # enable postprocessing unset do_post if ("$1" == "yes") then set do_post shift endif # override backup disk if specified on command line if ($#argv == 2) then set backdisk="$1" if ("$backdisk" == "") set backdisk=" " shift endif # see whether we just want help if ("$*" == "") goto procarg if ("$*" == '-h' || "$*" == '-?') goto procarg if ("$*" == '-help' || "$*" == '--help') goto procarg # if backdisk is not set, assume that no serious attempt to run is made if ("$backdisk" == "") then echo "This script performs backups. It must be edited before use." goto errexit endif # set the command being executed set dat=`date +'%m-%d-%y'` set cmd="$nam" if ("$*" != "") set cmd="$nam $*" set cmd="$cmd on `date +'%a %D %H:%M%P'`" # error folder not yet secured unset haverr # no lock file yet unset lckfil # no log file yet unset logfil # goto error processing on an interrupt onintr erri # try to secure the error folder set msg="Error messages folder errdir is not specified" if ("$errdir" == "") goto err set msg="The specification of error messages folder $errdir must start with /" if (`echo "$errdir" | grep -c '^/'` != 1) goto err set msg="Error messages folder '$errdir' does not exist" if !(-d "$errdir") goto err set msg="Unable to cd to error messages folder $errdir" cd "$errdir" if ($status) goto err set msg="Need more access to error messages folder $errdir" if !(-rwx .) goto err set haverr # no processing if there is a $nam_disabled file if (-e "${nam}_disabled") then if ("$*" != "enable") goto procarg endif # try to secure the lock file if !(-f "${nam}_running") goto endrml if ("$rmlock" == "") goto endrml set msg="Test if the lock file is older than $rmlock days using fnd failed" set i=`fnd -name "${nam}_running" -mtime +"$rmlock" | wc -l` if ($status) goto err set msg="Unable to remove expired lock file $cwd/${nam}_running" if ($i > 0) rm "${nam}_running" if ($status) goto err endrml: set msg="$nam is already running according to $cwd/${nam}_running" if (-f "${nam}_running") goto err set msg="Lock file $cwd/${nam}_running exists and is not a proper file" if (-e "${nam}_running") goto err set msg="Unable to initialize lock file $cwd/${nam}_running" echo "Running $cmd" > "${nam}_running" if ($status) goto err if !(-f "${nam}_running") goto err set lckfil="$cwd/${nam}_running" # enable the program if ("$*" != "enable") goto noena set msg="The $cwd/${nam}_disabled file does not exist" if !(-e "${nam}_disabled") goto err set msg="The $cwd/${nam}_disabled file is not a proper file" if !(-f "${nam}_disabled") goto err set msg="Unable to get file date of $cwd/${nam}_disabled using fdate" set olddat=`fdate "${nam}_disabled"` if ($status) goto err set msg="File $cwd/${nam}_$olddat already exists, read and remove it first" if (-f "${nam}_$olddat") goto err set msg="Unable to rename $cwd/${nam}_disabled to ${nam}_$olddat" mv "${nam}_disabled" "${nam}_$olddat" if ($status) goto err if !(-f "${nam}_$olddat") goto err goto finish noena: # find old log file set msg="Unable to search for old log files with fnd" set oldlog="`fnd -name ${nam}'_[0-9][0-9]-[0-9][0-9]-[0-9][0-9]' | tail -1`" if ($status) goto err if (-e "${nam}_$dat") set oldlog="$cwd/${nam}_$dat" if ("$oldlog" != "") then set msg="Old log $oldlog is not a proper file." if !(-f "$oldlog") goto err endif # disable the program if ("$*" != "disable") goto nodis if ("$oldlog" != "") then set msg="Unable to rename $oldlog to $cwd/${nam}_disabled" mv "$oldlog" "${nam}_disabled" if ($status) goto err if !(-e "${nam}_disabled") goto err else set msg="Unable to create $cwd/${nam}_disabled" set oldlog > "${nam}_disabled" if ($status) goto err if !(-f "${nam}_disabled") goto err endif goto finish nodis: # try to secure the log file if ("$oldlog" != "") then set msg="Unable to rename old log file $cwd/$oldlog" if ("$oldlog" != "$cwd/${nam}_$dat") mv "$oldlog" "$cwd/${nam}_$dat" if ($status) goto err if !(-f "${nam}_$dat") goto err # truncate old log size, maintaining its icon position set msg="Unable to check log file $cwd/${nam}_$dat size" set i=`cat "${nam}_$dat" | wc -l` if ($status) goto err set msg="Invalid number of lines to keep in the log" @ imax = $maxlines + $maxlines if ($status) goto err if ($i > $imax) then set msg="Unable to remove $cwd/${nam}_tmp" if (-e "${nam}_tmp") rm "${nam}_tmp" if (-e "${nam}_tmp") goto err set msg="Unable to truncate $cwd/${nam}_$dat to $cwd/${nam}_tmp" tail -$maxlines "${nam}_$dat" > "${nam}_tmp" if ($status) goto err if !(-f "${nam}_tmp") goto err if (`cat "${nam}_tmp" | wc -l` < $maxlines) goto err set msg="Unable to create truncated file $cwd/${nam}_$dat" cp "${nam}_tmp" "${nam}_$dat" if ($status) goto err rm "${nam}_tmp" if ($status) goto err endif set msg="Unable to write to the log file $cwd/${nam}_$dat" echo "" >> "${nam}_$dat" if ($status) goto err else set msg="Unable to create log file $cwd/${nam}_$dat" set i > "${nam}_$dat" if ($status) goto err if !(-f "${nam}_$dat") goto err endif set logfil="$cwd/${nam}_$dat" set msg="Unable to write to the log file $logfil" echo "Running $cmd" >> "$logfil" if ($status) goto err # check the existence of the backup disk or folder set msg="The backup disk backdisk=$backdisk must start with /" if (`echo "$backdisk" | grep -c '^/'` != 1) goto err set msg="Backup disk backdisk=$backdisk does not exist" if !(-e "$backdisk") goto err set msg="Backup disk backdisk=$backdisk is not a disk or folder" if !(-d "$backdisk") goto err # check variable nam set msg="Variable nam cannot be empty" if ("$nam" == "") goto err set msg="Variable nam cannot contain spaces" if (`echo "$nam" | grep -c '[ ]'` != 0) goto err set msg="Variable nam cannot start with a dash" if (`echo "$nam" | grep -c '^-'` != 0) goto err set msg="Illegal character in variable nam; allowed: 0-9, a-z, ., -, _" if (`echo "$nam" | grep -c '[^-.0-9A-Z_a-z]'` != 0) goto err # set the extended base name set base="$backdisk/$nam" # check the existence of the disk or folder to back up set msg="The disk or folder fsroot=$fsroot to back up must start with /" if (`echo "$fsroot" | grep -c '^/'` != 1) goto err set msg="The disk or folder fsroot=$fsroot to back up does not exist" if !(-e "$fsroot") goto err set msg="The disk or folder fsroot=$fsroot to back up is not a disk or folder" if !(-d "$fsroot") goto err # check variable marker (allow for it not being in fsroot) set msg="Variable marker is undefined" if !($?marker) goto err unset m if ("$marker" == "") goto endmkr set m="$marker" if (`echo "$m"|grep -c '^/'` == 0) set m="$fsroot/$marker" set msg="Variable marker cannot contain spaces" if (`echo "$marker" | grep -c '[ ]'` != 0) goto err set msg="Variable marker cannot start with a dash" if (`echo "$marker" | grep -c '^-'` != 0) goto err set msg="Illegal character in variable marker; allowed: 0-9, a-z, ., -, _, /" if (`echo "$marker" | grep -c '[^-._0-9A-Za-z/]'` != 0) goto err set e='IwGV1bS7TB' endmkr: # check skip set msg="Invalid skip: $skip" if ("$skip" != "" && "$skip" != "inc" && "$skip" != "all") goto err # check that only the final frequency digits are blank set msg="Frequency n1 cannot be blank" if ($n1 == ) goto err set msg= if ($n9 == ) set msg="$n9" if ($n8 == ) set msg="$n8$n9" if ($n7 == ) set msg="$n7$n8$n9" if ($n6 == ) set msg="$n6$n7$n8$n9" if ($n5 == ) set msg="$n5$n6$n7$n8$n9" if ($n4 == ) set msg="$n4$n5$n6$n7$n8$n9" if ($n3 == ) set msg="$n3$n4$n5$n6$n7$n8$n9" if ($n2 == ) set msg="$n2$n3$n4$n5$n6$n7$n8$n9" if ("$msg" != "") then set msg="Blank fields inside the backup frequency list" goto err endif set msg="Invalid fields inside the backup frequency list" set tmp=$n1$n2$n3$n4$n5$n6$n7$n8$n9 if ($status || "$n1$n2$n3$n4$n5$n6$n7$n8$n9" != "$tmp") goto err # check delete_backup if ("$delete_backup" != "") then set msg="Variable delete_backup must be a digit greater than 1" if (`echo "$delete_backup" | grep -c '^[2-9]$'` != 1) goto err endif # check that backupex is available set msg="The specification of backupex must start with /" if (`echo "$backupex" | grep -c '^/'` != 1) goto err set msg="Executable $backupex was not found" if !(-f "$backupex") goto err set msg="Executable $backupex is not executable" if !(-x "$backupex") goto err set e="`$backupex`" if ($status) goto err # check that dar_static is available set msg="The specification of dar_static must start with /" if (`echo "$dar_static" | grep -c '^/'` != 1) goto err set msg="Backup program $dar_static was not found" if !(-f "$dar_static") goto err set msg="Backup program $dar_static is not executable" if !(-x "$dar_static") goto err # check that gpg is available if we may need it alias g 'set msg="Unexpected call to gpg"; echo \!* > /dev/null; set status=1' if !($?m) goto endgpg if ("$*" == "init") goto chkgpg if (-fz "$m") goto endgpg chkgpg: set msg="Encoding program gpg was not found" which gpg > /dev/null if ($status) goto err set h if ("`whoami`" == 'root') set h=' --homedir /root' alias g "gpg$h --batch --yes --no-options -q --passphrase-repeat 0 --passphrase" endgpg: # process arguments procarg: # go to run (or terminate quietly if there is a disable file) if ("$*" == "auto") goto run if ("$*" == "new") goto run if ("$*" == "inc") goto run if ("$*" == "max") goto run if ("$*" == "1") goto run if ("$*" == "2") goto run if ("$*" == "3") goto run if ("$*" == "4") goto run if ("$*" == "5") goto run if ("$*" == "6") goto run if ("$*" == "7") goto run # initialize (or terminate with error if there is a disable file) if ("$*" == "init") goto init # disable is not possible set msg="Cannot disable $nam; $errdir/${nam}_disabled already exists" if ("$*" == "disable") goto err # print usage instructions set tmp="$nam yes backup_disk" echo "Usage: one of:" echo " $tmp init Creates the backup folder. Edit $nam first." echo " $tmp auto Does a backup" echo " $tmp new Forces a new backup" echo " $tmp inc Forces an incremental backup" echo " $tmp max Forces a new backup to be kept maximum time" echo " $tmp n Forces a new backup on weekday n (7=Sunday)" echo " $tmp disable Disables all backups" echo " $tmp enable Enables backups again" echo "where backup_disk is the path to backup disk $nam, (defaults to" echo "'$backdisk' if left away), and yes, if present, enables post processing." echo " No more than 36 successive incremental backups can be done without" echo "doing a full one." echo " When manually deleting an incremental backup from folder $nam/1," echo "be sure to also adjust file ../oldfnm.src. Do not delete full backups" echo "without doing a replacement full backup with '$nam new' afterwards." echo "In general, if the next backup that is performed is incremental, a" echo "previous good backup *must* be in $backdisk/$nam/1, and its filename" echo "*must* be settable by sourcing file $backdisk/$nam/oldfnm.src." echo " Be sure you regularly get desktop log files notifying you of" echo "successful backups or investigate." if ("$*" == "") goto errexit if ("$*" == "-h" || "$*" == "-?") goto errexit if ("$*" == "-help" || "$*" == "--help") goto errexit set msg="Invalid arguments: $*" goto err # initialize and exit if called with init init: # fail if disabled set msg="Cannot initialize $nam; there is already a ${nam}_disabled file" if (-e "$errdir/${nam}_disabled") goto err # check permissions for the backup disk folder set msg="Insufficient permissions for backup disk $backdisk" if !(-rwx "$backdisk") goto err # check $savefils set msg="Variable savefils is not set" if !($?savefils) goto err foreach tmp ($savefils) set msg="The full specification of file $tmp to save must start with /" if (`echo "$tmp" | grep -c '^/'` != 1) goto err set msg="File to save not found: $tmp" if !(-f "$tmp") goto err end # go to $fsroot set msg="The folder specification '$fsroot' in fsroot is incorrect" cd /bin cd "$fsroot" if ($status) goto err set tmp="`pwd`" cd "$HOME" cd "$fsroot" if ($status) goto err if ("`pwd`" != "$tmp") goto err set msg="Need more access to folder $fsroot. Try: sudo $nam init" if !(-rx .) goto err if ("$marker" == "") goto endsetmrk if !(-rwx .) goto err # check for an existing marker if !(-e $marker) goto fsisclr set msg="No access to hidden file $marker in $fsroot. Try: sudo $nam init" if !(-r $marker) goto err if (-z $marker) then echo "WARNING: replacing empty file $marker in $fsroot" goto rmolbin endif echo "" cat << EOF A file called $marker exists inside folder $fsroot. Such a file normally contains the password of the backups. Trying to read the password... EOF sp if !($status) goto curpwd nocurpwd: cat << EOF There is no readable password in the file. Initialization of the backups cannot proceed until the file $marker in $fsroot is out of the way. Please rename this file to something like $marker.save, then try again. Note that this is a hidden file; you may have to enable hidden files in the view menu, or use ls -a, to see it. EOF set msg="Aborted because $marker in $fsroot is in the way" goto err curpwd: if ("$password" == "") goto nocurpwd echo "The password in the file is: '$password'" cat << EOF Presumably you made earlier encrypted backups of this folder. The options are now: 1. Encrypt the new backup sets with the same password. 2. Delete file $marker and encrypt the new backups with a different password or leave them unencrypted. EOF askdgpg: echon "Enter 1 for choice 1 above, 2 for choice 2, or Ctrl+c to abort: " set ans="$<" if ("$ans" == 1) goto endsetmrk if !("$ans" == 2) then echo "*** enter 1 or 2 or press c while holding Ctrl to abort" goto askdgpg endif rmolbin: set msg="No access to hidden file $marker in $fsroot. Try: sudo $nam init" chmod u+w $marker rm $marker if ($status) goto err if (-e $marker) goto err fsisclr: # Ask whether encrypting is desired: cat << EOF Choose whether to encrypt or not: --------------------------------- Warning 1: If you encrypt the backups, you will simply NOT BE ABLE TO RESTORE your files if you forget the password. Dar will not even be to tell you whether the password you give it is correct or not. Warning 2: The password will be put in folder $fsroot in a file called $marker. A bad person that manages to get access to the files in that folder may also be able to see the password. So, if you decide to use encryption, do not use a password that you also use for something else, like for your bank account. Or a password similar to such a password. EOF echon \ 'Considering the warnings above, do you want to encrypt the backups? [y/n]: ' askenc: set ans="$<" if ("$ans" == "n") goto maknwmrk if ("$ans" != "y") then echon 'Please enter y for yes or n for no. [y/n]: ' goto askenc endif # get password echon 'Enter password (password will be visible\!): ' set ans="$<" askpwd: set password="$ans" if (`echo "$password" | wc -c` < 6) then echo "*** Password must be at least 6 characters" set password="" endif if (`echo "$password" | grep -c ' '` != 0) then echo "*** Too many spaces in password" set password="" endif echon ' enter password again: ' set ans="$<" if ("$password" == "") goto askpwd if ("$password" != "$ans") then echo 'The entered password does not match the previous one. Try again' goto askpwd endif # encode it set msg="Unknown error in encoding the password to $marker in $fsroot." echo "$password"| g "$e" -o "$m" -c if ($status) goto pwderr if !(-e $marker) goto err # ask for final confirmation set msg="Unable to retrieve the password from $marker in $fsroot" sp if ($status) goto pwderr echo " Your password is, in quotes to show all: '$password'" set msg="Script error. Password after retrieval does not match the original" if ("$ans" != "$password") goto pwderr echo "If there is an error in the above password, hold Ctrl and press c." echon "Otherwise remember this password and hit Enter: " set ans="$<" set msg="Unable to set protection on $marker in $fsroot???" chmod u=r,go= $marker if ($status) goto pwderr set msg="Unable to change ownership of $marker in $fsroot to $owner" if ("$owner" != "") chown "$owner" $marker if ($status) goto pwderr goto endsetmrk # create an empty file to check that the disk is mounted maknwmrk: set msg="Unable to create marker file $marker in $fsroot" set tmp > $marker if ($status) goto pwderr if !(-e $marker) goto err if !(-z $marker) goto pwderr set msg="Unable to set protection on $marker in $fsroot???" chmod u=r,go= $marker if ($status) goto pwderr set msg="Unable to change ownership of $marker in $fsroot to $owner" if ("$owner" != "") chown "$owner" $marker if ($status) goto pwderr goto endsetmrk # get rid of the file again pwderr: if (-e $marker) chmod u+w $marker if (-e $marker) rm $marker if (-e $marker) then echo "*** $msg" set msg=\ "Access denied: please delete hidden file $marker in $fsroot manually" endif goto err # done setting up the marker in fsroot endsetmrk: # create the backup folder set msg="Unable to create folder $base, it exists" if (-d "$base") goto err set msg="Unable to create folder $base" mkdir "$base" if ($status) goto err if !(-d "$base") goto err set msg="Unable to set protection on folder $base???" $chm "$base" if ($status) goto err # cd to it set msg="Unable to cd to folder $base" cd "$base" if ($status) goto err if (`pwd | grep -c "/$nam"'$'` != 1) goto err # create the backup age-level subfolders set msg="Unable to create folder $base/1" mkdir 1 if !(-d 1) goto err if ($n2 != ) mkdir 2 if ($n3 != ) mkdir 3 if ($n4 != ) mkdir 4 if ($n5 != ) mkdir 5 if ($n6 != ) mkdir 6 if ($n7 != ) mkdir 7 if ($n8 != ) mkdir 8 if ($n9 != ) mkdir 9 $chm `find . -type d` # create the starting file name set msg="Unable to create oldfnm.src in $base" echo "set oldfnm='000000_$n9$n8$n7$n6$n5$n4$n3$n2$n1'" > oldfnm.src if ($status) goto err if !(-f oldfnm.src) goto err chmod a-x oldfnm.src $chm oldfnm.src # copy in the requested files foreach tmp ($savefils) set msg="Error saving file $tmp to the backup folder" cp "$tmp" . if ($status) goto err end # create the readme file if !($?readme) goto endwrm set msg="Error creating readme.txt file in the backup folder" echo "" > readme.txt if ($status) goto err if !(-f readme.txt) goto err set i=0 lpwrm: @ i = $i + 1 if ($i > $#readme) goto endwrm echo "$readme[$i]" >> readme.txt if ($status) goto err goto lpwrm endwrm: set msg="Unable to copy /etc/fstab" cp /etc/fstab oldfstab.txt if ($status) goto err set msg="Unable to list current mount info" mount > oldmount.txt if ($status) goto err set msg="Unable to list current df info" df > olddf.txt if ($status) goto err set msg="Unable to list /" ls -l / > oldslash.txt if ($status) goto err if !(-x /sbin/blkid) goto endwbi set msg="Unable to get blkid info" if (`blkid | wc -l` == 0) goto err blkid > oldblkid.txt if ($status) goto err endwbi: # change ownership set msg="Unable to change ownership of $base to $owner" if ("$owner" != "") chown -R "$owner" . if ($status) goto err # notify of success: echo "Folder $base successfully initialized." >> "$logfil" echo "Folder $base successfully initialized." # finish up goto finish # run run: # done if disabled if (-e "$errdir/${nam}_disabled") goto okexit # cd to $fsroot set msg="The folder specification '$fsroot' in fsroot is incorrect" cd /bin cd "$fsroot" if ($status) goto err set tmp="`pwd`" cd "$HOME" cd "$fsroot" if ($status) goto err if ("`pwd`" != "$tmp") goto err set msg="Insufficient access to folder $fsroot." if !(-rx .) goto err # set password if any set password="" if !($?m) goto endgetmrk set msg="Missing marker file $marker in $fsroot. Is the disk mounted?" if !(-e $marker) goto err if (-z $marker) goto endgetmrk set msg="Insufficient access to hidden file $marker in $fsroot" if !(-r $marker) goto err set msg="Unable to read password from hidden file $marker in $fsroot" sp if ($status) goto err if ("$password" == "") goto err endgetmrk: # cd to the backup folder set msg="Folder $base does not exist" if !(-d "$base") goto err set msg="Insufficient permissions for folder $base" if !(-rwx "$base") goto err set msg="Unable to cd to folder $base" cd "$base" if ($status) goto err # check that we can delete any oldfnm.old backup if (-e oldfnm.old) then set msg="Invalid file: $base/oldfnm.old" if !(-f oldfnm.old) goto err set msg="No privileges to delete $base/oldfnm.old" if !(-rw oldfnm.old) goto err endif # get the old backup file name set msg="File $base/oldfnm.src not found" if !(-f oldfnm.src) goto err set msg="No permisions for file $base/oldfnm.src" if !(-rw oldfnm.src) goto err set oldfnm= set msg="File $base/oldfnm.src is corrupt" source oldfnm.src if ($status) goto err if ("$oldfnm" == "") goto err if ("$*" == "inc") then set msg="Too many incremental backups" if (`echo "$oldfnm$ext" | grep -c "Z$exts"` != 0) goto err set n1=Z endif # get the new file name (for new backups, search for a 0 final digit) set fnm="$oldfnm" if ("$*" == "max") set fnm="000000_$n9$n8$n7$n6$n5$n4$n3$n2$n1" @ iter = 0 gennam: set msg="Unable to remove fnm.tmp" if (-e fnm.tmp) rm fnm.tmp if (-e fnm.tmp) goto err set msg="Failure while running $backupex" "$backupex" "$fnm" "$n9$n8$n7$n6$n5$n4$n3$n2$n1" >> "$logfil" if ($status) goto err if !(-f fnm.tmp) goto err set msg="File fnm.tmp is corrupt" set fnm= source fnm.tmp if ($status) goto err if ("$fnm" == ) goto err rm fnm.tmp @ iter = $iter + 1 if ($iter > 36) then set msg="Stuck in a file name loop" goto err endif if ("$*" == "new" || "$*" == `date +'%u'`)then if (`echo "$fnm$ext" | grep -c "0$exts"` == 0) goto gennam endif # cd to the backup folder set msg="Insufficient permissions for folder $base/1" if !(-rwx "$base/1") goto err set msg="Unable to cd to folder $base/1" cd 1 if ($status) goto err if (`pwd | grep -c "/$nam/1"'$'` != 1) goto err # delete any junked backups if (`fnd -name "*$exta.bad" | wc -l` != 0) then set msg="Unable to get rid of the bad old backups" rm *$exta.bad if ($status) goto err if (`fnd -name "*$exta.bad" | wc -l` != 0) goto err endif if (`fnd -name "*.log.bad" | wc -l` != 0) rm *.log.bad # decide whether to do an incremental or new backup if (`echo "$fnm$ext" | grep -c "0$exts"` != 0) goto donew # process incremental backups doinc: # see whether the previous backup exists set msg="Previous backup $oldfnm$ext not in $backdisk/$nam/1" if !(-f $oldfnm"$ext") goto err # remove any existing failed backups if (`fnd -name "$fnm$exta" | wc -l` == 0) goto noorphs set msg="Unable to remove the orphaned backups $fnm$exta" echo "** removing orphaned backups $fnm$exta" >> "$logfil" echo "** removing orphaned backups $fnm$exta" rm $fnm$exta if ($status) goto err noorphs: # skip if $skip is set to inc or all and there are no newly modified files if ("$skip" != "inc" && "$skip" != "all") goto noiskp set msg="Unable to figure out newly modified files" set i=`find "$fsroot" -newer $oldfnm"$ext" | wc -l` if ($status) goto err if ("$i" != 0) goto noiskp echo "No modified files found. Terminating" >> "$logfil" if ("$oldlog" != "") then if ("$logfil" != "$oldlog") mv "$logfil" "$oldlog" endif unset logfil goto finish noiskp: # log the backup command set backprog="echo $dar_static" set msg="Unable to write backup parameters to $base/1/$fnm.log" if ("$password" == "") then backcmd --ref "`pwd`/$oldfnm" >> $fnm.log if ($status) goto err else backcmd --ref "`pwd`/$oldfnm" \ --key "bf:PASSWORD" --key-ref "bf:PASSWORD" >> $fnm.log if ($status) goto err endif # back up set backprog="$dar_static" if ("$password" == "") then backcmd --ref "`pwd`/$oldfnm" >> $fnm.log set bckstat="$status" else backcmd --ref "`pwd`/$oldfnm" \ --key "bf:$password" --key-ref "bf:$password" >> $fnm.log set bckstat="$status" endif # done goto didit # process a new backup donew: # skip if $skip is set to all and there are no newly modified files if ("$skip" != "all") goto nonskp if !(-f $oldfnm"$ext") then echo "** No current backup. Ignoring skip." >> "$logfil" goto nonskp endif set msg="Unable to figure out newly modified files" set i=`find "$fsroot" -newer $oldfnm"$ext" | wc -l` if ($status) goto err if ("$i" != 0) goto nonskp echo "No modified files found. Terminating" >> "$logfil" if ("$oldlog" != "") then if ("$logfil" != "$oldlog") mv "$logfil" "$oldlog" endif unset logfil goto finish nonskp: # clear the first folder that can be set msg="Insufficient privileges for the backup folders" if (`ls -1 | wc -l` == 0) goto mov1 if ($status) goto err if (-d ../2 && `ls -1 | grep -c "00$exts"` != 0) goto clr2 rm * if ($status) goto err goto mov1 clr2: cd ../2 if (`ls -1 | wc -l` == 0) goto mov2 if ($status) goto err if (-d ../3 && `ls -1 | grep -c "000$exts"` != 0) goto clr3 rm * if ($status) goto err goto mov2 clr3: cd ../3 if (`ls -1 | wc -l` == 0) goto mov3 if ($status) goto err if (-d ../4 && `ls -1 | grep -c "0000$exts"` != 0) goto clr4 rm * if ($status) goto err goto mov3 clr4: cd ../4 if (`ls -1 | wc -l` == 0) goto mov4 if ($status) goto err if (-d ../5 && `ls -1 | grep -c "00000$exts"` != 0) goto clr5 rm * if ($status) goto err goto mov4 clr5: cd ../5 if (`ls -1 | wc -l` == 0) goto mov5 if ($status) goto err if (-d ../6 && `ls -1 | grep -c "000000$exts"` != 0) goto clr6 rm * if ($status) goto err goto mov5 clr6: cd ../6 if (`ls -1 | wc -l` == 0) goto mov6 if ($status) goto err if (-d ../7 && `ls -1 | grep -c "0000000$exts"` != 0) goto clr7 rm * if ($status) goto err goto mov6 clr7: cd ../7 if (`ls -1 | wc -l` == 0) goto mov7 if ($status) goto err if (-d ../8 && `ls -1 | grep -c "00000000$exts"` != 0) goto clr8 rm * if ($status) goto err goto mov7 clr8: cd ../8 if (`ls -1 | wc -l` == 0) goto mov8 if ($status) goto err if (-d ../9 && `ls -1 | grep -c "000000000$exts"` != 0) goto clr9 rm * if ($status) goto err goto mov8 clr9: cd ../9 if (`ls -1 | wc -l` != 0) rm * if ($status) goto err # move the files to be kept out of the way mv ../8/* . if ($status) goto err cd ../8 mov8: mv ../7/* . if ($status) goto err cd ../7 mov7: mv ../6/* . if ($status) goto err cd ../6 mov6: mv ../5/* . if ($status) goto err cd ../5 mov5: mv ../4/* . if ($status) goto err cd ../4 mov4: mv ../3/* . if ($status) goto err cd ../3 mov3: mv ../2/* . if ($status) goto err cd ../2 mov2: mv ../1/* . if ($status) goto err cd ../1 mov1: # log the backup command set backprog="echo $dar_static" set msg="Unable to write backup parameters to $base/1/$fnm.log" if ("$password" == "") then backcmd >> $fnm.log if ($status) goto err else backcmd --key "bf:PASSWORD" >> $fnm.log if ($status) goto err endif # back up set backprog="$dar_static" if ("$password" == "") then backcmd >> $fnm.log set bckstat="$status" else backcmd --key "bf:$password" >> $fnm.log set bckstat="$status" endif # done goto didit # handle backup return status didit: echo "$dar_static command returned status $bckstat" >> $fnm.log cat $fnm.log >> "$logfil" if (`echo "$statnoti" | grep -w -c $bckstat` == 1) goto noabo if (`echo "$statign" | grep -w -c $bckstat` == 1) then unset bckstat goto noabo endif mv $fnm.log $fnm.log.bad if (`fnd -name "$fnm$exta" | wc -l` == 0) goto nobaddars foreach f ($fnm$exta) set msg="$dar_static failed, $bckstat, and cannot get rid of the junk" mv $f $f.bad if ($status) goto err end nobaddars: set msg="Backup command $dar_static failed; status: $bckstat" goto err noabo: set msg="Missing reference backup $backdisk/$nam/1/$fnm" if !(-f $fnm"$ext") goto err # set the backup as the old filename set msg="Unable to move $base/oldfnm.src to oldfnm.old" if (-e ../oldfnm.src) mv ../oldfnm.src ../oldfnm.old if (-e ../oldfnm.src) goto err set msg="Unable to create $backdisk/$nam/oldfnm.src" echo "set oldfnm='$fnm'" > ../oldfnm.src if !(-f ../oldfnm.src) goto err chmod a-x ../oldfnm.src $chm ../oldfnm.src # set file protection chmod a-x $fnm$exta $chm $fnm$exta chmod a-x $fnm.log $chm $fnm.log # set ownership of the backups set msg="Unable to change ownership of the files in `pwd` to $owner" if ("$owner" != "") then chown "$owner" * if ($status) goto err chown "$owner" ../* if ($status) goto err endif # remove the backups in folder delete_backup, if any if ("$delete_backup" == "") goto enddelold set msg="Backup folder $base/$delete_backup to clean out does not exist" if !(-d "$base/$delete_backup") goto err if (`ls -1 "$base/$delete_backup" | wc -l` == 0) goto enddelold set msg="Error cleaning out old backup folder $base/$delete_backup" rm "$base/$delete_backup"/* if ($status) goto err enddelold: # notify of error if ($?bckstat) then set msg="Backup command $dar_static had problems; status: $bckstat" goto err endif # finish up goto finish # finish finish: # mark as done if ($?logfil) then echo "Done: $cmd" >> "$logfil" echo " `date +'%c'`" >> "$logfil" endif # remove the lock file if ($?lckfil) then set msg="Unable to remove lock file $lckfil" rm "$lckfil" if (-e "$lckfil") goto err endif # give the error folder owner ownership of the log files cd "$errdir" if !($status) chown `stat -c %U .`:`stat -c %G .` ${nam}_* # all done goto okexit # error processing erri: # no more jumping to erri onintr # interrupted set msg="Interrupted" err: # to be safe unset password # put a failure message in $errdir if !($?haverr) goto enderr if (-e "$errdir/${nam}_FAILED") then echo "FAILED: $cmd" >> "$errdir/${nam}_FAILED" else echo "FAILED: $cmd" > "$errdir/${nam}_FAILED" endif echo "*** $msg\!" >> "$errdir/${nam}_FAILED" if ($status) then echo "*** $cmd $msg\!" > "$errdir/${nam}_FAILED_AGAIN" endif if ($?logfil) then echo "*** $msg\!" >> "$logfil" echo " `date +'%c'`" >> "$logfil" endif enderr: # remove the lock file if ($?lckfil) then rm "$lckfil" endif # echo the message to stdout, wherever that goes if ("$*" == "init") then echo "*** $msg\!" else echo "*** $msg\!" echo " `date +'%c'`" endif # send a mail message if ("$mailprog" == "") goto endemail echo "$msg" | $mailprog "FAILED: $cmd" endemail: # give the error folder owner ownership of the log files cd "$errdir" if !($status) chown `stat -c %U .`:`stat -c %G .` ${nam}_* # exit in disgrace errexit: if ($?do_post && "$post_on_error" != "") then $post_on_error endif exit 1 # exit successfully okexit: unset password if ($?do_post && "$post_on_success" != "") then $post_on_success endif exit 0 # shut down the computer (I am unable to do this using nohup &) shutdown: unset password /sbin/shutdown -P +1 'To cancel, in a terminal: sudo shutdown -c'