#! /bin/bash # after-dirvish, a tool for copying certain Dirvish logs, etc. to local storage # (from an external/removable device mounted on the bank directory) # Version 1.1 # # Usage: after-dirvish # # Directory structure within /var/log/dirvish (bank name is ignored): # # summary # # drive_desc.txt # index.gz # .log # .log.gz # .log.gz # # ... # # ... # # # Copyright (C) 2011 Alastair Irvine # Warpspace IT # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # On Debian systems, the complete text of the GNU General Public License # can be found in `/usr/share/common-licenses/GPL'. old_log_limit=2 # number of log files to keep around (other than the current one) log_dir=/var/log/dirvish DIRVISH_CONFIG=/etc/dirvish/master.conf # extract the bank directory from the master config file and print it # (whether or not it is on the same line as the Bank statement) extract_bank_dir() { awk 'BEGIN { bankline = -1 } tolower($1) == "bank:" { if (NF == 1) bankline = NR + 1; else print $2; } NR == bankline { print $1; }' $DIRVISH_CONFIG } # extract the vault names from the master config file and print them # (whether or not they are on the same line as the Runall statement) extract_active_vaults() { awk 'BEGIN { print_it = 0 } /^[^\t ]/ || /^$/ { print_it = 0; } # stop printing once a keyword or blank line is found print_it && !/^#/ { print $1; } # print the line before the flag is turned on to avoid printing the Runall: keyword tolower($1) == "runall:" { # look for vault names after Runall statement value = substr($0, 8); match_pos = match(value, /[^#]*/); names = substr(value, match_pos, RLENGTH); if (match_pos > 0 && match(names, /[^ \t]/) > 0) print names; else # otherwise vault name(s) are on subsequent lines print_it = 1; }' $DIRVISH_CONFIG } # *** MAINLINE *** # == command-line handling == # (no options supported) # process args case ${#*} in 0) echo after-dirvish: No UUID specified >&2 exit 1 ;; 1) uuid=$1 desc=None ;; *) uuid=$1 shift desc="$*" esac # == Sanity checking == bank_dir=`extract_bank_dir` ## echo $bank_dir if [ -z $bank_dir ] ; then echo after-dirvish: No Bank defined >&2 exit 2 fi if [ ! -d $bank_dir ] ; then echo after-dirvish: Bank not found >&2 exit 3 fi if [ -z "`ls $bank_dir`" ] ; then echo after-dirvish: Bank is empty >&2 exit 4 fi current_bank=${bank_dir##*/} if [ "`echo $bank_dir/*/dirvish`" = $bank_dir/'*/dirvish' ] ; then echo after-dirvish: No vaults found in bank directory $bank_dir >&2 exit 5 fi # == Processing == process_vault() { local vault_dir=$1 vault=$2 local histfile=$vault_dir/dirvish/default.hist # logging info for $vault in $current_bank local last_image_name=`sed -n '$ s/\t.*//p' $histfile` if [ -z $last_image_name ] ; then echo "after-dirvish: Warning: no image found on last line of '$histfile'" >&2 return 3 fi local image_dir=$vault_dir/$last_image_name if [ ! -d $image_dir ] ; then echo "after-dirvish: Warning: image '$image_dir' not found" >&2 return 4 fi local vault_log_dir=$log_dir/$vault ## echo processing $vault_log_dir ; return mkdir -p $vault_log_dir # only copy the stuff from the image dir if this vault has a new image # i.e. there is no .log for the mounted drive already in $vault_log_dir local dest_log_file=$vault_log_dir/$uuid/$last_image_name.log if [ ! -f $dest_log_file ] ; then # == update the summary file in the vault's log dir (include UUID) == mv $vault_log_dir/summary $vault_log_dir/summary.bak 2> /dev/null # fail if the file isn't writable set -e touch $vault_log_dir/summary set +e # create a new one (echo filesystem: $uuid if [ "$desc" != None ] ; then echo "($desc)" ; fi echo ; cat $image_dir/summary) > $vault_log_dir/summary # == store stuff for the mounted drive into the appropriate log subdir == mkdir -p $vault_log_dir/$uuid cp -p $histfile $vault_log_dir/$uuid # -- copy and rotate the log files from the image dir -- local files=(`ls -t $vault_log_dir/$uuid/*.log.gz 2>/dev/null`) if [ ${#files[*]} -ge $old_log_limit ] ; then local oldest_file=${files[${#files[*]}-1]} rm $oldest_file fi # should only be one existing log file without a .gz extension; # archive and replace it with a "copy" of the new log file gzip $vault_log_dir/$uuid/*.log 2>/dev/null if [ -r $image_dir/log ] ; then cp -p $image_dir/log $dest_log_file else zcat $image_dir/log.gz > $dest_log_file fi # -- copy the rest of the stuff from the image dir and add other stuff -- (echo "$desc" ; df -m $vault_dir ) > $vault_log_dir/$uuid/drive_desc.txt ## readlink --canonicalize /dev/disk/by-uuid/$uuid # it's in the df output cp -p $image_dir/index.gz $vault_log_dir/$uuid 2> /dev/null fi } # Iterate over all the vaults in the bank vault_names=`extract_active_vaults` if [ -n "$vault_names" ] ; then for vault in $vault_names ; do vault_dir=$bank_dir/$vault if [ ! -d $vault_dir/dirvish -o ! -r $vault_dir/dirvish/default.hist ] ; then echo "after-dirvish: Warning: specified Runall vault '$vault' is not valid" >&2 continue fi process_vault $vault_dir $vault done else # no Runall keyword, so look in the bank for vaults for dirvish_subdir in $bank_dir/*/dirvish ; do vault_dir=${dirvish_subdir%/*} process_vault $vault_dir ${vault_dir##*/} done fi