TenEM
TenEM

Reputation: 127

Script to backup and restore an Informix database

I made this script to backup and restore an Informix database. It's a menu with two functions that will give you two choices: to backup or restore a database.

The script will use dbexport then archive the backup to a directory.

To restore the database, I used dbimport.

#!/bin/sh
###################################################################################
#Usage  ./impexp.sh BASE USER ARCHIVE
###################################################################################
LOGO="DB IMPEXP"

#------------------------------------------------------
# Definition des variables
#------------------------------------------------------

BASE=$1
USER=$2
ARCHIVE=$3
export DBSTOR=/stored/bdd
export TEMPOF=/stored/tmp
ADATE=`date +%Y%m%d`
size_dbs=$(du "$BASE".exp |  sed -e 's/\t.*$//')
size_dbs2=$((size_dbs*4))


#------------------------------------------------------
# MENU PROMPTS
#------------------------------------------------------

ymenu="y.  backup BDD"              ;
zmenu="z.  restore archive "         ; 


#------------------------------------------------------
# MENU FUNCTION DEFINITIONS
#------------------------------------------------------
 
badchoice () { MSG="Invalid Selection ... Please Try Again" ; } 
 

ypick () {     echo "Backup BDD"
    #------------------------------------------------

    dbexport $BASE
    
    mkdir -m 0777 -p "$DBSTOR"
    
    tar -czvf $DBSTOR/$BASE.exp.$ADATE.tgz ./$BASE.exp && chmod 777 $DBSTOR/*

    rm -rf ./$BASE.exp
    rm -f  ./dbexport.out
 }
zpick () {     echo "Restoring archive"
    #---------------------------------------
    cd $DBPATH

    tar -xzvf $ARCHIVE
    
    onspaces -a dbs_"$BASE"_01 -p /bases_data/data_"$BASE"_01.dbs -o 0 -s ${size_dbs2}
    dbimport -q "$BASE" -d dbs_"$BASE"_01 
    echo "Import done"
  }

#------------------------------------------------------
# DISPLAY FUNCTION DEFINITION
#------------------------------------------------------

themenu () {
# clear the screen
clear
echo `date`
echo
echo "  " $LOGO
echo
echo " Please Select:"
echo
echo "   " $ymenu
echo "   " $zmenu
echo "   "
echo "   "
echo "     x. Exit"
echo
echo $MSG
echo
echo Select by pressing the letter and then ENTER ;
}
 
MSG=

while  true
do
  themenu

  read answer

  MSG=


  case $answer in
      y|Y) ypick;;
      z|Z) zpick;;


      x|X) break;;
 
        *) badchoice;;
 
  esac

  echo ""      
  echo "Press <ENTER> to return to the menu..."
  read junk
  clear
done

Sadly it doesn't work properly, especially the backup part where i have these error messages :

   create database
   225 - Cannot create file for system catalog (systables).
   131 - ISAM error: no free disk space
   ./impexp.sh: line 61: import_erreur: command not found

Thank you.

Upvotes: 1

Views: 1208

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 754450

After some discussion in comments and amendments to the question, the problem appears to be primarily in the 'recover' stage, and it may be that the trouble is with creating enough space in the dbspace.

I'm going to mention here that I find DB-Access distressing to use. So distressing that I wrote a program now called sqlcmd to work the way I wish DB-Access did. Consider using SQLCMD (available from the IIUG Software Archive), which I wrote to behave consistently in shell scripting contexts whereas DB-Access doesn't. It dates back to 1986 (before there was dbaccess; in those days, you used isql instead — DB-Access was carved out of isql in an evening) and was originally called rdsql. It bears no relation to Microsoft's johnny-come-lately program of the same name — except for the name and having the same general purpose (manipulate SQL databases).

I mention it because scripting for "is there already a dbspace called 'xyz'?" becomes trivial:

dbspace="xyz"
if [ -n "$(sqlcmd -d sysmaster "select name from sysdbspaces where name = '$dbspace'") ]
then : dbspace exists - add space to it
else : dbspace does not exist - create it
fi

With DB-Access, this is harder. What should work is something along the lines of:

dbspace="xyz"
result=$(dbaccess sysmaster - 2>/dev/null <<EOF
select name from sysdbspaces where name = '$dbspace';
EOF
)
if [ -n "$result" ]
then : dbspace exists - add space to it
else : dbspace does not exist - create it
fi

This code should be encapsulated into a shell function or a shell script called dbspace_exists that can be used by scripts. It should return 0 or exit with status 0 if the dbspace exists; it should return a non-zero value or exit with a non-zero status if the dbspace does not exist. (And it shouldn't generate any output by default!) I'd use a script because the performance impact is negligible and the clarity and reusability is much simpler. YMMV!

Chunk files must exist and have appropriate permissions before running onspaces. The following works if the user running the script is root or has system administrator privileges. Drop the chown line if necessary, but note that if the owner is not user informix, group informix, the new chunk path may not work at all.

cp /dev/null "$chunkpath"
chown informix:informix "$chunkpath"
chmod 660 "$chunkpath"

Your code keeps repeating some constructs — use variables so you stay DRY ("Don't Repeat Yourself").

You have something along the lines of:

cd $DBSTOR          # Changed from DBPATH

tar -xzvf $ARCHIVE

onspaces -c -d dbs_"$BASE"_01 -p /bases_data/data_"$BASE"_01.dbs -o 0 -s ${size_dbs2}
dbimport -q "$BASE" -d dbs_"$BASE"_01 
echo "Import done"

I think you need something more like:

cd "${DBSTOR}" || exit 1

tar -xzvf "${ARCHIVE}"

dbspace_name="dbs_${BASE}_01"
dbspace_path="/bases_data/${dbspace_name}.dbs"
if [ -f "$dbspace_path" ]
then
    echo "$0: dbspace chunk file $dbspace_path already exists" >&2
    exit 1
fi
cp /dev/null "$dbspace_path"
chown informix:informix "$dbspace_path"
chmod 660 "$dbspace_path"

if dbspace_exists "$dbspace_name"
then onspaces -a    "$dbspace_name" -p "$dbspace_path" -o 0 -s "${size_dbs2}"
else onspaces -c -d "$dbspace_name" -p "$dbspace_path" -o 0 -s "${size_dbs2}"
fi
if [ "$?" != 0 ]
then
    echo "$0: failed to create/expand dbspace $dbspace_name" >&2
    exit 1
fi
if dbimport -q "$BASE" -d "$dbspace_name"
then echo "Import of $BASE done"
else
    echo "Import of $BASE failed" >&2
    exit 1
fi

# Remove the files extracted from the tar file
rm -fr …

exit 0

You should do an archive before trying to use the new dbspace — I've not integrated that into the script. Without the archive, the extra chunk may not be available.

There is still a lot of polishing to do.

Note the use of the braces in dbspace_name="dbs_${BASE}_01". This ensures that the variable name is ${BASE} and not $BASE_01. Your circumvention is effective but clumsy and not idiomatic shell. I usually quote variables, and often embed the variable names in braces `"${dbspace_name}". If you don't have spaces or strings touching the variable name, you can do without the extra punctuation, but it helps in the long run.

Upvotes: 1

Related Questions