Skip to content
Snippets Groups Projects
Select Git revision
  • d4934a7c53112282104bed89b6095b76e43746a7
  • main default protected
2 results

Readme.md

Blame
  • couchdb.sh 7.17 KiB
    #!/bin/bash
    # ================================================================================
    #
    # LOCALDUMP :: COUCHDB
    # create gzipped plain text backups from each scheme
    #
    # --------------------------------------------------------------------------------
    # ah - Axel Hahn <axel.hahn@iml.unibe.ch>
    # ds - Daniel Schueler <daniel.schueler@iml.unibe.ch>
    #
    # 2017-03-24  ah,ds  v0.9  backup
    # 2017-03-27  .....  v1.0  restore
    # 2022-01-20         v1.1  fixes with shellcheck
    # 2022-03-17         v1.2  WIP: add lines with prefix __DB__
    # 2022-10-07  ah     v1.3  unescape regex with space to prevent "grep: warning: stray \ before white space"
    # ================================================================================
    
    if [ -z "$BACKUP_TARGETDIR" ]; then
      echo ERROR: you cannot start $(basename $0) directly
      rc=$rc+1
      exit 1
    fi
    
    # --------------------------------------------------------------------------------
    # CONFIG
    # --------------------------------------------------------------------------------
    
    dirPythonPackages=/usr/lib/python2.7/site-packages
    
    
    # --------------------------------------------------------------------------------
    # FUNCTIONS
    # --------------------------------------------------------------------------------
    
    # make an couch api request
    # param  string  method ... one of GET|POST|DELETE
    # param  string  relative url, i.e. _all_dbs or _stats
    function _couchapi(){
      method=$1
      apiurl=$2
      outfile=$3
    
      sParams=
      # sParams="$sParams -u ${couchdbuser}:${couchdbpw}"
      sParams="$sParams -X ${method}"
      sParams="$sParams ${COUCHDB_URL}${apiurl}"
      if [ ! -z "$outfile" ]; then
        sParams="$sParams -o ${outfile}"
      fi
      curl $sParams 2>/dev/null
    }
    
    function _couchGet(){
      _couchapi GET $*
    }
    
    function _getDblist(){
       _couchGet _all_dbs | sed 's#\"#\n#g' | grep -Ev "^(\[|\,|\])$"
    }
    
    
    # ---------- CONFIG/ INSTANCES
    
    # get valid configured instances
    function getInstances(){
     for mycfg in $(ls -1 "~/.iml_backup/couchdb/*.config" )
     do
       if . "$mycfg"; then
         echo $(basename "${mycfg}" | cut -f 1 -d ".")
       fi
     done
    }
    
    
    # load the config of an existing instance
    # see getInstances to get valid names
    # param  string  name of the instance to load
    function loadInstance(){
      COUCHDB_URL=
      if ! . "~/.iml_backup/couchdb/${1}.config" ; then
        color error
        echo ERROR: invalid instance: $1 - the config file cannot be sourced
        color reset
        exit 1
      fi
      if [ -z "${COUCHDB_URL}" ]; then
        color error
        echo "ERROR: invalid instance: $1 - the config file has no COUCHDB_URL"
        color reset
        exit 1
      fi
    
      # parse ${COUCHDB_URL} ...
      couchdbhost=$(echo "${COUCHDB_URL}" | cut -f 3 -d "/" | cut -f 2 -d "@" | cut -f 1 -d ":")
      couchdbport=$(echo "${COUCHDB_URL}" | cut -f 3 -d "/" | cut -f 2 -d "@" | cut -f 2 -d ":")
      couchdbuser=$(echo "${COUCHDB_URL}" | cut -f 3 -d "/" | cut -f 1 -d "@" | cut -f 1 -d ":")
      couchdbpw=$(  echo "${COUCHDB_URL}" | cut -f 3 -d "/" | cut -f 1 -d "@" | cut -f 2 -d ":")
    
    }
    
    
    # ---------- BACKUP
    
    # backup with loop over instances
    function doBackup(){
      # for mycfg in `ls -1 ~/.iml_backup/couchdb/*.config`
      for COUCHDB_INSTANCE in $(getInstances)
      do
        loadInstance "$COUCHDB_INSTANCE"
    
          echo "--- instance: $COUCHDB_INSTANCE"
          if curl --head -X GET "$COUCHDB_URL" 2>/dev/null | grep "^HTTP.* 200 "; then
    
            _doBackupOfSingleInstance
    
          else
            rc=$rc+1
            color error
            echo ERROR: couch DB instance is not available or canot be accessed with these credentials in config file
            # repeat curl to show the error message
            curl -X GET "$COUCHDB_URL"
            color reset
          fi
    
        echo
        echo "--- $(date) done."
        echo
      done
    }
    
    # make backup of all databases in a couchdb instance
    # global: COUCHDB_URL
    # global: COUCHDB_INSTANCE
    function _doBackupOfSingleInstance(){
    
      create_targetdir
      mkdir -p "${BACKUP_TARGETDIR}/${COUCHDB_INSTANCE}" 2>/dev/null
    
      echo
      echo "    DUMP databases of instance ${COUCHDB_INSTANCE}"
      echo "    couchdbhost $couchdbhost on port $couchdbport with user $couchdbuser"
      echo
    
      for dbname in $(_getDblist)
      do
        echo -n "__DB__${SERVICENAME} ${COUCHDB_INSTANCE} $_dbname backup "
        OUTFILE=${BACKUP_TARGETDIR}/${COUCHDB_INSTANCE}/$(get_outfile "${dbname}").couchdbdump
        python ${dirPythonPackages}/couchdb/tools/dump.py "${COUCHDB_URL}/${dbname}" >"${OUTFILE}"
    
        fetchrc
        db._compressDumpfile "${OUTFILE}"
    
        # $myrc is last returncode - set in fetchrc
        # if [ $myrc -eq 0 ]; then
        #   echo -n "gzip ... "
        #   compress_file "$OUTFILE"
        # else
        #   echo "ERROR occured - no gzip"
        # fi
        # ls -l "$OUTFILE"*
        # echo
      done
    
    }
    
    # ---------- RESTORE
    
    # restore a single backup file; the instance and db name will be detected from file
    # param  string  filename of db dump (full path or relative to BACKUP_TARGETDIR)
    function restoreByFile(){
      sMyfile=$1
      sMyDb=$2
      echo
      h2 "analyze dump $sMyfile"
    
      COUCHDB_INSTANCE=$(echo "$sMyfile" | sed "s#${BACKUP_TARGETDIR}##g" | sed "s#\./##g" | sed "s#^/##g" | cut -f 1 -d "/")
      echo "detected COUCHDB_INSTANCE   : [${COUCHDB_INSTANCE}]"
      if [ -z "$sMyDb" ]; then
        sMyDb=$(guessDB "$sMyfile")
        echo "detected db schema from file: [${sMyDb}]"
      else
        echo "db schema from param 2: [${sMyDb}]"
      fi
    
      echo
    
      loadInstance "$COUCHDB_INSTANCE"
    
      echo "connect $couchdbhost on port $couchdbport with user $couchdbuser"
      if ! curl --head -X GET "$COUCHDB_URL" 2>/dev/null | grep "^HTTP.* 200 " >/dev/null; then
        color error
        echo ERROR: couch DB instance is not available
        curl -X GET "$COUCHDB_URL"
        color reset
        exit 1
      fi
      color ok
      echo OK
      color reset
    
    
      echo
    
      # _getDblist | grep "^${sMyDb}$"
      # if [ $? -eq 0 ]; then
      #   echo DB exists ... need to drop it first
      # fi
    
      h2 "deleting database [$sMyDb] ..."
      color cmd
      _couchapi DELETE "$sMyDb"
      fetchrc
      color reset
    
      h2 "creating database [$sMyDb] ..."
      color cmd
      _couchapi PUT "$sMyDb"
      fetchrc
      color reset
    
      h2 import file ...
      color cmd
      zcat "${sMyfile}" | python ${dirPythonPackages}/couchdb/tools/load.py "$COUCHDB_URL/$sMyDb"
      fetchrc
      color reset
      echo
    
    }
    
    # --------------------------------------------------------------------------------
    # MAIN
    # --------------------------------------------------------------------------------
    
    
    # ----- check requirements
    
    # --- is a couchd here
    j_requireProcess "couchdb"   1
    
    # --- very specific :-/ ... check available config files
    ls -1 ~/.iml_backup/couchdb/* >/dev/null 2>&1
    rc=$rc+$?
    
    
    if [ $rc -eq 0 ]; then
      echo OK: couchdb was found on this system ... checking requirements for backup ...
    
      j_requireBinary  "curl"     1
    
      ls ${dirPythonPackages}/couchdb/tools/dump.py ${dirPythonPackages}/couchdb/tools/load.py >/dev/null && echo "OK: python couchdb tools were found"
      rc=$rc+$?
    
    
      if [ $rc -eq 0 ]; then
        echo
    
        if [ "$1" = "restore" ]; then
          echo
          shift 1
          restoreByFile $*
    
        else
          doBackup
        fi
    
      else
        color error
        echo ERROR: Couchdb is here but I am missing things for the backup :-/
        color reset
      fi
    
    else
      rc=0
      echo "__DB__$SERVICENAME SKIP: couchdb seems not to be here"
    fi
    
    
    echo "__DB__$SERVICENAME INFO: $0 $* [couchdb] final returncode rc=$rc"
    
    # --------------------------------------------------------------------------------