Advertisement
kinsham

maint-bacula.sh

Nov 29th, 2023 (edited)
634
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 10.27 KB | None | 0 0
  1. #!/bin/bash
  2. #forked from:
  3. # https://github.com/elonen/bareos-cleaner/blob/master/bareos-cleanup and
  4. # https://admin.shamot.cz/?p=309
  5. print_usage() {
  6.   echo "  -s"
  7.   echo "     status of all catalog volumes"
  8.   echo "  -c"
  9.   echo "     check configs"
  10.   echo "  -z"
  11.   echo "     list disk space used"
  12.   echo "  -p"
  13.   echo "     prune all volumes ";
  14.   echo "  -d"
  15.   echo "     check/repair catalog ";
  16.   echo "  -t"
  17.   echo "     update all volumes to \"actiononpurge=Truncate\"";
  18.   echo "  -n"
  19.   echo "     update all volumes to \"actiononpurge=None\"";
  20.   echo "  -Do"
  21.   echo "     delete obsolete volume files from disk and cloud storage"
  22.   echo "  -Dp"
  23.   echo "     delete all purged, recycle, error volumes from catalog"
  24.   echo "  -h"
  25.   echo "     print this screen";
  26.   echo ""
  27.   exit 0
  28. }
  29.  
  30. if [ $# -lt 1 ]; then
  31.   print_usage
  32.   exit 3
  33. fi
  34.  
  35. dbname="bacula"
  36. dbuser="bacula"
  37. dbpass="xxxxxx"
  38. cloud="backblaze:bacula01"
  39.  
  40. #local stores
  41. cache="/mnt/usb16tb/cache"
  42. nas="/mnt/nas-bacula"
  43. qnap="/mnt/nas-qnap"
  44.  
  45. #check which stores exist
  46. if [ ! -d ${cache} ]; then
  47.   cache=""
  48. fi
  49. if [ ! -d  ${nas} ]; then
  50.   nas=""
  51. fi
  52. if [ ! -d  ${qnap} ]; then
  53.   qnap=""
  54. fi
  55. stores="${nas} ${qnap} ${cache}"
  56.  
  57. status() {
  58. #list status of all catalog volumes
  59. for vol in $(echo "llist media" | bconsole | grep "volumename:" | awk '{print $2}')
  60. do
  61.   volname=$(echo "llist volume=${vol}" | bconsole | grep "volumename:" | xargs)
  62.   volstat=$(echo "llist volume=${vol}" | bconsole | grep "volstatus:" | xargs)
  63.   expires=$(echo "llist volume=${vol}" | bconsole | grep "expiresin:" | xargs | sed s/,//g)
  64.   echo "${volname}" "${volstat}" "${expires}"
  65. done
  66. }
  67.  
  68. configs() {
  69.   if [ -z $(bacula-dir -t) ]; then
  70.     echo "director config OK"
  71.   fi
  72.  
  73.   if [ -z $(bacula-fd -t) ]; then
  74.     echo "file daemon config OK"
  75.   fi
  76.  
  77.   if [ -z $(bacula-sd -t) ]; then
  78.     echo "storage daemon config OK"
  79.   fi
  80. }
  81.  
  82. update_volume() {
  83.   echo ""
  84.   echo "updating all volumes to \"actiononpurge=$1\"..."
  85.   echo ""
  86.   for storage in ${stores}; do
  87.     echo "Processing" ${storage}
  88.     BACULA_BATCH="$(mktemp)"
  89.     ls -1 ${storage} | while read vol; do
  90.       echo "update volume=${vol} ActionOnPurge=$1" >> ${BACULA_BATCH}
  91.     done
  92.     bconsole < ${BACULA_BATCH} | grep $1
  93.     rm "${BACULA_BATCH}"
  94.   done
  95. }
  96.  
  97. pool_size() {
  98.   for store in ${stores}; do
  99.     if [[ -d ${store} ]] && [[ -n $(ls -1 ${store}) ]]; then  #exists and has files
  100.       echo ${store}
  101.       for pool in $(ls -1 ${store} | cut -d - -f 1 | sort -u); do #filename is pool-sequ
  102.         echo ${pool} $'\t' $(sudo du -sch ${store}/${pool}* | grep total | cut -d $'\t' -f 1)
  103.       done
  104.       echo ${store} "Total" $(sudo du -sch ${store} | grep total)
  105.     fi
  106. done
  107.  
  108. #cloud
  109.   if [[ ${store} = "cloud" ]]; then
  110.     echo "Cloud Total" $(rclone size ${cloud} --human-readable)
  111.   fi
  112. }
  113.  
  114. checkdb() {
  115.   dbcheck /var/lib/bacula/ ${dbname} ${dbuser} ${dbpass}
  116. }
  117.  
  118. delete_obsolete_volumes() {
  119. #################################################################################################
  120. #list volumes that have no associated job and hence can be deleted from the catalog and disk/cloud
  121. #################################################################################################
  122. echo "############################################"
  123. echo "Deleting volumes that have no associated job"
  124. echo "############################################"
  125.   VOLUMES_TO_DELETE="$(mktemp)"
  126.   for vol in $(echo "list media" | bconsole | grep "^| \+[0-9].*" | awk '{print $4}'); do
  127.     echo -e "query 14\n${vol}\n" | bconsole | if grep --quiet "No results to list"; then
  128.       status=$(echo "list volume=${vol}" | bconsole | grep "^| \+[0-9].*" | awk '{print $6}')
  129.       echo ${vol} "has no job" "status="${status}  #volumes in catalog that have no associated job
  130. #      if [ ${status} != "Append" ]; then
  131.         echo ${vol} >> ${VOLUMES_TO_DELETE}  # do not delete Append status volumes
  132. #      fi
  133.     fi
  134.   done
  135.  
  136. # Check whether we have found some volumes to delete
  137.   numvols=$(wc -l ${VOLUMES_TO_DELETE} | awk '{print $1}')
  138.   if [ ${numvols} -gt 0 ]; then
  139.     echo "${numvols} volumes are ready to delete: "
  140.     cat "${VOLUMES_TO_DELETE}"
  141.     echo -n "Are you sure you want to delete these ${numvols} volumes ? \(yes|no\): "
  142.     read response
  143.     if [ ${response} = "yes" ]; then
  144.       cat ${VOLUMES_TO_DELETE} | while read vol; do
  145.         echo -e "delete yes volume=${vol}" | bconsole  # delete from catalog
  146.         volpath=$(find ${stores} -name ${vol}) # directories for cloud volumes
  147.         if [ -f ${volpath} ]; then
  148.           sudo -u bacula rm -rf ${volpath} # delete from disk also directories for cache
  149.           echo ${volpath} "deleted"
  150.         fi
  151.         rclone purge ${cloud}/${vol} # cloud
  152.       done
  153.       echo "DONE: following volumes were deleted: "
  154.       cat "${VOLUMES_TO_DELETE}"
  155.     else
  156.       echo "quitting"
  157.       exit 1
  158.     fi
  159.   else
  160.     echo "no volumes found to delete"
  161.   fi
  162.   rm "${VOLUMES_TO_DELETE}"
  163.  
  164. #now check for disk volumes that are not in the catalog
  165.   echo "####################################################"
  166.   echo "Deleting volumes on disk that are not in the catalog"
  167.   echo "####################################################"
  168.   VOLUMES_TO_DELETE="$(mktemp)"
  169. #cache
  170.   echo "cache"
  171.   if [[ -d ${cache} ]] && [[ -n $(ls -1 ${cache}) ]]; then  #exists and has files
  172.     for vol in $(basename -a $(sudo -u bacula find ${cache} -mindepth 1 -type d | sort)); do
  173.       echo "list volume=${vol}" | bconsole | if grep --quiet "No results to list"; then
  174.         echo $(sudo -u bacula du -s -b ${cache}/${vol})
  175.         sudo -u bacula rm -rf ${cache}/${vol}
  176.         echo "Deleted" "${cache}/${vol}"
  177.       fi
  178.     done
  179.   fi
  180. #cloud
  181.   echo "cloud"
  182.   if [[ ! -z $(rclone ls ${cloud}) ]]; then
  183.     for vol in $(basename -a $(rclone lsd ${cloud} | awk '{print $5}' | sort)); do
  184.       echo "list volume=${vol}" | bconsole | if grep --quiet "No results to list"; then
  185.         echo ${vol} $(rclone size ${cloud}/${vol}) #print volumes/size that do not exist in catalog
  186.         rclone purge ${cloud}/${vol} #delete on remote
  187.         echo "Deleted" ${vol} $(rclone size ${cloud}/${vol})
  188.       fi
  189.     done
  190.   fi
  191. #dns-325
  192.   echo "DNS-325"
  193.   if [[ -d ${nas} ]] && [[ -n $(ls -1 ${nas}) ]]; then  #exists and has files
  194.     for vol in $(basename -a $(sudo find ${nas} -mindepth 1 -type f | sort)); do
  195.       echo "list volume=${vol}" | bconsole | if grep --quiet "No results to list"; then
  196.         echo $(sudo -u bacula du -s -b ${nas}/${vol})
  197.         sudo -u bacula rm -f ${nas}/${vol}
  198.         echo "Deleted" "${nas}/${vol}"
  199.       fi
  200.     done
  201.   fi
  202. #QNAP
  203.   echo "QNAP"
  204.   if [[ -d ${qnqp} ]] && [[ -n $(ls -1 ${qnap}) ]]; then  #exists and has files
  205.     for vol in $(basename -a $(sudo find ${qnap} -mindepth 1 -type f | sort)); do
  206.       echo "list volume=${vol}" | bconsole | if grep --quiet "No results to list"; then
  207.         echo $(sudo -u bacula du -s -b ${qnap}/${vol})
  208.         sudo -u bacula rm -f ${qnap}/${vol}
  209.         echo "Deleted" "${qnap}/${vol}"
  210.       fi
  211.     done
  212.   fi
  213. }
  214.  
  215. prune_all() {
  216.   BACULA_BATCH="$(mktemp)"
  217.   echo ""
  218.   echo "pruning all volumes and let Bacula mark them as purged once the retention periods are expired..."
  219.   echo ""
  220.   for st in ${stores}; do
  221.     ls -1 ${st} | while read vol; do
  222.       echo "prune volume=${vol}" >> ${BACULA_BATCH}
  223.       echo "yes" >> ${BACULA_BATCH}
  224.     done
  225.     bconsole < ${BACULA_BATCH} | grep -i "marking it purged"
  226.   done
  227.   rm "${BACULA_BATCH}"
  228. }
  229.  
  230. delete_purged_volumes() {
  231. # delete purged, recycle or error volumes from catalog
  232.   echo "searching for all purged, recycle, read-only or error volumes to be deleted..."
  233.   echo "purged"
  234.   PURGED_VOLUMES=`echo "list volumes" | bconsole | grep "Purged" | awk '{print $4}'`
  235.   if [[ -n ${PURGED_VOLUMES} ]]; then
  236.     echo "${PURGED_VOLUMES}"
  237.     echo -n "Are you sure you want to delete these purged volumes from the catalog ? \(yes|no\): "
  238.     read -r response
  239.     if [[ ${response} = "yes" ]]; then
  240.       for vol in ${PURGED_VOLUMES}; do
  241.         echo "delete volume=${vol} yes" | bconsole
  242.       done
  243.     fi
  244.   else
  245.     echo "no purged volumes"
  246.   fi
  247.  
  248.   echo "recycled"
  249.   RECYCLE_VOLUMES=$(echo "list volumes" | bconsole | grep "Recycle" | awk '{print $4}')
  250.   if [[ -n ${RECYCLE_VOLUMES} ]]; then
  251.     echo "${RECYCLE_VOLUMES}"
  252.     echo -n "Are you sure you want to delete these recycled volumes from the catalog ? \(yes|no\): "
  253.     read -r response
  254.     if [[ ${response} = "yes" ]]; then
  255.       for vol in ${RECYCLE_VOLUMES}; do
  256.         echo "delete volume=${vol} yes" | bconsole
  257.       done
  258.     fi
  259.   else
  260.     echo "no recycle volumes"
  261.   fi
  262.  
  263.   echo "errored"
  264.   ERROR_VOLUMES=$(echo "list volumes" | bconsole | grep "Error" | awk '{print $4}')
  265.   if [[ -n ${ERROR_VOLUMES} ]]; then
  266.     echo "${ERROR_VOLUMES}"
  267.     echo -n "Are you sure you want to delete these errored volumes from the catalog ? \(yes|no\): "
  268.     read -r response
  269.     if [[ ${response} = "yes" ]]; then
  270.       for vol in ${ERROR_VOLUMES}; do
  271.         echo "delete volume=${vol} yes" | bconsole
  272.       done
  273.     fi
  274.   else
  275.     echo "no error volumes"
  276.   fi
  277.  
  278.   echo "read only"
  279.   READ_ONLY_VOLUMES=$(echo "list volumes" | bconsole | grep "Read-Only" | awk '{print $4}')
  280.   if [[ -n ${READ_ONLY_VOLUMES} ]]; then
  281.     echo "${READ_ONLY_VOLUMES}"
  282.     echo -n "Are you sure you want to delete these read-only volumes from the catalog ? \(yes|no\): "
  283.     read -r response
  284.     if [[ ${response} = "yes" ]]; then
  285.       for vol in ${READ_ONLY_VOLUMES}; do
  286.         echo "delete volume=${vol} yes" | bconsole
  287.       done
  288.     fi
  289.   else
  290.     echo "no read only volumes"
  291.   fi
  292. }
  293.  
  294. # Parse parameters
  295. while [ $# -gt 0 ]; do
  296.   case "$1" in
  297.   -h | --help)
  298.     print_usage
  299.     exit 0
  300.     ;;
  301.   -s)
  302.     shift
  303.     status
  304.     exit 0
  305.     ;;
  306.   -c)
  307.     shift
  308.     configs
  309.     exit 0
  310.     ;;
  311.   -z)
  312.     shift
  313.     pool_size
  314.     exit 0
  315.     ;;
  316.   -t)
  317.     shift
  318.     update_volume Truncate
  319.     exit 0
  320.     ;;
  321.   -d)
  322.     shift
  323.     checkdb
  324.     exit 0
  325.     ;;
  326.   -p)
  327.     shift
  328.     prune_all
  329.     exit 0
  330.     ;;
  331.   -n)
  332.     shift
  333.     update_volume None
  334.     exit 0
  335.     ;;
  336.   -Do)
  337.     shift
  338.     delete_obsolete_volumes
  339.     exit 0
  340.     ;;
  341.   -Dp)
  342.     shift
  343.     delete_purged_volumes
  344.     exit 0
  345.     ;;
  346.   *)  echo 'Unknown argument: ' $1
  347.       print_usage
  348.       exit 3
  349.       ;;
  350.   esac
  351. done
  352. exit 1
  353.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement