Mysql.inc.sh

De wiki.nexiat.fr
Aller à la navigation Aller à la recherche
Fiche express
Type Bibliothèque bash pour requêtage MySQL en script
Langage Bash + Perl (parsing des résultats)
Voir aussi Mysql config editor · Mysqldump

mysql.inc.sh est une petite bibliothèque bash à inclure (source) dans un script, fournissant quelques fonctions d'aide pour exécuter des requêtes MySQL et exploiter leurs résultats sans réinventer le parsing à chaque script.

Avertissement sécurité : ces fonctions passent le mot de passe en argument de commande (--password=$password), ce qui l'expose en clair dans la liste des processus (ps aux) le temps de l'exécution, à tout autre utilisateur du système. Pour un usage en production, préférer mysql_config_editor (login-path) ou un fichier ~/.my.cnf à permissions restreintes plutôt que ce passage explicite du mot de passe.

Chargement dans un script

test -f ./mysql.inc.sh && source ./mysql.inc.sh || exit 1

Fonctions fournies

  • rc_mysql_query (status, host, user, password, database, query) — exécute une requête. Pour les instructions INSERT/UPDATE/REPLACE/DELETE/DROP, retourne vrai/faux selon la présence d'une erreur ; pour les autres (SELECT, SHOW, DESCRIBE...), retourne le résultat.
  • rc_mysql_status (host, user, password, database, table, clé) — exécute SHOW TABLE STATUS LIKE '<table>' et extrait la valeur d'une colonne donnée (par exemple auto_increment).
  • mysql_fetch_rows (données brutes) — convertit un résultat brut en tableau bash row[], une ligne par entrée, colonnes séparées par |.
  • rc_mysql_nextid (host, user, password, database, table) — raccourci vers rc_mysql_status pour récupérer le prochain auto_increment d'une table.

Exemple d'utilisation

# Mise à jour de la table 'users'.
if ! rc_mysql_query "UPDATE" "$dbHostname" "$dbUsername" \
                     "$dbPassword" "$dbDatabase" \
                     "UPDATE users SET email='exemple@exemple.fr' WHERE id=1" ; then
    echo "La requête MySQL a échoué !"
fi

# Sélection de toutes les lignes de la table 'users'.
rows=$( rc_mysql_query "SELECT" "$dbHostname" \
                        "$dbUsername" "$dbPassword" \
                        "$dbDatabase" "SELECT * FROM users ORDER BY id ASC" )

# Conversion du résultat '$rows' en tableau row[].
mysql_fetch_rows "$rows"

# Parcours du tableau row[], découpage de chaque ligne sur le caractère '|'.
for (( i=0; i<${#row[@]}; i++ )); do
    id=$( echo ${row[$i]} | cut -d'|' -f1 )
    username=$( echo ${row[$i]} | cut -d'|' -f3 )
    echo "\$id: $id; \$username: $username"
done

# Récupération du prochain auto_increment de la table 'users'.
nextid=$( rc_mysql_nextid "$dbHostname" "$dbUsername" "$dbPassword" "$dbDatabase" "users" )

Code source

# *********************************************************
# file: mysql.inc.sh
# description: Petite bibliothèque bash pour MySQL.
# auteur original : bibliothèque tierce d'origine (identité non conservée dans cette migration)
# *********************************************************

# Exécute une instruction INSERT|UPDATE|REPLACE|DELETE|DROP et retourne le nombre
# de lignes affectées via ROW_COUNT().
function rc_mysql_query () {

local status=$1
local hostname=${2:-"localhost"}
local username=$3
local password=$4
local database=$5
local query=$6
local error="/tmp/mysql_query.err"

if [ "$status" = "INSERT" -o "$status" = "UPDATE" -o "$status" = "REPLACE" -o "$status" = "DELETE" -o "$status" = "DROP" ]; then
	local res=$( mysql	--user=$username \
						--password=$password \
						--database=$database \
						--host=$hostname \
						--line-numbers --no-beep -Bse "$query; SELECT ROW_COUNT();" 2>$error )

	if [ "$( cat $error | wc -l )" -ne 0 ]; then
		[ -f "$error" ] && rm -f $error; false
	else
		[ -f "$error" ] && rm -f $error; true
	fi
else
	local res=$( mysql --user=$username \
					--password=$password \
					--database=$database \
					--host=$hostname \
					--line-numbers --no-beep --column-names -Bse "$query" 2>$error )

	if [ "$( cat $error 2>/dev/null | wc -l )" -ne 0 ]; then
		if [ -f "$error" ]; then
			cat $error; rm -f $error; exit 1
		fi
	else
		echo -e "$res"
	fi
fi

}

# Exécute SHOW TABLE STATUS LIKE '<table>' et retourne la valeur d'une clé donnée
# (ex. auto_increment).
function rc_mysql_status () {

local hostname=${1:-"localhost"}
local username=$2
local password=$3
local database=$4
local table=$5
local object=$6
local error="/tmp/mysql_status.err"

local res=$( mysql --user=$username \
					--password=$password \
					--database=$database \
					--host=$hostname \
					--column-names --skip-auto-rehash -Be "SHOW TABLE STATUS LIKE '$table'" 2>$error )

if [ "$( cat $error 2>/dev/null | wc -l )" -ne 0 ]; then
	if [ -f "$error" ]; then
		cat $error; rm -f $error; exit 1
	fi
else
	echo -e "$res" | \
		perl -ne '
		BEGIN {
		use strict;
		use vars qw( $obj @data );
		$obj="'$object'";
		}

		my @tmp = split( /\s+/, $_ );
		push( @data, [@tmp] );

		END {
		my $index=0;
		for my $x ( 0 .. ($#data+1) ) {
			foreach my $y( 0 .. (@{$data[$x]}+1) ) {
				$index = $y if ( lc($data[0][$y]) eq "$obj" );
			}
		}
		print $data[1][$index]."\n";
		}'
fi

}

# Convertit le résultat brut MySQL en tableau numérique row[] (tableau 2D simulé,
# colonnes séparées par '|').
function mysql_fetch_rows () {

local data="$*"

array=$( echo -e "$data" | perl -ne '
BEGIN { $i=0; }
next if $_ =~ m/^$/;
$_ = conv_chars( $_ );
$_ =~ s/\t+/\|/g;
print "row[".$i."]=\"".$_."\"\n";
$i++;

sub conv_chars {
my $txt=shift;
$txt =~ s/\cM\n//g;
$txt =~ s/\n\cM//g;
$txt =~ s/\cM//g;
$txt =~ s/\s+$//g;
return $txt;
}
' )

eval $array

}

# Retourne le prochain auto_increment de la table donnée.
function rc_mysql_nextid () {

local hostname=${1:-"localhost"}
local username=$2
local password=$3
local database=$4
local table=$5

rc_mysql_status  "$dbHostname" "$dbUsername" "$dbPassword" "$dbDatabase" "$table" "auto_increment"

}

# EOF

Voir aussi

  • Mysql config editor — pour éviter le passage du mot de passe en argument de commande
  • Mysqldump — outil dédié pour les sauvegardes, à préférer à un script maison pour ce cas d'usage