This page is for people to post sample configurations for particularly tricky or usefull setups. This can include unusual hardware setups, or complicated schedules, for example.
conf.d
directorymkdir /etc/bacula/conf.d
# vi /etc/bacula/conf.d/test.conf
Job { Name = "Test" Enabled = no Client = backup-fd FileSet = "FileSetTest" Schedule = "ScheduleTest" Write Bootstrap = "/var/bacula/Test.bsr" Full Backup Pool = FullTest Incremental Backup Pool = IncrTest Differential Backup Pool = DiffTest Storage = DAT72 Type = Backup Level = Incremental Pool = Default Priority = 10 Messages = Standard } FileSet { Name = "FileSetTest" Include { Options { signature = MD5 } File = /home } Exclude { File = /proc File = /tmp File = /.journal File = /.fsck } } Schedule { Name = "ScheduleTest" Run = Full 1st sun at 23:05 Run = Differential 2nd-5th sun at 23:05 Run = Incremental mon-sat at 23:05 } Pool { Name = FullTest Label Format = "FullTest" Pool Type = Backup Recycle = yes # Bacula can automatically recycle Volumes AutoPrune = yes # Prune expired volumes Volume Retention = 6 months Maximum Volume Jobs = 1 } Pool { Name = DiffTest Label Format = "DiffTest" Pool Type = Backup Recycle = yes AutoPrune = yes Volume Retention = 40 days Maximum Volume Jobs = 1 } Pool { Name = IncrTest Label Format = "IncrTest" Pool Type = Backup Recycle = yes AutoPrune = yes Volume Retention = 10 days Maximum Volume Jobs = 1 }
# vi /etc/bacula/bacula-dir.conf
[snip] ... AutoPrune = yes # Prune expired volumes Volume Retention = 365 days # one year MaximumVolumeBytes = 4700000000 } # # Restricted console used by tray-monitor to get the status of the director # Console { Name = backup-mon Password = "7f+4TYcZiZuSuPcAJQODTta55CL8lBPrj9MuYdyx6Y3u" CommandACL = status, .status } # Include below all yours jobs configuration files (remember add '@' at beginning) @/etc/bacula/conf.d/test.conf
# vi /etc/bacula/conf.d/schedule.conf
Run = Full on 1 at 23:05 Run = Differential thu at 23:05 Run = Incremental mon-fri at 3:05
# vi /etc/bacula/conf.d/test.conf
[snip] File = /.journal File = /.fsck } } Schedule { Name = "ScheduleTest" @/etc/bacula/conf.d/schedule.conf } Pool { Name = FullTest ...
To maintain Bacula Director configuration file as clean as possible and more readable, is a good idea put Pools, Clients and Storages Resources declarations in different files.
For example:
# vi /etc/bacula/conf.d/pools.conf
Pool { Name = AllIncrementals Label Format = "Incr" Pool Type = Backup Recycle = yes # Bacula can automatically recycle Volumes AutoPrune = yes # Prune expired volumes Storage = DDS-4 Volume Retention = 2 months } Pool { Name = AllDifferentials Label Format = "Diff" Pool Type = Backup Recycle = yes # Bacula can automatically recycle Volumes AutoPrune = yes # Prune expired volumes Storage = DAT72 Volume Retention = 2 months }
AllInrementals pool is used to backup all Incrementals jobs in the same tape. Same idea with AllDifferentials pool.
Note: than don't exist “Maximum Volume Jobs” statement
# vi /etc/bacula/bacula-dir.conf
[snip] ... Password = "7f+4TYcZiZuSuPcAJQODTta55CL8lBPrj9MuYdyx6Y3u" CommandACL = status, .status } # Include below all yours jobs configuration files (remember add '@' at beginning) @/etc/bacula/conf.d/test.conf # Pools definition files @/etc/bacula/conf.d/pools.conf
A job file example than use those pools could be:
# vi /etc/bacula/conf.d/test.conf
Job { Name = "Test" Enabled = no Client = backup-fd FileSet = "FileSetTest" Schedule = "ScheduleTest" Write Bootstrap = "/var/bacula/Test.bsr" Full Backup Pool = FullTest Incremental Backup Pool = AllIncrementals Differential Backup Pool = AllDifferentials Storage = DAT72 Type = Backup ...
An Bacula Director configuration example could be:
# vi /etc/bacula/bacula-dir.conf
[snip] ... AutoPrune = yes # Prune expired volumes Volume Retention = 365 days # one year MaximumVolumeBytes = 4700000000 } # # Restricted console used by tray-monitor to get the status of the director # Console { Name = backup-mon Password = "7f+4TYcZiZuSuPcAJQODTta55CL8lBPrj9MuYdyx6Y3u" CommandACL = status, .status } # Include below all yours jobs configuration files (remember add '@' at beginning) @/etc/bacula/conf.d/test.conf @/etc/bacula/conf.d/mails.conf @/etc/bacula/conf.d/server2.conf @/etc/bacula/conf.d/monitor.conf @/etc/bacula/conf.d/debian.conf # Clients definition files @/etc/bacula/conf.d/clients.conf # Storages definition file @/etc/bacula/conf.d/storages.conf # Pools definition files @/etc/bacula/conf.d/pools.conf
Since Bacula 2.2.0 you can include the output of a command within a configuration file with the “@|” syntax. Here's how you can use “@|” to include all files within some directory without explicitly naming the files (this lets you, say, add new clients to a configuration without changing existing configuration files, just by adding a file for the new client, containing its Job, Client, and FileSet resources, to the included directory):
# # Include subfiles associated with configuration of clients. # They define the bulk of the Clients, Jobs, and FileSets. # Remember to "reload" the Director after adding a client file. # @|"find /etc/bacula/clientdefs -name '*.conf' -type f -exec echo @{} \;"
After reading Total Automation of Bacula Tape Handling tip in the Bacula manual, I eventually managed to get it to work with the latest version of Bacula with a lot of script hacking.
Here's what I came up with…
Storage { Name = LTO-2 Address = storage.host.name SDPort = 9103 Password = "storage_password" Device = LTO-2 Media Type = LTO-2 Autochanger = yes Maximum Concurrent Jobs = 5 }
Autochanger { Name = LTO-2 Device = LTO-2-Drive Changer Device = /dev/nst0 Changer Command = "/usr/local/bin/bacula-changer.sh %o %a %S" } Device { Name = LTO-2-Drive Drive Index = 0 Autochanger = yes Archive Device = /dev/nst0 Maximum Changer Wait = 3d AutomaticMount = yes AlwaysOpen = yes Media Type = LTO-2 RemovableMedia = yes Offline On Unmount = no Spool Directory = /home/bacula/spool }
#!/bin/sh # # Bacula interface to mtx autoloader # # Created OCT/31/03 by Alexander Kuehn, derived from Ludwig Jaffe's script # # *Heavily* hacked between 31/10/07 & 02/11/07 by Sean Cardus to make it work # with the current Bacula version & our LTO tape drive. This works for me, # it might work for you too - But, don't blame me if it blows up :) # # John Murray added storagename feature on 6th Nov 2007 to cater for situation # where more than one Storage resource exists - we need to supply the correct # qualifier after 'status Storage' # # * Check that the bacula-sd process has permission to run this script, # run bconsole and to write to the logfile specified below! * # #set -x # these are the labels of the tapes in each virtual slot, not the slots! labels="DC01 DC02 DC03 DC04 DC05 DC06 DC07 DC08 DC09 DC10" # If more than one Storage resource exists, specify which to check status # of (name is case-sensitive) # e.g. # storagename="Tape" storagename="" # who to send a mail to? recipient=operator@my.domain.name logfile=/var/log/mtx.log # Delay in seconds how often to check whether a new tape has been inserted TAPEDELAY=10 # the default is every 10 seconds echo `date` ":" $@ >>$logfile # change this if mt is not in the path (use different quotes!) mt=`which mt` grep=`which grep` # # how to run the console application? console="/usr/sbin/bconsole -c /etc/bacula/bconsole.conf" command="$1" #TAPEDRIVE0 holds the device/name of your 1st and only drive (Bacula supports only 1 drive currently) #Read TAPEDRIVE from command line parameters if [ -z "$2" ] ; then TAPEDRIVE0=/dev/nst0 else TAPEDRIVE0=$2 fi #Read slot from command line parameters if [ -z "$3" ] ; then slot=`expr 1` else slot=`expr $3` fi if [ -z "$command" ] ; then echo "" echo "The mtx-changer script for Bacula" echo "---------------------------------" echo "" echo "usage: mtx-changer <command> <devicename of tapedrive> [slot]" echo " mtx-changer" echo "" echo "Valid commands:" echo "" echo "unload Unloads a tape into the slot" echo " from where it was loaded." echo "load <slot> Loads a tape from the slot <slot>" echo "list Lists full storage slots" echo "loaded Gives slot from where the tape was loaded." echo " 0 means the tape drive is empty." echo "slots Gives Number of avialable slots." echo "volumes List avialable slots and the label of the." echo " tape in it (slot:volume)" echo "Example:" echo " mtx-changer load /dev/nst0 1 loads a tape from slot1" echo " mtx-changer %a %o %S " echo "" exit 0 fi case "$command" in unload) echo "mtx-changer: Unload request on $TAPEDRIVE0" >>$logfile DRIVESTATUS=`$mt -f $TAPEDRIVE0 status | grep ONLINE` echo "DriveStatus: $DRIVESTATUS" >>$logfile if [ -z $DRIVESTATUS ] ; then echo "Drive is OFFLINE" >>$logfile else echo "Drive is ONLINE" >>$logfile echo "Taking drive offline and ejecting..." >>$logfile mt -f $TAPEDRIVE0 rewoffl 2>/dev/null fi exit 0 ;; load) echo "mtx-changer: load request on $TAPEDRIVE0" >>$logfile #Let's check if drive is loaded before we load it MOUNTED=`echo "status Storage=$storagename" | $console | $grep $TAPEDRIVE0 | $grep "is mounted with"` if [ -z "$MOUNTED" ] ; then echo "Drive is UNMOUNTED: $MOUNTED" >>$logfile else echo "Drive is MOUNTED: $MOUNTED" >>$logfile VOLUME=`echo "status Storage=$storagename" | $console | $grep -A2 $TAPEDRIVE0 | $grep "Volume:" | awk {'print $2'}` echo "Mounted Volume: $VOLUME" >>$logfile if [ $MOUNTED = $3 ] ; then echo "$3 is already mounted in $TAPEDRIVE0 as $VOLUME" >>$logfile exit else echo "$VOLUME is currently mounted in $TAPEDRIVE0, unmounting..." >>$logfile echo "unmount" | $console >/dev/null 2>/dev/null fi fi echo "Taking drive offline and ejecting..." >>$logfile mt -f $TAPEDRIVE0 rewoffl 2>/dev/null # extract label for the mail count=`expr 1` for label in $labels ; do if [ $slot -eq $count ] ; then volume=$label ; fi count=`expr $count + 1` done mail -s "Bacula needs volume $volume." $recipient <<END_OF_DATA Please insert tape labelled $volume from slot $slot into $TAPEDRIVE0. Kind regards, Bacula. END_OF_DATA sleep $TAPEDELAY # Wait for the tape to be inserted STATUS=`$mt -f $TAPEDRIVE0 status | $grep ONLINE` while [ -z "$STATUS" ] ; do sleep $TAPEDELAY STATUS=`$mt -f $TAPEDRIVE0 status | $grep ONLINE` done mail -s "Bacula says thank you." $recipient <<END_OF_DATA Thank you for inserting the new tape! (I requested volume $volume from slot $slot.) Kind regards, Bacula. END_OF_DATA echo "Successfully loaded a tape into drive $TAPEDRIVE0 (requested $volume from slot $slot)." >>$logfile echo "Loading finished." ; >>$logfile echo "$slot" exit 0 ;; list) echo "mtx-changer: Requested list" >>$logfile count=`expr 1` for label in $labels ; do echo $count:$label count=`expr $count + 1` done printf "\n" ;; loaded) echo "mtx-changer: tape loaded request on $TAPEDRIVE0" >>$logfile DRIVESTATUS=`mt -f $TAPEDRIVE0 status 2>/dev/null` MTRTN=$? if [ $MTRTN = "0" ] ; then echo "MT ran ok. Return Code: $MTRTN" >>$logfile DRIVESTATUS=`mt -f $TAPEDRIVE0 status | grep "DR_OPEN"` if [ -z "$DRIVESTATUS"] ; then echo "MT says the drive has a tape" >>$logfile echo "0" else echo "MT says the drive is empty" >>$logfile echo "0" fi else echo "MT error, bacula might be using it! Return code: $MTRTN" >>$logfile MOUNTED=`echo "status Storage=$storagename" | $console | $grep $TAPEDRIVE0 | $grep "is mounted with"` if [ -z "$MOUNTED" ] ; then echo "Drive is UNMOUNTED: $MOUNTED">>$logfile echo "0" else echo "Drive is MOUNTED: $MOUNTED">>$logfile VOLUME=`echo "status Storage=$storagename" | $console | $grep -A2 $TAPEDRIVE0 | $grep "Volume:" | awk {'print $2'}` echo "Mounted Volume: $VOLUME" >>$logfile count=`expr 1` for label in $labels ; do if [ $VOLUME = $label ] ; then echo "$VOLUME = $label in slot $count" >>$logfile echo "$count" fi count=`expr $count + 1` done fi fi exit 0 ;; slots) echo "mtx-changer: Request slots" >>$logfile count=`expr 0` for label in $labels ; do count=`expr $count + 1` done echo $count ;; volumes) echo "mtx-changer: Request volumes" >>$logfile count=`expr 1` for label in $labels ; do printf "$count:$label" count=`expr $count + 1` done printf "\n" ;; esac
Autochanger { Name = Autochanger1 Device = Drive-1 Changer Command = "/etc/bacula/mtx-changer %c %o %S %a %d" Changer Device = /dev/sg0 } Autochanger { Name = Autochanger2 Device = Drive-2 Changer Command = "/etc/bacula/mtx-changer %c %o %S %a %d" Changer Device = /dev/sg1 } Device { Name = Drive-1 # Drive Index = 0 Media Type = LTO-2 Archive Device = /dev/st0 Changer Device = /dev/sg0 AutomaticMount = yes; # when device opened, read it AlwaysOpen = yes; RemovableMedia = yes; RandomAccess = no; AutoChanger = yes Label Media = no # Enable the Alert command only if you have the mtx package loaded Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'" } Device { Name = Drive-2 # Drive Index = 0 Media Type = LTO-2 Archive Device = /dev/st1 Changer Device = /dev/sg1 AutomaticMount = yes; # when device opened, read it AlwaysOpen = yes; RemovableMedia = yes; RandomAccess = no; AutoChanger = yes Label Media = no # Enable the Alert command only if you have the mtx package loaded Alert Command = "sh -c 'tapeinfo -f %c |grep TapeAlert|cat'" }
Autochanger and device resources for an ML6000 with two LTO-3 drives (includes some commented-out default values):
Autochanger { Name = "ML6000 Library" Device = ML6000-LTO3-0, ML6000-LTO3-1 Changer Device = /dev/sg3 Changer Command = "/usr/local/bacula/sbin/mtx-changer %c %o %S %a %d" # %c = changer device # %o = command (unload|load|loaded|list|slots) # %S = slot index (1-based) # %a = archive device (i.e., /dev/sd* name for tape drive) # %d = drive index (0-based) } Device { # The ML6000's first tape drive Name = ML6000-LTO3-0 Archive Device = /dev/nst1 Device Type = Tape Media Type = LTO3 # If we were likely to ever have # multiple storage daemons # with LTO3 drives, we might # need to use media types like # "ML6000-LTO3" to distinguish # which library contained # which volumes. But we're not. Autochanger = Yes # Changer Device = <inherited from Changer> Alert Command = "sh -c '/usr/local/bacula/sbin/tapeinfo -f /dev/sg1 | /bin/sed -n /TapeAlert/p'" # We use /dev/sg1 instead of # %c because we want the tape # drive's status, not the # changer's. We use sed # instead of grep to avoid # logging non-zero exit # status reports from # grep when no strings # match its pattern. Drive Index = 0 # Autoselect = yes # Since our backup host lacks # the I/O bandwidth for it to # worthwhile to write to two # drives simultaneously, it # might be worthwhile # manipulating this to either # reserve a drive for # restores, or to spread the # wear across the two drives. # Maximum Changer Wait = 300 seconds # Maximum Rewind Wait = 300 seconds # Maximum Open Wait = 300 seconds # Always Open = Yes # Volume Poll Interval = 0 # 0 means "don't poll". RemovableMedia = yes Random Access = no # Maximum block size = 64512 # Some sources suggest 128K or # 256K for better LTO3 throughput # Hardware End of Medium = Yes # Fast Forward Space File = Yes # Use MTIOCGET = Yes # BSF at EOM = No # Two EOM = No # Backward Space Record = Yes # Backward Space File = Yes # Forward Space Record = Yes # Forward Space File = Yes # Offline On Unmount = No # Maximum File Size = 1gb # Block Positioning = yes # Maximum Network Buffer Size = 32768 # The manual suggests it may be # worthwhile doubling this. Maximum Spool Size = 100gb Maximum Job Spool Size = 60gb Spool Directory = /backup/spool # Label media = No # Automatic mount = Yes } Device { # The ML6000's second tape drive Name = ML6000-LTO3-1 Archive Device = /dev/nst2 Device Type = Tape Media Type = LTO3 Autochanger = Yes # Changer Device = <inherited from Changer> Alert Command = "sh -c '/usr/local/bacula/sbin/tapeinfo -f /dev/sg2 | /bin/sed -n /TapeAlert/p" Drive Index = 1 RemovableMedia = yes Random Access = no Maximum Spool Size = 80gb Maximum Job Spool Size = 40gb Spool Directory = /backup/spool }
Inserted a new parameter in config file.
# If you vant Import/Export slots to show up in Bacula
io_slots_visible=1
# Bacula version 5.0.3 # # This file is sourced by the mtx-changer script every time it runs. # You can put your site customization here, and when you do an # upgrade, the process should not modify this file. Thus you # preserve your mtx-changer configuration. # # Set to 1 if you want to do offline before unload offline=0 # Set to amount of time in seconds to wait after an offline offline_sleep=0 # Set to amount of time in seconds to wait after a load load_sleep=0 # Set to 1 to do an inventory before a status. Not normally needed. inventory=0 # If you have a VXA PacketLoader, it might display a different # Storage Element line, so try setting the following to 1 vxa_packetloader=0 # If you vant Import/Export slots to show up in Bacula io_slots_visible=1 # Set to 1 if you want debug info written to a log debug_log=0 # mt status output # SunOS No Additional Sense # FreeBSD Current Driver State: at rest. # Linux ONLINE # Note Debian has a different mt than the standard Linux version. # When no tape is in the drive it waits 2 minutes. # When a tape is in the drive, it prints user unfriendly output. # Note, with Ubuntu Gusty (8.04), there are two versions of mt, # so we attempt to figure out which one. # OS=`uname` case ${OS} in SunOS) ready="No Additional Sense" ;; FreeBSD) ready="Current Driver State: at rest." ;; Linux) ready="ONLINE" if test -f /etc/debian_version ; then mt --version|grep "mt-st" >/dev/null 2>&1 if test $? -eq 1 ; then ready="drive status" fi fi ;; esac
#!/bin/sh # # Bacula interface to mtx autoloader # Bacula version 5.0.3 # # If you set in your Device resource # # Changer Command = "path-to-this-script/mtx-changer %c %o %S %a %d" # you will have the following input to this script: # # So Bacula will always call with all the following arguments, even though # in come cases, not all are used. # # mtx-changer "changer-device" "command" "slot" "archive-device" "drive-index" # $1 $2 $3 $4 $5 # # for example: # # mtx-changer /dev/sg0 load 1 /dev/nst0 0 (on a Linux system) # # will request to load the first cartidge into drive 0, where # the SCSI control channel is /dev/sg0, and the read/write device # is /dev/nst0. # # The commands are: # Command Function # unload unload a given slot # load load a given slot # loaded which slot is loaded? # list list Volume names (requires barcode reader) # slots how many slots total? # listall list all info # transfer # # Slots are numbered from 1 ... # Drives are numbered from 0 ... # # # If you need to an offline, refer to the drive as $4 # e.g. mt -f $4 offline # # Many changers need an offline after the unload. Also many # changers need a sleep 60 after the mtx load. # # N.B. If you change the script, take care to return either # the mtx exit code or a 0. If the script exits with a non-zero # exit code, Bacula will assume the request failed. # # source our conf file if test ! -f /etc/bacula/mtx-changer.conf ; then echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" echo "ERROR: /etc/bacula/mtx-changer.conf file not found!!!!" echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" exit 1 fi . /etc/bacula/mtx-changer.conf MTX=/opt/csw/sbin/mtx if test ${debug_log} -ne 0 ; then touch /var/bacula/working/mtx.log fi dbgfile="/var/bacula/working/mtx.log" debug() { if test -f $dbgfile; then echo "`date +\"%Y%m%d-%H:%M:%S\"` $*" >> $dbgfile fi } # # Create a temporary file # make_temp_file() { TMPFILE=`mktemp /var/bacula/working/mtx.XXXXXXXXXX` if test x${TMPFILE} = x; then TMPFILE="/var/bacula/working/mtx.$$" if test -f ${TMPFILE}; then echo "ERROR: Temp file security problem on: ${TMPFILE}" exit 1 fi fi } # # The purpose of this function to wait a maximum # time for the drive. It will # return as soon as the drive is ready, or after # waiting a maximum of 300 seconds. # Note, this is very system dependent, so if you are # not running on Linux, you will probably need to # re-write it, or at least change the grep target. # We've attempted to get the appropriate OS grep targets # in the code at the top of this script. # wait_for_drive() { i=0 while [ $i -le 300 ]; do # Wait max 300 seconds if mt -f $1 status 2>&1 | grep "${ready}" >/dev/null 2>&1; then break fi debug "Device $1 - not ready, retrying..." sleep 1 i=`expr $i + 1` done } # check parameter count on commandline # check_parm_count() { pCount=$1 pCountNeed=$2 if test $pCount -lt $pCountNeed; then echo "ERROR: usage: mtx-changer ctl-device command [slot archive-device drive-index]" echo " Insufficient number of arguments given." if test $pCount -lt 2; then echo " Mimimum usage is first two arguments ..." else echo " Command expected $pCountNeed arguments" fi exit 1 fi } # Check for special cases where only 2 arguments are needed, # all others are a minimum of 5 # case $2 in list|listall) check_parm_count $# 2 ;; slots) check_parm_count $# 2 ;; transfer) check_parm_count $# 4 ;; *) check_parm_count $# 5 ;; esac # Setup arguments ctl=$1 cmd="$2" slot=$3 device=$4 drive=$5 debug "Parms: $ctl $cmd $slot $device $drive" case $cmd in unload) debug "Doing mtx -f $ctl unload $slot $drive" if test ${offline} -eq 1 ; then mt -f $device offline fi if test ${offline_sleep} -ne 0 ; then sleep ${offline_sleep} fi ${MTX} -f $ctl unload $slot $drive ;; load) debug "Doing mtx -f $ctl load $slot $drive" ${MTX} -f $ctl load $slot $drive rtn=$? if test ${load_sleep} -ne 0 ; then sleep ${load_sleep} fi wait_for_drive $device exit $rtn ;; list) debug "Doing mtx -f $ctl -- to list volumes" make_temp_file if test ${inventory} -ne 0 ; then ${MTX} -f $ctl inventory fi ${MTX} -f $ctl status >${TMPFILE} rtn=$? if test ${vxa_packetloader} -ne 0 ; then cat ${TMPFILE} | grep " *Storage Element [0-9]*:.*Full" | sed "s/ Storage Element //" | sed "s/Full :VolumeTag=//" else if test ${io_slots_visible} -ne 0 ; then cat ${TMPFILE} | grep " Storage Element [0-9]*.*:Full.*" | sed "s/ *IMPORT\/EXPORT//" | awk "{print \$3 \$4}" | sed "s/Full.*:VolumeTag=//" else cat ${TMPFILE} | grep " *Storage Element [0-9]*:.*Full" | awk "{print \$3 \$4}" | sed "s/Full.*:VolumeTag=//" fi fi cat ${TMPFILE} | grep "^Data Transfer Element [0-9]*:Full (Storage Element [0-9]" | awk '{printf "%s:%s\n",$7,$10}' rm -f ${TMPFILE} >/dev/null 2>&1 exit $rtn ;; listall) # Drive content: D:Drive num:F:Slot loaded:Volume Name # D:0:F:2:vol2 or D:Drive num:E # D:1:F:42:vol42 # D:3:E # # Slot content: # S:1:F:vol1 S:Slot num:F:Volume Name # S:2:E or S:Slot num:E # S:3:F:vol4 # # Import/Export tray slots: # I:10:F:vol10 I:Slot num:F:Volume Name # I:11:E or I:Slot num:E # I:12:F:vol40 debug "Doing mtx -f $ctl -- to list all" make_temp_file if test ${inventory} -ne 0 ; then ${MTX} -f $ctl inventory fi ${MTX} -f $ctl status >${TMPFILE} rtn=$? # can be converted to awk+sed+cut, see below # perl -ne ' #/Data Transfer Element (\d+):Empty/ && print "D:$1:E\n"; #/Data Transfer Element (\d+):Full \(Storage Element (\d+) Loaded\)(:VolumeTag =\s*(.+))?/ && print "D:$1:F:$2:$4\n"; #/Storage Element (\d+):Empty/ && print "S:$1:E\n"; #/Storage Element (\d+):Full( :VolumeTag=(.+))?/ && print "S:$1:F:$3\n"; #/Storage Element (\d+) IMPORT.EXPORT:Empty/ && print "I:$1:E\n"; #/Storage Element (\d+) IMPORT.EXPORT:Full( :VolumeTag=(.+))?/ && print "I:$1:F:$3\n";' ${TMPFILE} # If perl isn't installed, you can use by those commands cat ${TMPFILE} | grep "Data Transfer Element" | awk "{print \"D:\"\$4 \$7 \$9 \$10}" | sed "s/=/:/" | sed "s/Full/F:/" | sed "s/Empty/E/" cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep -v "IMPORT/EXPORT" | awk "{print \"S:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" cat ${TMPFILE} | grep -v "Data Transfer Element" | grep "Storage Element" | grep "IMPORT/EXPORT" | awk "{print \"I:\"\$3 \$4 \$5}" | sed "s/IMPORT\/EXPORT//" | sed "s/Full *:VolumeTag=/F:/" | sed "s/Empty/E/" rm -f ${TMPFILE} >/dev/null 2>&1 exit $rtn ;; transfer) slotdest=$device debug "Doing transfer from $slot to $slotdest" ${MTX} -f $ctl transfer $slot $slotdest rtn=$? exit $rtn ;; loaded) debug "Doing mtx -f $ctl $drive -- to find what is loaded" make_temp_file ${MTX} -f $ctl status >${TMPFILE} rtn=$? cat ${TMPFILE} | grep "^Data Transfer Element $drive:Full" | awk "{print \$7}" cat ${TMPFILE} | grep "^Data Transfer Element $drive:Empty" | awk "{print 0}" rm -f ${TMPFILE} >/dev/null 2>&1 exit $rtn ;; slots) debug "Doing mtx -f $ctl -- to get count of slots" ${MTX} -f $ctl status | grep " *Storage Changer" | awk "{print \$5}" ;; esac