web-dev-qa-db-fra.com

Comment exécuter une commande MySQL à partir d'un script Shell?

Comment puis-je exécuter une commande SQL via un script Shell afin de pouvoir l'automatiser?

Je souhaite restaurer les données que j'ai collectées dans un fichier SQL à l'aide d'un script Shell. Je veux me connecter à un serveur et restaurer des données. La commande fonctionne lorsqu'elle est exécutée séparément via la ligne de commande SSH.

C'est la commande que j'utilise:

mysql -h "server-name" -u root "password" "database-name" < "filename.sql"

C'est le code de script du shell qui crée le fichier ds_fbids.sql et le transfère dans mysql.

Perl fb_apps_frm_fb.pl
Perl fb_new_spider.pl ds_fbids.txt ds_fbids.sql
mysql -h dbservername -u username -ppassword dbname < ds_fbids.sql

Quelle est la bonne façon de faire cela?

105
MUFC

Vous devez utiliser le drapeau -p pour envoyer un mot de passe. Et c'est délicat, car vous ne devez pas laisser d'espace entre -p et le mot de passe.

$ mysql -h "server-name" -u "root" "-pXXXXXXXX" "database-name" < "filename.sql"

Si vous utilisez un espace après -p, le client mysql vous demandera le mot de passe de manière interactive, puis interprétera le prochain argument de commande comme un nom de base de données:

$ mysql -h "server-name" -u "root" -p "XXXXXXXX" "database-name" < "filename.sql"
Enter password: <you type it in here>
ERROR 1049 (42000): Unknown database 'XXXXXXXX'

En fait, je préfère stocker l'utilisateur et le mot de passe dans ~/.my.cnf afin de ne pas avoir à le mettre du tout sur la ligne de commande:

[client]
user = root
password = XXXXXXXX

Ensuite:

$ mysql -h "server-name" "database-name" < "filename.sql"

Re votre commentaire:

J'exécute les commandes mysql en mode batch comme ci-dessus sur la ligne de commande et dans les scripts Shell tout le temps. Il est difficile de diagnostiquer ce qui ne va pas avec votre script Shell, car vous n'avez pas partagé le script exact ni la sortie d'erreur. Je vous suggère de modifier votre question initiale ci-dessus et de donner des exemples de ce qui ne va pas.

De plus, lorsque je dépanne un script Shell, j'utilise l'indicateur -x pour savoir comment il exécute chaque commande:

$ bash -x myscript.sh
149
Bill Karwin

Utilisez cette syntaxe:

mysql -u $user -p$passsword -Bse "command1;command2;....;commandn"
101
Kshitij Sood

Toutes les réponses précédentes sont super. S'il s'agit d'une simple commande d'une ligne que vous souhaitez exécuter, vous pouvez également utiliser l'option -e.

mysql -h <Host> -u<user> -p<password> database -e \
  "SELECT * FROM blah WHERE foo='bar';"
34
Jericon

Comment exécuter un script SQL, utilisez cette syntaxe:

mysql --Host= localhost --user=root --password=xxxxxx  -e "source dbscript.sql"

Si vous utilisez Host en tant qu'hôte local, vous n'avez pas besoin de le mentionner. Vous pouvez utiliser ceci:

mysql --user=root --password=xxxxxx  -e "source dbscript.sql"

Cela devrait fonctionner pour Windows et Linux.

Si le contenu du mot de passe contient un ! (point d'exclamation), vous devez ajouter un \ (barre oblique inverse) devant celui-ci.

17
Milinda Bandara

Le cœur de la question a déjà reçu une réponse à plusieurs reprises, je pensais simplement ajouter que les backticks (s) ont été complétés à la fois dans les scripts Shell et dans SQL. Si vous avez besoin de les utiliser en SQL pour spécifier un nom de table ou de base de données, vous devez les échapper dans le script Shell de la manière suivante:

mysql -p=password -u "root" -Bse "CREATE DATABASE \`${1}_database\`;
CREATE USER '$1'@'%' IDENTIFIED BY '$2';
GRANT ALL PRIVILEGES ON `${1}_database`.* TO '$1'@'%' WITH GRANT OPTION;"

Bien sûr, la génération de code SQL via une entrée utilisateur concaténée (arguments passés) ne devrait pas être effectuée à moins de faire confiance à l'entrée utilisateur. Il serait beaucoup plus sûr de l'insérer dans un autre langage de script prenant en charge les paramètres et les chaînes correctement insérées pour l'insertion. dans MySQL.

7
Li1t

Vous avez oublié -p ou --password= (ce dernier est mieux lisible):

mysql -h "$server_name" "--user=$user" "--password=$password" "--database=$database_name" < "filename.sql"

(Les guillemets sont inutiles si vous êtes certain que vos informations d'identification/noms ne contiennent pas d'espace ni de caractères spéciaux du shell.)

Notez également que la page de manuel indique que la fourniture des informations d'identification sur la ligne de commande n'est pas sécurisée. Alors suivez les conseils de Bill sur my.cnf.

5
PointedEars
mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file

(utilisez le chemin complet pour sql_script_file si nécessaire) 

Si vous voulez rediriger la sortie vers un fichier 

mysql -h "hostname" -u usr_name -pPASSWD "db_name" < sql_script_file > out_file
5
vine

Comme indiqué précédemment, vous pouvez utiliser -p pour transmettre le mot de passe au serveur.

Mais je recommande ceci:

mysql -h "hostaddress" -u "username" -p "database-name" < "sqlfile.sql"

Notez que le mot de passe n'est pas là. Il vous demanderait alors le mot de passe. J'aurais PUIS le saisir. Pour que votre mot de passe ne soit pas connecté à l'historique de la ligne de commande du serveur.

Ceci est une mesure de sécurité de base.

Si la sécurité ne vous préoccupe pas, je supprimerai temporairement le mot de passe de l'utilisateur de la base de données. Puis, après l'importation, ajoutez-le à nouveau.

De cette manière, aucun autre compte partageant le même mot de passe ne serait compromis.

Il semble également que dans votre script Shell, vous n'attendez/vérifiez pas si le fichier que vous essayez d'importer existe réellement. Le script Perl n'est peut-être pas encore terminé.

4
Grok

Un point important à prendre en compte pour accéder à mysql à partir d'un script Shell utilisé dans cron est que mysql examine l'utilisateur connecté pour déterminer le fichier .my.cnf à charger.

Cela ne fonctionne pas avec cron. Cela peut également être source de confusion si vous utilisez su/Sudo car l’utilisateur connecté peut ne pas être l’utilisateur sous lequel vous vous exécutez.

J'utilise quelque chose comme:

mysql --defaults-extra-file=/path/to/specific/.my.cnf -e 'SELECT something FROM sometable'

Assurez-vous simplement que la propriété et les autorisations des utilisateurs et des groupes sont définies correctement et correctement sur le fichier .my.cnf.

2
Danny

Utilisation 

echo "your sql script;" | mysql -u -p -h db_name
0
senninha

J'ai écrit un script Shell qui lit les données du fichier de propriétés, puis exécute le script mysql sur un script Shell. partager cela peut aider les autres.

#!/bin/bash
    PROPERTY_FILE=filename.properties

    function getProperty {
       PROP_KEY=$1
       PROP_VALUE=`cat $PROPERTY_FILE | grep "$PROP_KEY" | cut -d'=' -f2`
       echo $PROP_VALUE
    }

    echo "# Reading property from $PROPERTY_FILE"
    DB_USER=$(getProperty "db.username")
    DB_PASS=$(getProperty "db.password")
    ROOT_LOC=$(getProperty "root.location")
    echo $DB_USER
    echo $DB_PASS
    echo $ROOT_LOC
    echo "Writing on DB ... "
    mysql -u$DB_USER -p$DB_PASS dbname<<EOFMYSQL

    update tablename set tablename.value_ = "$ROOT_LOC" where tablename.name_="Root directory location";
    EOFMYSQL
    echo "Writing root location($ROOT_LOC) is done ... "
    counter=`mysql -u${DB_USER} -p${DB_PASS} dbname -e "select count(*) from tablename where tablename.name_='Root directory location' and tablename.value_ = '$ROOT_LOC';" | grep -v "count"`;

    if [ "$counter" = "1" ]
    then
    echo "ROOT location updated"
    fi
0
flopcoder
mysql_config_editor set --login-path=storedPasswordKey --Host=localhost --user=root --password

Comment puis-je exécuter une ligne de commande avec un mot de passe sécurisé? utilisez l'éditeur de configuration !!!

Depuis mysql 5.6.6, vous pouvez stocker le mot de passe dans un fichier de configuration, puis exécuter des commandes cli comme ceci ....

mysql --login-path=storedPasswordKey ....

--login-path remplace les variables ... Hôte, utilisateur ET mot de passe. excellent droit!

0
Artistan
#!/bin/sh
#Procedures = update
#Scheduled at : Every 00.05 

v_path=/etc/database_jobs
v_cnt=0

MAILTO="[email protected] [email protected] [email protected]"
touch "$v_path/db_db_log.log"

#test
mysql -uusername -ppassword -h111.111.111.111 db_name -e "CALL functionName()" > $v_path/db_db_log.log 2>&1
if [ "$?" -eq 0 ]
  then
   v_cnt=`expr $v_cnt + 1`
  mail -s "db Attendance Update has been run successfully" $MAILTO < $v_path/db_db_log.log
 else
   mail -s "Alert : db Attendance Update has been failed" $MAILTO < $v_path/db_db_log.log
   exit
fi
0
kartavya soni

Pour "automatiser" le processus d'importation du fichier .sql généré, tout en évitant toutes les interruptions pouvant être masquées lors de la tentative de transmission de fichiers via stdin et stdout, il suffit d'indiquer à MySQL d'exécuter le fichier .sql généré à l'aide de la commande SOURCE de MySQL.

La syntaxe dans le court, mais excellent, answer , from Kshitij Sood , donne le meilleur point de départ. En bref, modifiez la commande de l'OP conformément à la syntaxe de Kshitij Sood et remplacez-la par la commande SOURCE:

#!/bin/bash
mysql -u$user -p$password $dbname -Bse "SOURCE ds_fbids.sql
SOURCE ds_fbidx.sql"

Si le nom de la base de données est inclus dans le fichier .sql généré, il peut être supprimé de la commande.

La présomption est que le fichier généré est valide comme un fichier .sql à lui seul. En l'absence de redirection du fichier, de son canalisation ou de toute autre manière prise en charge par le shell, il n'y a aucun problème à devoir échapper à l'un des caractères de la sortie générée à cause du shell. Les règles concernant ce qui doit être échappé dans un fichier .sql s'appliquent bien entendu.

La manière de traiter les problèmes de sécurité autour du mot de passe sur la ligne de commande, dans un fichier my.cnf, etc., a été bien abordée dans d’autres réponses, avec quelques excellentes suggestions. Ma réponse préférée , de Danny , couvre cela, y compris la façon de gérer le problème lorsque vous travaillez avec des tâches cron ou autre.


Pour répondre à un commentaire (question?) Sur la réponse courte que j'ai mentionnée: Non, il ne peut pas être utilisé avec une syntaxe HEREDOC, car cette commande Shell est donnée. HEREDOC peut être utilisé dans la syntaxe redirection version (sans l'option -Bse), car la redirection des E/S est ce sur quoi HEREDOC est construit. Si vous avez besoin des fonctionnalités de HEREDOC, il serait préférable de les utiliser pour créer un fichier .sql, même temporaire, et d'utiliser ce fichier comme "commande" à exécuter avec la ligne de traitement par lots de MySQL.

#!/bin/bash
cat >temp.sql <<SQL_STATEMENTS
...
SELECT \`column_name\` FROM \`table_name\` WHERE \`column_name\`='$Shell_variable';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql

N'oubliez pas qu'en raison de l'expansion de Shell, vous pouvez utiliser les variables d'environnement et Shell dans HEREDOC. L'inconvénient est que vous devez vous échapper tous et chacun backtick. MySQL les utilise comme délimiteurs pour les identificateurs, mais le shell, qui obtient la chaîne en premier, les utilise comme délimiteurs de commandes exécutables. Manquez l'échappement sur un seul backtick des commandes MySQL, et le tout explose avec des erreurs. Toute la question peut être résolue en utilisant un LimitString cité pour le HEREDOC:

#!/bin/bash
cat >temp.sql <<'SQL_STATEMENTS'
...
SELECT `column_name` FROM `table_name` WHERE `column_name`='constant_value';
...
SQL_STATEMENTS
mysql -u $user -p$password $db_name -Be "SOURCE temp.sql"
rm -f temp.sql

En supprimant les extensions de Shell de cette manière, vous évitez d'avoir à échapper aux backticks et autres caractères spéciaux de Shell. Cela supprime également la possibilité d'utiliser les variables d'environnement et Shell à l'intérieur de celui-ci. Cela supprime les avantages d'utiliser un HEREDOC dans le script Shell pour commencer.

L'autre option consiste à utiliser les chaînes entre lignes multilignes autorisées dans Bash avec la version de syntaxe de lot (avec le -Bse). Je ne connais pas d’autres coquillages, je ne peux donc pas dire s’ils y travaillent également. Vous auriez quand même besoin de l'utiliser pour exécuter plus d'un fichier .sql avec la commande SOURCE car il s'agit de not terminé par un ; comme le sont les autres commandes MySQL et un seul est autorisé par ligne. La chaîne multiligne peut être simple ou double, avec les effets normaux sur le développement de Shell. Il présente également les mêmes inconvénients que l’utilisation de la syntaxe HEREDOC pour les backticks, etc.

Une meilleure solution consisterait probablement à utiliser un langage de script, Perl, Python, etc., pour créer le fichier .sql, comme l’a fait le PO, et SOURCE ce fichier à l’aide de la syntaxe de commande simple en haut. Les langages de script maîtrisent beaucoup mieux la manipulation des chaînes que le shell et la plupart ont des procédures intégrées pour gérer les guillemets et les échappements nécessaires lors de l'utilisation de MySQL.

0
Gypsy Spellweaver