Introduction.
Pour sauvegarder les bases de données Informix d’un serveur fonctionnant sous Linux, récupérer la structure des tables et les données, j’ai pu être confronté à l’élaboration d’un script assez complexe mais efficace.
Outre la simple sauvegarde texte, ce script génère un fichier de commande par table permettant de re-créer une table avec les bonnes tailles d’Extent.Le déchargement en fichier texte est trié sur l’ordre du premier index trouvé pour cette table.
Ce script utilise la base sysmaster pour retrouver certaines informations. Ce script execute sa sauvegarde pour toutes les instances locales définies dans le fichier $INFORMIXDIR/etc/sqlhosts, et retrouve les bases de chacune de ces instances.
Il est fait mention dans ce script d’un fichier portant l’extension .var plaçé dans /home/shared/scripts/connexion et nommé du nom de l’instance. C’est une habitude que j’ai de placer dans ce fichier les variables d’environnement nécessaires à Informix, mais même sans ce fichier, ce script devrait pouvoir fonctionner.
Script
#!/bin/sh
###############################################################################
# Programme : backup_informix.sh
# Application : Sauvegardes
# Date de creation : 25/04/2005
# Auteur : Marc-Henri PAMISEUX
#
# Copyright (c) 2005 Marc-Henri PAMISEUX
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# -----------------------------------------------------------------------------
# ! Date Modif. ! fonction ! description ! auteur !
# -----------------------------------------------------------------------------
# ! ! ! ! !
# ! ! ! ! !
###############################################################################
###############################################################################
# FONCTION Genere_IfxScript
# LIBELLE Fonction génératrice de script SQL
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE INSTANCE,DATABASE,TABLE
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de génerer les scripts de rechargement
# des tables pour une base et une instance Informix donnée
###############################################################################
Genere_IfxScript()
{
if [ $# -gt 2 ]
then
export INSTANCE=$1
export DATABASE=$2
export TABLE=$3
fi
pagesUsed=`"${INFORMIXDIR}"/bin/oncheck -pT "${DATABASE}":"${TABLE}" | head -n 30 | grep 'Number of pages used' | sed -r 's,[[:alpha:][:blank:][:cntrl:][:punct:]],,g'`
${INFORMIXDIR}/bin/oncheck -pT "${DATABASE}":"${TABLE}" | head -n 30 |grep -C 2 'umber of pages allocated' | sed -r 's,[[:space:]],,g' | sed -r 's,.*[A-Z],\L&,g' | sed -e 's,[0-9], &,' >${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.check
#...............................................................................
# Si le fichier est vide ou n'existe pas on le créé avec des valeurs égales à 0
#...............................................................................
if [ ! -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.check ]
then
echo -e "firstextentsize\t0\nnextextentsize\t0numberofpagesused\t0" >${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.check
fi
#...............................................................................
# On vient lire la taille du First Extent
#...............................................................................
unset firstExtent
firstExtent=`cat "${DirBakIfx}"/"${INSTANCE}"/"${DATABASE}"/"${TABLE}".check | grep 'firstextentsize' | awk '\
/firstextentsize/ { value=$2*2 } { \
if (value <= 16) \
{ \
value=16 \
} \
printf ("%6d",value) \
} '`
if [ -z "${firstExtent}" ]
then
firstExtent=16
fi
#...............................................................................
# On vient lire la taille du Next Extent
#...............................................................................
unset nextExtent
nextExtent=`cat "${DirBakIfx}"/"${INSTANCE}"/"${DATABASE}"/"${TABLE}".check | grep 'nextextentsize' | awk '\
/nextextentsize/ { value=$2*2 } { \
if (value <= 16) \
{ \
value=16 \
} \
printf ("%6d",value) \
} '`
if [ -z "${nextExtent}" ]
then
nextExtent=16
fi
#...............................................................................
# On vient calculer la taille du First Extent ideal (pagesUsed+25%)
# Attention le First Extent minimum doit être de 16
#...............................................................................
unset pagesUsed
pagesUsed=`cat "${DirBakIfx}"/"${INSTANCE}"/"${DATABASE}"/"${TABLE}".check | grep 'numberofpagesused' | awk '\
/numberofpagesused/ { value=$2*2*1.25 } { \
if (value <= 16) \
{ \
value=16 \
} \
printf ("%6d",value) \
} '`
if [ -z "${pagesUsed}" ]
then
pagesUsed=16
fi
#...............................................................................
# On vient calculer la taille du Next Extent basé sur la taille de pagesUsed
# Attention le Next Extent minimum doit être de 16
#...............................................................................
unset newNextExtent
if [ ${pagesUsed} -gt 64 ]
then
newNextExtent=`expr ${pagesUsed} / 4`
else
newNextExtent=16
fi
if [ -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.check ]
then
rm -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.check
fi
#...............................................................................
# On vient lire le nom des colonnes de la table
#...............................................................................
echo "UNLOAD TO '${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.col' \
SELECT syscolumns.colno,syscolumns.colname \
FROM systables,syscolumns \
WHERE systables.tabname='${TABLE}' \
AND syscolumns.tabid=systables.tabid \
ORDER BY syscolumns.colno ASC;" | \
${INFORMIXDIR}/bin/dbaccess ${DATABASE} 1>/dev/null 2>&1
#...............................................................................
# On vient retirer les | liés a l'UNLOAD Informix
#...............................................................................
if [ -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.col ]
then
cat ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.col | \
sed -e 's,|$,,g' | sed -e 's,|, ,g' \
>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.colname
if [ ! -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.colname ]
then
echo "99999 noname" \
>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.colname
fi
else
echo "99999 noname" >${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.colname
fi
if [ -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.col ]
then
rm -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.col
fi
#...............................................................................
# On vient lire l'index primaire de la table
#...............................................................................
echo "UNLOAD TO '${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx' \
SELECT sysindexes.levels,sysindexes.part1,\
sysindexes.part2,sysindexes.part3,sysindexes.part4,\
sysindexes.part5,sysindexes.part6,sysindexes.part7,\
sysindexes.part8,sysindexes.part9,sysindexes.part10,\
sysindexes.part11,sysindexes.part12,sysindexes.part13,\
sysindexes.part14,sysindexes.part15,sysindexes.part16 \
FROM systables,sysindexes \
WHERE systables.tabname='${TABLE}' \
AND sysindexes.tabid=systables.tabid \
ORDER BY sysindexes.levels ASC;" | \
${INFORMIXDIR}/bin/dbaccess ${DATABASE} 1>/dev/null 2>&1
#...............................................................................
# On vient retirer la colonne levels du fichier issu de l'UNLOAD
# Si le fichier est vide c'est qu'il n'y a pas d'index
#...............................................................................
if [ -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx ]
then
cat ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx | \
sed -e 's,^[0-9]*.|,,' | sed -e 's,^,|,g' \
>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idxname
if [ ! -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idxname ]
then
echo "|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|" \
>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idxname
fi
else
echo "|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|" \
>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idxname
fi
if [ -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx ]
then
rm -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx
fi
#...............................................................................
# On vient fusionner le fichier index avec le fichier des noms de colonnes
#...............................................................................
/usr/bin/awk -v FICCOL=${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.colname -v FICIDX=${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idxname '
BEGIN {
FS = "|"
tabidx=0
while ((getline < FICIDX) > 0) {
tabindex[tabidx]=$0
FS = " "
while ((getline < FICCOL) > 0) {
colid=$1
colname=$2
gsub("\\|" colid "\\|","|" colname "|",tabindex[tabidx])
}
close(FICCOL)
tabidx++
FS = "|"
}
close(FICIDX)
tabidx=0
while ((tabidx in tabindex) > 0) {
print tabindex[tabidx]
tabidx++
}
}' | sed -e 's,0,,g' | sed -e 's,||,,g' | sed -e 's,^|,,g' | sed -e 's,|$,,g' | sed -e 's/|/,/g'>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx
if [ -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx ]
then
rm -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.colname
rm -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idxname
fi
#...............................................................................
# On vient fabriquer un script de rechargement de la table
#...............................................................................
echo -e "#!/bin/sh\n" >${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo "if [ -s ./${TABLE}.out ]" \
>>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo "then" >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo -e "\tmv ./${TABLE}.out ./${TABLE}.bak" \
>>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo -e "fi\n" >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo "${INFORMIXDIR}/bin/dbaccess ${DATABASE}<<!EOF" \
>>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo -e "\tUNLOAD TO '${TABLE}.out'" \
>>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo -e "\tSELECT *" >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo -e "\tFROM ${TABLE}" >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
#...............................................................................
# On vient lire le premier index de la liste des index de la table
#...............................................................................
if [ -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx ]
then
unset sOrderBy
sOrderBy=`head -1 "${DirBakIfx}"/"${INSTANCE}"/"${DATABASE}"/"${TABLE}".idx`
else
sOrderBy=""
fi
if [ ! -z "${sOrderBy}" ]
then
echo -e "\tORDER BY ${sOrderBy} ASC;\n" \
>>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
else
echo -e ";\n" >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
fi
echo -e "\tDROP TABLE ${TABLE};\n" \
>>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
#...............................................................................
# On vient fabriquer le schema de la table
#...............................................................................
unset inDbSpace
if [ -z "${nomDbSpace}" ]
then
inDbSpace=") extent size"
else
inDbSpace=") in ${nomDbSpace} extent size"
fi
${INFORMIXDIR}/bin/dbschema -d ${DATABASE} -ss -t ${TABLE} | grep -v -E "DBSCHEMA|Copyright|Software|\{|\}" | grep -v '^$' | sed -e 's,unipe,informix,g' | sed -e 's,develop,informix,g' | sed -e 's,jacquelg,informix,g' | sed -e 's,martinec,informix,g' | sed -e 's,mhenrip,informix,g' | sed -e 's,noelb,informix,g' | sed -e 's,benoitg,informix,g' | sed -e 's,fadrian,informix,g' | sed -e 's,mterreau,informix,g' | sed -e "s,revoke.*$,LOAD FROM '\./${TABLE}\.out' INSERT INTO ${TABLE}\;," | sed -r "s,\) *.extent size,${inDbSpace},g" | sed -r "s,extent size [0-9]*.,extent size ${pagesUsed} ,g" | sed -r "s,next size [0-9]*.,next size ${newNextExtent} ,g" | sed -e 's,lock mode page,lock mode row,g' >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo -e "UPDATE STATISTICS HIGH FOR TABLE ${TABLE};\n" >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
echo -e "!EOF 1>/dev/null 2>&1\n" >>${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.cmd
}
###############################################################################
# FONCTION Unload_IfxTable
# LIBELLE Fonction d'exportation des données Informix
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE INSTANCE,DATABASE,TABLE
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet d'extraire les données d'une table
# informix dans un fichier texte à plat.
###############################################################################
Unload_IfxTable()
{
if [ $# -gt 2 ]
then
export INSTANCE=$1
export DATABASE=$2
export TABLE=$3
fi
#...............................................................................
# Déchargement de la table courante dans un fichier texte
#...............................................................................
unset sRequete
sRequete="SELECT * FROM ${TABLE}"
#...............................................................................
# On vient lire le premier index de la liste des index de la table
#...............................................................................
if [ -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx ]
then
unset sOrderBy
sOrderBy=`head -1 "${DirBakIfx}"/"${INSTANCE}"/"${DATABASE}"/"${TABLE}".idx`
else
sOrderBy=""
fi
if [ -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx ]
then
rm -f ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.idx
fi
if [ ! -z "${sOrderBy}" ]
then
sRequete=${sRequete}" ORDER BY ${sOrderBy} ASC;"
else
sRequete=${sRequete}";"
fi
echo "UNLOAD TO '${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.out' \
${sRequete}" |\
${INFORMIXDIR}/bin/dbaccess ${DATABASE} 1>/dev/null 2>&1
}
###############################################################################
# FONCTION Compress_IfxTable
# LIBELLE Fonction de compression des donées
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE INSTANCE,DATABASE,TABLE
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de compresser les fichiers contenant les
# données d'une table informix afin d'économiser de la place
###############################################################################
Compress_IfxTable()
{
if [ $# -gt 2 ]
then
export INSTANCE=$1
export DATABASE=$2
export TABLE=$3
fi
if [ ! -s ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.out ]
then
echo "La table ${TABLE} de la base ${DATABASE}, instance ${INSTANCE} est vide"
else
unset TailleTable
TailleTable=`du -sk ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.out | awk '{print $1}'`
gzip ${DirBakIfx}/${INSTANCE}/${DATABASE}/${TABLE}.out
echo "Table sauvegardée: ${TABLE} (${TailleTable} Ko)"
fi
}
###############################################################################
# FONCTION Histo_Dech
# LIBELLE Fonction d'historisation de la sauvegarde
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE folderHisto
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet d'ajouter une entrée dans le fichier
# d'historisation des sauvegardes
###############################################################################
Histo_Dech()
{
if [ $# -gt 0 ]
then
folderHisto=$1
else
return 1
fi
#...............................................................................
# On vient vérifier que le dossier des historiques existe bien
#...............................................................................
if [ ! -d ${folderHisto} ]
then
echo "Erreur: Le dossier ${folderHisto} n'existe pas"
return 1
fi
if [ -z "${BakDate}" ]
then
export BakDate=`date --iso-8601`
fi
if [ ! -d ${folderHisto}/${BakDate} ]
then
echo "Erreur: Le dossier ${folderHisto}/${BakDate} n'existe pas"
return 1
fi
unset tailleBackup
tailleBackup=`du -sk ${folderHisto}/${BakDate} | awk '{print $1}'`
#...............................................................................
# On vient vérifier que la sauvegarde courante n'a pas déjà été historisée.
#...............................................................................
if [ -s ${folderHisto}/histo_dech ]
then
unset isHisto
isHisto=`cat ${folderHisto}/histo_dech | grep ${BakDate}`
#...............................................................................
# Si isHisto n'est pas vide, c'est qu'il existe une historisation pour ce jour
# Dans ce cas, on l'efface et on la recalcule; Sinon, on l'insère directement
#...............................................................................
if [ ! -z "${isHisto}" ]
then
cat ${folderHisto}/histo_dech | grep -v ${BakDate} > ${folderHisto}/histo_temp
if [ -f ${folderHisto}/histo_temp ]
then
echo -e "${BakDate}\t${folderHisto}/${BakDate}\t${tailleBackup}" >>${folderHisto}/histo_temp
rm -f ${folderHisto}/histo_dech
mv ${folderHisto}/histo_temp ${folderHisto}/histo_dech
else
echo "Une erreur est survenue lors de l'historisation de la sauvegarde."
fi
else
echo -e "${BakDate}\t${folderHisto}/${BakDate}\t${tailleBackup}" >>${folderHisto}/histo_dech
fi
else
touch ${folderHisto}/histo_dech
echo -e "${BakDate}\t${folderHisto}/${BakDate}\t${tailleBackup}" >>${folderHisto}/histo_dech
fi
}
###############################################################################
# FONCTION Test_DblBackup
# LIBELLE Fonction de test de la sauvegarde
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE folderBackup
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de tester si la taille du dossier de
# backup est supérieure à la sauvegarde précedente du même jour.
# Cela permet de conserver une bonne sauvegarde dans un même
# jour, dans le cas où la sauvegarde courante serait incorrecte
###############################################################################
Test_DblBackup()
{
if [ $# -gt 0 ]
then
folderBackup=$1
else
return 1
fi
#...............................................................................
# On vient vérifier que le dossier de la sauvegarde existe bien
#...............................................................................
if [ ! -d ${folderBackup} ]
then
echo "Erreur: Le dossier ${folderBackup} n'existe pas"
return 1
fi
unset tailleBackup
tailleBackup=`du -sk ${folderBackup} | awk '{print $1}'`
unset tailleMinor
tailleMinor=`expr ${tailleBackup} / 4`
#...............................................................................
# On vient tester s'il existe une même sauvegarde pour ce jour
#...............................................................................
if [ -d ${folderBackup}.old ]
then
unset tailleOldBackup
tailleOldBackup=`du -sk ${folderBackup}.old | awk '{print $1}'`
tailleOldBackup=`expr ${tailleOldBackup} - ${tailleMinor}`
#...............................................................................
# Si la taille de l'ancien dossier de sauvegarde minoré du quart de la taille
# de la sauvegarde actuelle est > 0 ET
# que la taille de l'actuel dossier de sauvegarde est supérieur ou égal à
# cette valeur, alors on supprime l'ancien dossier de sauvegarde
#...............................................................................
if ([ ${tailleBackup} -ge ${tailleOldBackup} ] && [ ${tailleOldBackup} -gt 0 ])
then
rm -rf ${folderBackup}.old
else
echo "Pas de suppression de ${folderBackup}.old."
echo "Valeur de tailleBackup=>${tailleBackup}"
echo "Valeur de tailleOldBackup=>${tailleOldBackup}"
fi
fi
}
###############################################################################
# FONCTION Remove_Backup
# LIBELLE Fonction de suppression des anciennes sauvegardes
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE nbBakToKeep
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de tester le nombre de sauvegardes
# présentes dans le dossier de backup, et de supprimer toutes
# les plus anciennes sauvegardes
###############################################################################
Remove_Backup()
{
if [ $# -gt 1 ]
then
folderBackup=$1
nbBakToKeep=$2
else
return 1
fi
#...............................................................................
# On vient vérifier que le dossier de la sauvegarde existe bien
#...............................................................................
if [ ! -d ${folderBackup} ]
then
echo "Erreur: Le dossier ${folderBackup} n'existe pas"
return 1
fi
#...............................................................................
# On récupère la liste des 8 dernières sauvegardes
#...............................................................................
unset ListeToKeep
ListeToKeep=`ls -1t ${folderBackup} | grep -v 'histo_dech' | head -8`
if [ -z "${ListeToKeep}" ]
then
echo "Erreur: Le dossier ${folderBackup} est vide"
return 1
fi
#...............................................................................
# On vient lire la liste de tous les dossiers
#...............................................................................
listeAll=`ls -1t ${folderBackup} | grep -v 'histo_dech'`
#...............................................................................
# On supprime de la liste des dossiers les éléments à conserver
#...............................................................................
for Dossier in ${ListeToKeep}
do
listeAll=`echo ${listeAll} | sed -e 's,'${Dossier}',,g'`
done
#...............................................................................
# Pour chaque élément de la nouvelle liste, on supprime le dossier
#...............................................................................
unset Dossier
if [ ! -z "${listeAll}" ]
then
for Dossier in ${listeAll}
do
echo "suppression de ${Dossier} (rm -rf ${folderBackup}/${Dossier})"
rm -rf ${folderBackup}/${Dossier}
done
fi
}
###############################################################################
# FONCTION backup_IfxBases
# LIBELLE Fonction de sauvegarde des bases de données
# TYPE NORMAL
# ARGUMENTS OUI
# ENTREE INSTANCE,DATABASE
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de déclencher une sauvegarde des bases
# de données Informix relatives à une instance
###############################################################################
backup_IfxBases()
{
if [ $# -gt 1 ]
then
export INSTANCE=$1
export DATABASE=$2
fi
#...............................................................................
# Création du dossier de sauvegarde
#...............................................................................
if [ -d ${DirBakIfx}/${INSTANCE}/${DATABASE} ]
then
if [ -d ${DirBakIfx}/${INSTANCE}/${DATABASE}.old ]
then
rm -rf ${DirBakIfx}/${INSTANCE}/${DATABASE}.old
fi
mv ${DirBakIfx}/${INSTANCE}/${DATABASE} ${DirBakIfx}/${INSTANCE}/${DATABASE}.old
fi
mkdir ${DirBakIfx}/${INSTANCE}/${DATABASE}
unset nomDbSpace
if [ -s ${DirBakIfx}/${INSTANCE}/liste_dbspaces ]
then
nomDbSpace=`cat ${DirBakIfx}/${INSTANCE}/liste_dbspaces | grep ${DATABASE} | awk '{print $1}'`
else
nomDbSpace=""
fi
#...............................................................................
# Fonction de génération des scripts de rechargement de la base
#...............................................................................
echo "UNLOAD TO '/tmp/liste_tbl'\
SELECT tabname\
FROM systables\
WHERE tabtype='T'\
AND tabid>99\
ORDER BY tabname;" |\
${INFORMIXDIR}/bin/dbaccess ${DATABASE} 1>/dev/null 2>&1
if [ -s /tmp/liste_tbl ]
then
cat /tmp/liste_tbl | sed -e 's,|$,,g' | sed -e 's,|,\t,g' \
>${DirBakIfx}/${INSTANCE}/${DATABASE}/liste_tables
rm -f /tmp/liste_tbl
else
return 1
fi
################################################################################
# BOUCLE des tables de la base de données courante
################################################################################
#...............................................................................
# Pour chaque table:
# - on on calcule la taille du First extent et du Next extent
# - on génère un shéma
# - on décharge la table dans un fichier texte (.out)
# - on compresse le fichier d'export s'il est non vide
#...............................................................................
for TABLE in `cat ${DirBakIfx}/${INSTANCE}/${DATABASE}/liste_tables`
do
export TABLE
Genere_IfxScript ${INSTANCE} ${DATABASE} ${TABLE}
Unload_IfxTable ${INSTANCE} ${DATABASE} ${TABLE}
Compress_IfxTable ${INSTANCE} ${DATABASE} ${TABLE}
done
}
###############################################################################
# FONCTION backup_informix
# LIBELLE Fonction de sauvegarde
# TYPE NORMAL
# ARGUMENTS NON
# ENTREE AUCUN
# RETOUR AUCUN
# DESCRIPTION Cette fonction permet de déclencher une sauvegarde des bases
# de données Informix
###############################################################################
backup_informix()
{
unset DateNow
export DateNow=`date`
echo "DEBUT BACKUP INFORMIX du: ${DateNow}" >${LogBakIfx}
echo "" >>${LogBakIfx}
#...............................................................................
# Definition des variables informix
#...............................................................................
export INFORMIXDIR=/opt/informix
export PATH=${PATH}:${INFORMIXDIR}/bin:${INFORMIXDIR}/lib
export INFORMIXSQLHOSTS=${INFORMIXDIR}/etc/sqlhosts
export IFMX_HPKAIO_NUM_REQ=2000
export INFORMIXSTACKSIZE=128
export LD_LIBRARY_PATH=${INFORMIXDIR}/lib:${INFORMIXDIR}/lib/cli:${INFORMIXDIR}/lib/esql:${LD_LIBRARY_PATH}
export TERMCAP=/opt/informix/etc/termcap
export DBCENTURY=C
export DBDATE=DMY4/
unset Qui
export Qui=`uname -n`
unset MyIP
export MyIP=`cat /etc/hosts | grep "${Qui}" | awk '{print $1}'`
if [ ! -z "${MyIP}" ]
then
unset INSTANCES
INSTANCES=`cat ${INFORMIXSQLHOSTS} | grep -v '^#' | grep -v '^$' | grep "${MyIP}" | awk '{ print $1 }'`
################################################################################
# BOUCLE des Instances de base de données
################################################################################
for INSTANCE in `echo ${INSTANCES}`
do
export INSTANCE
if [ -s /home/shared/scripts/connexion/${INSTANCE}.var ]
then
source /home/shared/scripts/connexion/${INSTANCE}.var
else
export INFORMIXSERVER=${INSTANCE}
export ONCONFIG=onconfig.${INSTANCE}
fi
if [ ! -d ${DirBakIfx}/${INSTANCE} ]
then
mkdir ${DirBakIfx}/${INSTANCE}
fi
#...............................................................................
# On vient charge la liste des bases de l'instance courante
#...............................................................................
if [ -f /tmp/liste_dtb ]
then
rm -f /tmp/liste_dtb
fi
echo "UNLOAD TO '/tmp/liste_dtb' \
SELECT name \
FROM sysdatabases \
WHERE name NOT IN ('sysmaster','sysutils','sysuser');" |\
${INFORMIXDIR}/bin/dbaccess sysmaster 1>/dev/null 2>&1
if [ -s /tmp/liste_dtb ]
then
cat /tmp/liste_dtb | sed -e 's,|$,,g' | sed -e 's,|,\t,g' \
>${DirBakIfx}/${INSTANCE}/liste_databases
rm -f /tmp/liste_dtb
else
return 1
fi
#...............................................................................
# Requete de lecture des noms des dbspaces
#...............................................................................
echo "UNLOAD TO '/tmp/nom_dbs'\
SELECT dbinfo('DBSPACE',partnum) dbspace,name\
FROM sysdatabases\
ORDER BY dbspace,name ASC;" |\
${INFORMIXDIR}/bin/dbaccess sysmaster 1>/dev/null 2>&1
if [ -s /tmp/nom_dbs ]
then
cat /tmp/nom_dbs | sed -e 's,|$,,g' | sed -e 's,|,\t,g' \
>${DirBakIfx}/${INSTANCE}/liste_dbspaces
else
touch ${DirBakIfx}/${INSTANCE}/liste_dbspaces
fi
if [ -f /tmp/nom_dbs ]
then
rm -f /tmp/nom_dbs
fi
################################################################################
# BOUCLE des bases de données
################################################################################
for DATABASE in `cat ${DirBakIfx}/${INSTANCE}/liste_databases`
do
echo "###############################################################################" >>${LogBakIfx}
echo "# Base actuelle: ${DATABASE}" >>${LogBakIfx}
echo "###############################################################################" >>${LogBakIfx}
export DATABASE
backup_IfxBases ${INSTANCE} ${DATABASE} 1>>${LogBakIfx} 2>&1
Test_DblBackup ${DirBakIfx}/${INSTANCE}/${DATABASE} 1>>${LogBakIfx}2>&1
done
done
#...............................................................................
# Suppression des n sauvegardes précedentes
#...............................................................................
Remove_Backup ${DirBak}/informix 8 >>${LogBakIfx}
#...............................................................................
#Historisation de la sauvegarde courante
#...............................................................................
Histo_Dech ${DirBak}/informix 1>>${LogBakIfx} 2>&1
unset DateNow
export DateNow=`date`
echo "FIN BACKUP INFORMIX du: ${DateNow}" >>${LogBakIfx}
fi
}
###############################################################################
# FONCTION MAIN
# LIBELLE Fonction principale
# TYPE NORMAL
# ARGUMENTS NON
# ENTREE AUCUN
# RETOUR AUCUN
# DESCRIPTION entree du programme
###############################################################################
#...............................................................................
# Export des fonctions du script
#...............................................................................
export -f Genere_IfxScript
export -f Unload_IfxTable
export -f Compress_IfxTable
export -f Histo_Dech
export -f Test_DblBackup
export -f backup_IfxBases
export -f backup_informix
#...............................................................................
# Definition des variables de scripts
#...............................................................................
unset BakDate
export BakDate=`date --iso-8601`
unset DirBak
export DirBak=/home/backup
unset DirBakIfx
export DirBakIfx=${DirBak}/informix/${BakDate}
unset DirLog
export DirLog=/var/log/backup
unset LogBakIfx
export LogBakIfx=${DirLog}/informix/${BakDate}.log
#...............................................................................
# Vérification des variables de scripts
#...............................................................................
if [ -z "${BakDate}" ]
then
exit 1
fi
if [ ! -d ${DirBak} ]
then
mkdir ${DirBak}
chown root:backup ${DirBak}
mkdir ${DirBak}/informix
chown informix:backup ${DirBak}/informix
fi
if [ ! -d ${DirBak}/informix ]
then
mkdir ${DirBak}/informix
chown informix:backup ${DirBak}/informix
fi
if [ ! -d ${DirBakIfx} ]
then
mkdir ${DirBakIfx}
chown informix:backup ${DirBakIfx}
fi
if [ ! -d ${DirLog} ]
then
mkdir ${DirLog}
chown root:backup ${DirLog}
mkdir ${DirLog}/informix
chown informix:backup ${DirLog}/informix
fi
if [ ! -d ${DirLog}/informix ]
then
mkdir ${DirLog}/informix
chown informix:backup ${DirLog}/informix
fi
#...............................................................................
# On passe en tant qu'utilisateur informix sans son environnement
#...............................................................................
su informix -p -c backup_informix
Voilà, vous aurez au final un dossier par jour dans /home/backup/informix, contenant un sous dossier par instance, lui-même contenant un sous dossier par base de données, lui-même contenant un fichier .cmd représentant le schéma de la table et le fichier .out.gz qui lui est associé et contenant les données BRUT en texte prêtes à être rechargées en base (fichier gzip).