Résolu Backup bases de données

G

Guest

Invité
Bonjour,

Tout d'abord, désolé si je ne poste pas au bon endroit.

Je demande votre assistance pour du backup de base de donnée.

Je ne suis pas informaticien, mais pendant mon temps libre, j'essaie d'apprendre certaines choses qui pourraient me servir.

Là, je suis sur mysql sur une plate forme linux.

Ca fait déjà 2 ou 3 fois que suite à une erreur de manipulation, je perds toutes mes bases de données. je dois chaque fois tout recommencer. :/ Je perds donc du temps dans mon apprentissage.

J'essaie donc d'écrire un script que je mettrai dans un cron pour sauvegarder toutes mes tables.

Code:
#!/bin/bash

BASES_SQL=`mysql -u root -e "show databases"` #On commence par lister les bases de donnees
        for i in $BASES_SQL;    #on fait un boucle sur le resultat obtenu
                do
                        if  ! [ -d /root/$i ]; then #verification de la presence du repertoire et s'il n'existe pas on le cree
                        mkdir /root/$i
                        fi
                        TABLES_SQL=`mysql -u root -e "show tables from $i"` #pour chaque base de donnees, on extrait les tables
                        for b in $TABLES_SQL;
                                do
                                        mysqldump -u root $i $b >"/root/$i/$b.sql" #backup les tables individuellement
                                done
                done

Le hic, c'est que la commande show affiche le titre de la colonne et bien que le script fonctionne, j'ai un message d'erreur.

ERROR 1064 (42000) at line 1: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Database' at line 1
mysqldump: Couldn't find table: "Tables_in_mysql"
mysqldump: Couldn't find table: "Tables_in_postfix"

J'ai essayé en ajoutant le switch --skip-column-names dans la commande show, mais ça me retourne une erreur sql et ça ne fonctionne plus du tout. :/

Toute aide sera la bienvenue.

merci d'avance.
 

zeb

Modérateur
Salut,

Tu n'as pas un problème de bases de données.
Tu as des difficultés avec la programmation bash.

Je nous téléportes dans le Monde de Linux.
 
G

Guest

Invité
merci [:jap]

Je constate que les balises fixed on un peu écraser la mise en forme et que du coup mes commentaires s'étendent sur 2 lignes. Ca reste lisible ou je dois éditer?

 

RedSux

Grand Maître
Bonjour,

Bon, pas le temps de regarder ton script donc je te colle celui de mes serveurs :

[cpp]#!/bin/bash
# Connexion parameters
MyUSER="SET-MYSQL-USER-NAME" # USERNAME
MyPASS="SET-PASSWORD" # PASSWORD
MyHOST="localhost" # Hostname

# Linux bin paths, change this if it can not be autodetected via which command
MYSQL="$(which mysql)"
MYSQLDUMP="$(which mysqldump)"
CHOWN="$(which chown)"
CHMOD="$(which chmod)"
GZIP="$(which gzip)"

# Backup Dest directory, change this if you have someother location
DEST="/backup"

# Main directory where backup will be stored
MBD="$DEST/mysql"

# Get hostname
HOST="$(hostname)"

# Get data in dd-mm-yyyy format
NOW="$(date +"%d-%m-%Y")"

# File to store current backup file
FILE=""
# Store list of databases
DBS=""

# DO NOT BACKUP these databases
IGGY="test"

[ ! -d $MBD ] && mkdir -p $MBD || :

# Only root can access it!
$CHOWN 0.0 -R $DEST
$CHMOD 0600 $DEST

# Get all database list first
DBS="$($MYSQL -u $MyUSER -h $MyHOST -p$MyPASS -Bse 'show databases')"

for db in $DBS
do
skipdb=-1
if [ "$IGGY" != "" ];
then
for i in $IGGY
do
[ "$db" == "$i" ] && skipdb=1 || :
done
fi

if [ "$skipdb" == "-1" ] ; then
FILE="$MBD/$db.$HOST.$NOW.gz"
# do all inone job in pipe,
# connect to mysql using mysqldump for select mysql database
# and pipe it out to gz file in backup dir :)
$MYSQLDUMP -u $MyUSER -h $MyHOST -p$MyPASS $db | $GZIP -9 > $FILE
fi
done[/cpp]

Je sais plus ou j'avais trouvé ça, mais ça fonction, arrange le à ta sauce. Je me souviens juste que le script était fournit en GPLv2.
Bonne continuation.
 

zeb

Modérateur
Meilleure réponse
Bon, maintenant que nous sommes ici, je peux te demander de respecter le règlement de là-bas ? Utilise la balise [code ] plutôt que [fixed] pour présenter tes scripts.

Tu utilises bash, le Bourne Again Shell. C'est très bien. Alors n'utilise pas la syntaxe ancienne et obsolète du bsh : abandonne les anti-quotes `..` et utilise les dollar-parenthèses à la place : $( .. ) D'une c'est plus moderne, de deux, on peut les imbriquer, de trois, c'est plus facile à lire.

Et surtout, indente ton code.

Ah, encore une chose, trèèès importante.
N'UTILISE PAS LE COMPTE ROOT

-----------

Bon, si après tout ça tu n'es pas encore parti, voici quelques solutions.

Tu as une liste. Si tu veux filtrer cette liste, utilise les commandes standard sed, grep, voire le puissant awk.
Soit tu traites directement au remplissage de la variable, soit tu la filtres après.

Exemple 1
Cachez cette erreur que je ne saurais voir....
Code:
#!/bin/bash

BASES_SQL=$( mysql -u root -e "show databases" )
for BASE_SQL in $BASES_SQL
do
    if ! [ -d "$HOME/$BASE_SQL" ] ; then
        mkdir "$HOME/$BASE_SQL"
    fi
    TABLES_SQL=$( mysql -u root -e "show tables from $BASE_SQL" )
    for TABLE_SQL in $TABLES_SQL
    do
        mysqldump -u root "$BASE_SQL" "$TABLE_SQL" > "$HOME/$BASE_SQL/$TABLE_SQL.sql" 2> /dev/null
    done
done
(J'ai mis les variables en majuscule, par convention, j'ai retiré les points-virgules inutiles, et j'ai utilisé la variable $HOME, ce qui est logique, que ce soit root ou un autre utilisateur qui exécute le script.)
C'est la redirection 2 de la ligne 12 qui fait le boulot : l'erreur est devenue invisible.

Facile, non ?
Oui, mais horriblement moche et honteux.

Exemple 2
En supprimant les lignes qui contiennent "Tables_in_"
Code:
#!/bin/bash

BASES_SQL=$( mysql -u root -e "show databases" )
for BASE_SQL in $BASES_SQL
do
    if ! [ -d "$HOME/$BASE_SQL" ] ; then
        mkdir "$HOME/$BASE_SQL"
    fi
    TABLES_SQL=$( mysql -u root -e "show tables from $BASE_SQL" | grep -v 'Tables_in_' )
    for TABLE_SQL in $TABLES_SQL
    do
        mysqldump -u root "$BASE_SQL" "$TABLE_SQL" > "$HOME/$BASE_SQL/$TABLE_SQL.sql"
    done
done
C'est le grep de la ligne 9 qui fait le boulot.

Ca marche :)
Mais on peut faire mieux. En effet, ce qui t'embête, c'est l'entête, quelque soit son contenu.

Exemple 3
Pas la première ligne !

Code:
#!/bin/bash

BASES_SQL=$( mysql -u root -e "show databases" )
for BASE_SQL in $BASES_SQL
do
    if ! [ -d "$HOME/$BASE_SQL" ] ; then
        mkdir "$HOME/$BASE_SQL"
    fi
    TABLES_SQL=$( mysql -u root -e "show tables from $BASE_SQL" | awk '{if(NR>1)print}' )
    for TABLE_SQL in $TABLES_SQL
    do
        mysqldump -u root "$BASE_SQL" "$TABLE_SQL" > "$HOME/$BASE_SQL/$TABLE_SQL.sql"
    done
done
C'est le awk de la ligne 9 qui fait le boulot. Si le numéro de ligne (number row) est plus grand que 1, on affiche.

Quelle solution choisis-tu ?

-----------

Tiens, voici du code compliqué, juste pour le plaisir :
Code:
#!/bin/bash

if [ "$1" == "--help" ] ; then
	echo "$( basename $0 ): Sauvegarde des bases de données."
	echo "Syntaxe: $( basename $0 )"
	exit 0
fi

for BASE_SQL in $( mysql -u root -e "show databases" ) ; do
    [ -d "$HOME/$BASE_SQL" ] || mkdir "$HOME/$BASE_SQL"
    for TABLE_SQL in $( mysql -u root -e "show tables from $BASE_SQL" | 
                        awk '{if(NR>1)print}' ) ; do
        mysqldump -u root "$BASE_SQL" "$TABLE_SQL" | bzip2 > "$HOME/$BASE_SQL/$TABLE_SQL.sql.bz2"
    done
done
 
G

Guest

Invité
Merci pour vos propositions. [:jap]
corrections sur le mise-en-forme faites.

Merci pour les remarques sur la syntaxes. Il semblerait que mon bouquin soit un peu vieux. (J'utilise le livre learning bash d'Oreilly, si d'autres lectures, n'hésitez pas. )

Je testerai le tout ce soir devant mon pc personnel.





 
G

Guest

Invité
Bonjour,

Je reviens vers vous.

j'ai opté pour la solution 3 qui me convient tout à fait.

Une petite frayeur à la 1ère exécution qui me retournait une erreur.

Je n'avais pas fait attention à la nuance des variables.

Un tout grand merci.
 
G

Guest

Invité
Problème réglé.

Pour contenter tout le monde, j'ai créé un utilisateur sql qui a juste le droit de lire toutes les tables sans avoir d'accès en écriture et ça fonctionne très bien. [:jap]
 

zeb

Modérateur
Tu utilisais le compte root de mysql, ce qui n'est pas génial. Tu as créé un utilisateur lecteur, c'est très bien. Mais ce que je te disais, c'est de ne pas utiliser le compte root du système !
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 098
Messages
6 717 073
Membres
1 586 286
Dernier membre
petitangebleu1977
Partager cette page
Haut