On Wed, Mar 24, 2004 at 02:46:08PM +0800, Mathias Koerber wrote: > > d) I was looking into pre-post dump actions (eg to stop a database or email > delivery) > I found the tips to write a specialized tar (amgtar) script which does > this. > My question however is whether the protocol between server and client > could > handle this, or at least handle whether a pre-post function is to be > called and > its results etc. > > I understand that security is an issue, which means that which scripts > are allowed to > run on each client should be controlled on that client itself, which > speaks for a > local amgtar. > > Does anyone already have such a script which is flexible to support > several pre/post > dump (and pre/post estimate?) scripts as well as handles errors in such > scripts?
Quite a while ago JRJ posted the attached readme and wrapper script. I've not used them, just still have them available. -- Jon H. LaBadie [EMAIL PROTECTED] JG Computing 4455 Province Line Road (609) 252-0159 Princeton, NJ 08540-4322 (609) 683-7220 (fax)
Subject: Re: Synchronizing Amanda with Applications >I looked at the archives. I found some references to such wrappers, >but I've failed to find a good example of one, and what needs to be done >on which machine (client/server). OK, you asked for it :-). Some notes on the following over-engineered, under-tested, script: * It has **NOT** been run in a full Amanda setup, other than what little I did to make sure syntax was right and the general flow worked. * The script uses **EXAMPLE** execution point functions (see the code). You **WILL** have to change it to do what you want (and remove what you don't). * There are definitions of the Amanda debug directory (e.g. /tmp/amanda) and path to GNU tar (on the client) in the first few lines that may need to be tweaked for your environment. * It is written in ksh (although now that I think about it, I probably could have used Perl). Hopefully the examples and your own shell coding experience will be sufficient to fit in what you need, but if you want some help, ask me offline. The idea is to install this on the client and build Amanda there using --with-gnutar=<path-to-script>. Then set up the disks you want to use this wrapper with GNU tar as the dump program in disklist and add execution point functions (see the code) to the script to do what you need. Note that the script doesn't have to actually use GNU tar -- that's just the trick to get Amanda to call it with a set of arguments that are easy to decipher. You can use a run_* function to use whatever dump program you want, as long as it generates an estimate to stdout that Amanda can parse and sends the actual dump image to stdout. Note also that compression is a separate step Amanda will tack on to the stdout of this script (or not). If you want to do your own compression, add it to the script and tell Amanda "compress none". Then test it at least once :-). If you set the DEBUG environment variable to "print" (or "echo" -- same difference), the script will run but not execute anything (although you'll have to set up your own functions to follow the examples in the code). Here is a sample test line I used (using ksh as a login shell): DEBUG=print gtar-wrapper.ksh \ --directory /home/HomeAC \ --file - \ . Amanda will pass whatever you set in disklist as the --directory argument. To test estimates, change "-" to "/dev/null" for the --file argument. Amanda passes a mess of other parameters, but only --directory and --file are of interest to the script. If you do any significant argument processing, make sure you don't loose anything (see function do_home in the script). I think. :-) John R. Jackson, Technical Software Specialist, [EMAIL PROTECTED] ** Additional notes -- 12-Sep-01 ** Fixed some truly silly bugs. Rewrote enough of the code to be able to run under bash as well as ksh.
#!/bin/ksh ### # This script is called by an Amanda client to run GNU tar. We look # through the arguments for what is being processed and (optionally) # run extra things before and/or after GNU tar, or alter the actual # command run (e.g. different GNU tar flags and options or a completely # different program). # # Remember that this script runs as root under the Amanda runtar program. # Exercise appropriate caution. # # To test, run with the DEBUG environment variable set to "echo". # The command line need not look exactly like what Amanda issues, but # must include the --directory <dir-to-back-up> and --file <outfile> # flags as well as the trailing ".". To test an estimate, set the # output file to "/dev/null": # # env DEBUG=echo ./gtar-wrapper.ksh --directory /whatever --file /dev/null . # # and to test the real dump, set it to "-": # # env DEBUG=echo ./gtar-wrapper.ksh --directory /whatever --file - . # # John R. Jackson ([EMAIL PROTECTED]) # Purdue University Computing Center # # 24-Mar-00: Initial version. # # 12-Sep-01: Fixed several bugs (sigh) and converted the code so it would # work under bash as well as ksh. ### PN=${0##*/} if [[ -z $DEBUG ]] then log=/tmp/amanda/$PN.$$ # <<< change as needed rm -f $log else log=/dev/tty fi GTAR=${GTAR:-/opt/tar/bin/gtar} # <<< change as needed ### # Define functions to be called at various execution points. The name # determines when the function is called: # # pre_estimate_* called before a GNU tar estimate # pre_real_* called before a GNU tar real run # run_estimate_* called to run a GNU tar estimate # run_real_* called to run a GNU tar real run # post_estimate_* called after a GNU tar estimate # post_real_* called after a GNU tar real run # # The rest of the function name comes from the directory being processed # by converting everything other than alphanumerics and the underscore # to an underscore, e.g. /home/abc becomes _home_abc. # # If a function does not exist for a particular execution point, nothing # special is done. ### ### # The following set of functions (*_some_db) show how you might set # up the execution points to shut down and restart a database around # the Amanda steps. ### ### # This function is called before we get the estimate of /some/db. ### function pre_estimate__some_db { echo "$PN: shutting down the database" >> $log } ### # This function is called after we get the estimate of /some/db. ### function post_estimate__some_db { echo "$PN: starting the database" >> $log } ### # This function is called before we dump /some/db. ### function pre_real__some_db { echo "$PN: shutting down the database" >> $log } ### # This function is called after we dump /some/db. ### function post_real__some_db { echo "$PN: starting the database" >> $log } ### # The following set of function are called to process groups of home # directories. The Amanda disklist entries are "faked" to indicate # a range of directories to be processed instead of a single item. # For instance, /home/HomeAC (which should not actually exist) would be # converted into all the directories in /home that start with a, b or c. # # This might be used to get around the current limit on the number of # "disks" Amanda can handle on a given client or to make it easier to # set up groups of things to back up without exclusion lists. ### function run_estimate__home_HomeAC { echo "$PN: preparing to estimate homes a* through c*" >> $log do_home a c "$@" return $? } function run_real__home_HomeAC { echo "$PN: preparing to dump homes a* through c*" >> $log do_home a c "$@" return $? } ### # The first and second args to do_home are the start and end names. # The remaining args are passed to GNU tar pretty much as is, except # --directory which is shortened to the home directory base. ### function do_home { ### # Copy all the args except the last one (which should be ".") and # tweak the --directory value. ### start=$1 shift end=$1 shift typeset -i do_directory=0 new_args= typeset -i first_arg=1 for arg do if ((first_arg == 0)) then a=$last_arg if ((do_directory)) then base_directory=${last_arg%/*} a=$base_directory do_directory=0 elif [[ X"$last_arg" = X"--directory" ]] then do_directory=1 # --directory dir-to-back-up fi new_args="$new_args $a" fi first_arg=0 last_arg=$arg done if [[ X"$base_directory" = X"" ]] then echo "$PN: cannot parse args: --directory not found" >> $log echo "$PN: cannot parse args: --directory not found" 1>&2 return 1 elif [[ X"$last_arg" != X"." ]] then echo "$PN: cannot parse args: . not at end" >> $log echo "$PN: cannot parse args: . not at end" 1>&2 return 1 fi \cd $base_directory || return 1 typeset -i s e s=36#$start e=36#$end ((s = s - 10)) # 'a' -> 0 ((e = e - 10)) # 'z' -> 25 alpha[0]=a alpha[1]=b alpha[2]=c alpha[3]=d alpha[4]=e alpha[5]=f alpha[6]=g alpha[7]=h alpha[8]=i alpha[9]=j alpha[10]=k alpha[11]=l alpha[12]=m alpha[13]=n alpha[14]=o alpha[15]=p alpha[16]=q alpha[17]=r alpha[18]=s alpha[19]=t alpha[20]=u alpha[21]=v alpha[22]=w alpha[23]=x alpha[24]=y alpha[25]=z typeset -i found_homes=0 while (($s <= $e)) do for dir in $(ls -1d ${alpha[$s]}* 2>/dev/null) do if [[ -d $dir ]] then new_args="$new_args $dir" found_homes=1 fi done ((s = s + 1)) done \cd - > /dev/null if ((found_homes == 0)) then echo "$PN: no homes to process in range $start..$end" >> $log echo "$PN: no homes to process in range $start..$end" 1>&2 return 1 fi set -- $new_args echo "$PN: running $GTAR" "$@" >> $log $DEBUG $GTAR "$@" } ### # Utility functions. ### function IsFunction { f=$1 echo "$PN: looking for $f" >> $log if [[ -n "$BASH_VERSION" ]] then t=$(type -t "$f" 2> /dev/null) r=$? else t=$(whence -v "$f" 2> /dev/null) r=$? fi if [[ $r -eq 0 ]] then if [[ "$t" != *function* ]] then r=1 fi fi return $r } ### # Start of main code. ### ### # Set up a log file in /tmp/amanda. ### echo "$PN: start: $(date)" >> $log echo "$PN: args:" "$@" >> $log ### # Find the directory Amanda is asking us to back up. Also figure out # if we are doing an estimate or the real thing. ### typeset -i get_directory=0 typeset -i get_file=0 directory_arg= file_arg= for arg do if ((get_directory)) then directory_arg=$arg get_directory=0 elif ((get_file)) then file_arg=$arg get_file=0 elif [[ X"$arg" = X"--directory" ]] then get_directory=1 # --directory dir-to-back-up elif [[ X"$arg" = X"--file" ]] then get_file=1 # --file file-to-write-to fi done echo "$PN: directory: $directory_arg" >> $log echo "$PN: file: $file_arg" >> $log if [[ X"$file_arg" = X"-" ]] then type=real # real dump if output is stdout elif [[ X"$file_arg" = X"/dev/null" ]] then type=estimate # estimate if output is /dev/null else type=unknown # no idea what is going on fi ### # Make the directory name into something we can use as part of a function # name by converting the slashes to underscores. Hopefully there is # not anything else annoying in the name. ### d=$(echo $directory_arg | /bin/sed 's/[^a-zA-Z0-9_]/_/g') ### # See if there is something to be done before we call GNU tar. ### if IsFunction pre_${type}_$d then echo "$PN: running pre_${type}_$d" >> $log pre_${type}_$d else echo "$PN: pre_${type}_$d not found so nothing special run" >> $log fi ### # Run GNU tar or a private function. ### if IsFunction run_${type}_$d then echo "$PN: running run_${type}_$d" >> $log run_${type}_$d "$@" exit_code=$? else echo "$PN: running $GTAR" >> $log $DEBUG $GTAR "$@" exit_code=$? fi ### # See if there is something to be done after we ran GNU tar. ### if IsFunction post_${type}_$d then echo "$PN: running post_${type}_$d" >> $log post_${type}_$d else echo "$PN: post_${type}_$d not found so nothing special run" >> $log fi ### # Exit with the GNU tar exit code. ### echo "$PN: end: $(date)" >> $log exit $exit_code