Ok, I've changed over to the new version that was suggested, and I have also incorporated the suggestions of several people who's name escape me (sorry). This now has the 'mt offline' variable of the newest chg-zd-mtx, and tests whether your drives provides an 'offline', or an 'ONLINE' when changing from offline to online. It is also in chg-zd-mtx.sh.in form, so it can be linked in with the configure step. I would appreciate it if some people can test this, both with a large barcode reader, and also some more standard <10 slot drives. I want to be sure that I didn't break a working script just to add my parts. Thanks... -- Jason Hollinden SMG Systems Admin
#!/bin/sh # # Exit Status: # 0 Alles Ok # 1 Illegal Request # 2 Fatal Error # # Contributed by Eric DOUTRELEAU <[EMAIL PROTECTED]> # This is supposed to work with Zubkoff/Dandelion version of mtx # # Modified by Joe Rhett <[EMAIL PROTECTED]> # to work with MTX 1.2.9 by Eric Lee Green http://mtx.sourceforge.net # # Modified by Jason Hollinden <[EMAIL PROTECTED]> on 13-Feb-2001 # to work with MTX 1.2.10, >9 slots, and added barcode support. # NOTE: Only tested the 2 additions with an ADIC Scalar 100. # All my additions have a '#### Comment' close by. ###################################################################################### # You may need to customize these things MT=@MT@ MTF=@MT_FILE_FLAG@ MTX=@MTX@ firstslot=1 lastslot=7 # Don't forget to leave out the cleaning tape. cleanslot=8 # Which slot contains your cleaning tape? OFFLINE_BEFORE_UNLOAD=0 # Does your tape driver require a # 'mt offline' before mtx unload? # Do you want to clean the drive after a certain number of accesses? # NOTE - This is unreliable, since 'accesses' aren't 'uses', and we # have no reliable way to count this. A single amcheck could # generate as many accesses as slots you have, plus 1. # ALSO NOTE - many modern tape loaders handle this automatically. AUTOCLEAN=0 # Set to '1' or greater to enable autocleancount=99 havereader=0 #### If you have a barcode reader, set to 1. offlinestatus=0 #### Set to 0 if 'mt status' gives an #### "offline" when drive is offline. #### Set to 1 or greater if 'mt status' #### doesn't give and offline, rather an #### "ONLINE" when drive is online. #### Check the 'readyError' section if mt acts differently for you #### as stated below. #### See the 'readstatus' section below if using a different drive than 0. ###################################################################################### # No user-level customized required beyond this point. # Paths prefix=@prefix@ exec_prefix=@exec_prefix@ sbindir=@sbindir@ libexecdir=@libexecdir@ # try to hit all the possibilities here PATH=$sbindir:$libexecdir:/usr/bin:/bin:/usr/sbin:/sbin:/usr/ucb:/usr/local/bin export PATH email=`amgetconf$SUF mailto` mailer=@MAILER@ if [ -d "@AMANDA_DBGDIR@" ]; then DBGFILE=@AMANDA_DBGDIR@/changer.debug else DBGFILE=/dev/null fi USE_VERSION_SUFFIXES="@USE_VERSION_SUFFIXES@" if test "$USE_VERSION_SUFFIXES" = "yes"; then SUF="-@VERSION@" else SUF= fi myname=$0 tape=`amgetconf$SUF tapedev` TAPE=`amgetconf$SUF changerdev`; export TAPE # for mtx command if [ "$tape" = "/dev/null" -o "$TAPE" = "/dev/null" ]; then echo "Both tapedev and changerdev must be specified in config file"; exit 2; fi changerfile=`amgetconf$SUF changerfile` cleanfile=$changerfile-clean accessfile=$changerfile-access slotfile=$changerfile-slot labelfile=$changerfile-barcodes [ ! -f $cleanfile ] && echo 0 > $cleanfile [ ! -f $accessfile ] && echo 0 > $accessfile [ ! -f $slotfile ] && echo 0 > $slotfile [ ! -f $labelfile ] && echo 0 > $labelfile cleancount=`cat $cleanfile` accesscount=`cat $accessfile` # Routines start here #### If using a different drive than /dev/nst0 (or whatever your OS #### calls the 0'th drive) change the 'Data Transfer Element 0' (there #### are 6 below, and 1 in searchtape().) to 'Data Transfer Element #' #### where # = /dev/nst# (or whatever for your OS). readstatus() { if [ $havereader -eq 1 ]; then tmpslot=`$MTX status | grep "Data Transfer Element 0"` usedslot=`echo $tmpslot | sed -n 's/Data Transfer Element 0:Empty/-1/p;s/Data Transfer Element 0:Full (Storage Element \([1-9][0-9]*\) Loaded)\(.*\)/\1/p'` barcode=`echo $tmpslot | sed -n 's/Data Transfer Element 0:Empty/-1/p;s/Data Transfer Element 0:Full (Storage Element \(.\) Loaded):VolumeTag = \(.*\)/\2/p'` else usedslot=`$MTX status | sed -n 's/Data Transfer Element 0:Empty/-1/p;s/Data Transfer Element 0:Full (Storage Element \(.\) Loaded)/\1/p'` fi if [ "$usedslot" -eq "-1" ]; then echo '-1' > $slotfile fi echo "STATUS -> currently loaded slot = $usedslot" >> $DBGFILE } eject() { readstatus echo "EJECT -> ejecting tape from slot $usedslot" >> $DBGFILE if [ $usedslot -gt 0 ]; then if [ $OFFLINE_BEFORE_UNLOAD -gt 0 ]; then $MT $MTF $tape offline fi $MTX unload $usedslot 2>/dev/null echo "0 $tape" exit 0 else echo "0 Drive was not loaded" exit 1 fi } reset() { $myname -eject >/dev/null echo "RESET -> loading tape from 1st slot ($firstslot)" >> $DBGFILE result=`$MTX load $firstslot 2>&1` if [ $? -eq 0 ]; then echo "1 $tape" exit 0 else echo "1 $result" exit 1 fi } loadslot() { readstatus whichslot=$1 numeric=`echo $whichslot | tr -cd 0-9` echo "LOADSLOT -> load tape from slot $whichslot" >> $DBGFILE case $whichslot in current) if [ $usedslot -lt 0 ]; then loadslot=$firstslot else echo "$usedslot $tape" exit 0 fi ;; next|advance) if [ $usedslot -lt 0 ]; then loadslot=$firstslot else loadslot=`expr $usedslot + 1` if [ $loadslot -gt $lastslot ]; then loadslot=$firstslot fi fi ;; prev) loadslot=`expr $usedslot - 1` if [ $loadslot -lt $firstslot ]; then loadslot=$lastslot fi ;; first) loadslot=$firstslot ;; last) loadslot=$lastslot ;; $numeric) if [ $whichslot -gt $lastslot ] || [ $whichslot -lt $firstslot ]; then echo "0 Slot $whichslot is out of range ($firstslot - $lastslot)" exit 1 else loadslot=$whichslot fi ;; clean) loadslot=$cleanslot ;; *) echo "0 illegal request" exit 1 ;; esac # Is this already the current slot? if [ $loadslot = $usedslot ]; then echo "$usedslot $tape" exit 0 fi # Is this a cleaning request? if [ $loadslot = $cleanslot ]; then expr $cleancount + 1 > $cleanfile echo 0 > $accessfile else expr $accesscount + 1 > $accessfile if [ $AUTOCLEAN -gt 0 -a $accesscount -gt $autocleancount ]; then $myname -slot clean >/dev/null # Slot $cleanslot might contain an ordinary tape rather than a cleaning # tape. A cleaning tape *MIGHT* auto-eject; an ordinary tape does not. # We therefore have to read the status again to check what actually happened. readstatus fi fi # Unload any previous tape if [ $usedslot -ne "-1" ]; then echo " -> unload $usedslot" >> $DBGFILE if [ $OFFLINE_BEFORE_UNLOAD -gt 0 ]; then $MT $MTF $tape offline fi result=`$MTX unload $usedslot 2>&1` status=$? echo " -> status $status, result '$result'" >> $DBGFILE if [ $status -ne 0 ]; then echo "$loadslot $result" exit 2 fi fi # Load the tape, finally! echo " -> loading tape from slot $loadslot" >> $DBGFILE result=`$MTX load $loadslot 2>&1` status=$? echo " -> status $status, result '$result'" >> $DBGFILE # If there is an error, abort unless the slot is simply empty if [ $status -ne 0 ]; then empty=`echo $result | grep "is Empty"` if [ -z "$empty" ]; then echo "$loadslot $result" exit 2 else loadslot next fi else #### The origional test if the drive is offline. This depends on what #### 'mt -f <device> status returns different between being offline and #### online. Aparently some drives report an 'offline' when offline, and #### it goes away when online. #### ADIC doesn't report an 'offline', rather an 'ONLINE' when it's up. #### Don't assume the drive is ready until we get an ONLINE #### This is tested by the variable $offlinestatus from the beginning. if [ $offlinestatus -eq 0 ]; then readyError="offline" while [ -n "$readyError" ]; do readyStatus=`$MT $MTF $tape status 2>&1` readyError=`echo $readyStatus | grep "offline"` done else readyError="" while [ -z "$readyError" ]; do readyStatus=`$MT $MTF $tape status 2>&1` readyError=`echo $readyStatus | grep "ONLINE"` done fi #### Moved this outside of the above while statements. echo " -> readyStatus = $readyStatus" >> $DBGFILE # Now rewind and check echo " -> rewind $loadslot" >> $DBGFILE $MT $MTF $tape rewind echo "$loadslot" > $slotfile echo "$loadslot $tape" exit 0 fi } info() { readstatus echo "INFO -> current slot $usedslot, last slot $lastslot, can go backwards 1" >> $DBGFILE #### Checks if you have a barcode reader or not. If so, it passes the 4th item in the echo #### back to amtape signifying it can search based on barcodes. if [ $havereader -eq 1 ]; then if [ $usedslot -lt 0 ]; then #### added a variable to the end of the following 2 echos. #### This indicates to amtape that it can/cannot read barcodes. echo "0 $lastslot 1 1" else echo "$usedslot $lastslot 1 1" fi exit 0 else if [ $usedslot -lt 0 ]; then echo "0 $lastslot 1" else echo "$usedslot $lastslot 1" fi exit 0 fi } #### Adds the amlabel and the barcode to the barcode file specified above. #### If the database is messed up, it kills amtape (rather abruptly) and #### dumps a message into changer.debug on what to do, then sends an email #### of the changer.debug to the above set email addr. addlabel() { readstatus tapelabel=$1 labelfilesize=`ls -l $labelfile | awk '{print $5}'` case $tapelabel in $tapelabel) echo "LABEL -> Adding Barcode $barcode and amlabel $tapelabel for Slot $usedslot into $labelfile" >> $DBGFILE if [ $labelfilesize -eq 2 ]; then echo "$tapelabel $barcode" > $labelfile echo "0 $usedslot $tape" else included=`grep $tapelabel $labelfile | awk '{print $1}'` if [ -z $included ]; then echo "$tapelabel $barcode" >> $labelfile echo "0 $usedslot $tape" else oldbarcode=`grep $tapelabel $labelfile | awk '{print $2}'` if [ $oldbarcode -eq $barcode ]; then echo " -> Barcode $barcode $oldbarcode already synced for $tapelabel" >> $DBGFILE echo "0 $usedslot $tape" else echo " -> WARNING!!! Label database corrupted!!!" >> $DBGFILE echo " -> $tapelabel $oldbarcode conflicts with new barcode $barcode" >> $DBGFILE echo " -> Remove file $labelfile and run /usr/sbin/amtape <config> update" >> $DBGFILE `cat $DBGFILE | $mailer -s "Error with barcode reader on \`date\`" $email` `killall amtape` fi fi fi ;; esac exit 0 } #### Looks for the amlabel in the barcode file. If found, it locates the #### slot it's in by looking for the barcode in the mtx output. It then #### loads that tape, and returns to amtape the device the tape is loaded in. #### If the amlabel is not found, it kills amtape and dumps a message to #### changer.debug on what to do, then sends an email of the changer.debug #### to the above set email addr. searchtape() { # readstatus tapelabel=$1 includedtag=`grep $tapelabel $labelfile | awk '{print $1}'` includedbar=`grep $tapelabel $labelfile | awk '{print $2}'` tmpincludedslot=`$MTX status | grep $includedbar` #### The horrid sed statement below returns the slot number. #### The origional was in shell script, so I didn't want to change that, #### Which give the below puke for a number between 1-999. includedslot=`echo $tmpincludedslot | sed -n 's/\(.*\)Storage Element \([1-9][0-9]*\):\(.*\)/\2/p;s/Data Transfer Element 0:Full (Storage Element \(.\) Loaded)\(.*\)/\1/p'` case $tapelabel in $tapelabel) if [ $tapelabel == $includedtag ]; then shift loadslot $includedslot echo "$tape" else echo "SEARCH -> WARNING!!! $tapelabel not found in current ADIC-barcodes database." >> $DBGFILE echo " -> WARNING!!! Check your typing, and/or update the database." >> $DBGFILE `cat $DBGFILE | $mailer -s "Error with barcode reader on \`date\`" $email` `killall amtape` fi exit 0 esac } # Program invocation begins here echo "`date` Invoked with args '$@'" >> $DBGFILE while [ $# -ge 1 ];do case $1 in -slot) shift loadslot $* ;; -info) shift info ;; -reset) shift reset ;; -eject) shift eject ;; #### Added the below flags, for barcode support -label) shift addlabel $* ;; -search) shift searchtape $* ;; -clean) shift loadslot $cleanslot ;; *) echo "Unknown option $1" exit 2 ;; esac done