¿Cómo ejecutar un comando MySQL desde un script de shell?

¿Cómo puedo ejecutar un comando SQL a través de un script de shell para poder automatizarlo?

Quiero restaurar los datos que he recopilado en un archivo SQL usando un script de shell. Quiero conectarme a un servidor y restaurar datos. El comando funciona cuando se ejecuta por separado a través de la línea de comando SSH.

Este es el comando que uso:

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

Este es el código del script de shell que crea el archivo. ds_fbids.sql y lo canaliza a 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

¿Cuál es la forma correcta de hacer esto?

preguntado el 08 de noviembre de 11 a las 19:11

14 Respuestas

Necesitas usar el -p bandera para enviar una contraseña. Y es complicado porque no debe haber espacio entre -p y la contraseña.

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

Si usa un espacio después -p hace que el cliente mysql le solicite la contraseña de forma interactiva, y luego interpreta el siguiente argumento de comando como un nombre de base de datos:

$ 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 realidad, prefiero almacenar el usuario y la contraseña en ~ / .my.cnf para no tener que ponerlos en la línea de comandos en absoluto:

[client]
user = root
password = XXXXXXXX

Entonces:

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

Re tu comentario:

Ejecuto comandos mysql en modo por lotes como el anterior en la línea de comandos y en scripts de shell todo el tiempo. Es difícil diagnosticar qué está mal con su script de shell, porque no ha compartido el script exacto o ningún resultado de error. Le sugiero que edite su pregunta original anterior y proporcione ejemplos de lo que sale mal.

Además, cuando soluciono un problema de un script de shell, uso el -x bandera para que pueda ver cómo está ejecutando cada comando:

$ bash -x myscript.sh

respondido 08 nov., 11:23

Gracias por una respuesta rápida. Me cansé de poner la contraseña en la propia línea de comandos. El problema real es que estoy poniendo este comando en el archivo .sh y luego ejecuto este script de shell. El comando en el archivo no se ejecuta en la línea de comando, pero el mismo comando funciona perfectamente bien cuando ejecuto solo el comando en la línea de comando. - MUF

+ mysql -h dbservername -u user-name -ppassword dbname</br> : No such file or directoryids.sql</br> + $'\r' : command not found2: Este es el mensaje de error que recibí: MUF

Ok, entonces inferiría que su directorio de trabajo actual no es donde se encuentra el archivo ids.sql. También es posible que haya incrustado nuevas líneas en su secuencia de comandos. - Bill Karwin

Tengo nuevas líneas incrustadas en mi script de shell después de cada comando. Todo lo que contiene mi script de shell son 3 comandos de línea de comandos que no quiero ejecutar por separado, así que creé un script de shell para que se ejecutaran sin mi intervención y puse una nueva línea después de cada comando. ¿Eso está causando problemas? - MUF

@ racl101, si desea que sea más claro en sus scripts, use --password=xxxxxx - Bill Karwin

Utilice esta sintaxis:

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

Respondido 30 Oct 12, 21:10

Llegué a esta página desde Google y esta es la solución que esperaba (que coincide con el título de la pregunta). - Janaka R Rajapaksha

Algunos detalles más sobre las opciones del manual: -B es para lotes, imprima los resultados usando la pestaña como separador de columnas, con cada fila en una nueva línea. Con esta opción, mysql no usa el archivo histórico. El modo por lotes da como resultado un formato de salida no tabular y el escape de caracteres especiales. -s es el modo silencioso. Produce menos salida. -e es ejecutar la declaración y salir - wranvaud

¡Gracias por tu ayuda! :) - haotang

¿Podría funcionar con un heredoc? - zx1986

@ zx1986 Sí y No, a HEREDOC. Depende de cómo pretenda usarlo. Usándolo para reemplazar el "command1;command2;....;commandn" parte de esta respuesta no funcionará. Usándolo para reemplazar el uso del archivo redirigido en la sintaxis del OP enlatado trabaja. He abordado ese problema en mi https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be a esta pregunta. - Chindraba

Todas las respuestas anteriores son geniales. Si desea ejecutar un comando sql simple de una línea, también puede usar la opción -e.

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

respondido 09 nov., 11:03

La consulta entre comillas dobles ("") era lo que tenía que hacer. Gracias - user3132107

Ya veo, y supongo que es necesario incluir el punto y coma al final de la consulta. - Lori

Cómo ejecutar un script SQL, use esta sintaxis:

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

Si usa host como localhost, no es necesario que lo mencione. Puedes usar esto:

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

Esto debería funcionar para Windows y Linux.

Si el contenido de la contraseña contiene un ! (Signo de exclamación) debe agregar un \ (barra invertida) delante de él.

Respondido el 25 de diciembre de 13 a las 01:12

¿Cómo especificar la base de datos? ¿Debería estar dentro de -e, como -e "use abc; source dbscript.sql"? - Abdul Muneer

El núcleo de la pregunta ya ha sido respondido varias veces, solo pensé en agregar que las comillas invertidas (`s) tienen beaning tanto en el script de shell como en SQL. Si necesita usarlos en SQL para especificar una tabla o el nombre de una base de datos, deberá escapar de ellos en el script de shell de la siguiente manera:

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;"

Por supuesto, la generación de SQL a través de la entrada del usuario concatenada (argumentos pasados) no debe hacerse a menos que confíe en la entrada del usuario. Sería mucho más seguro ponerlo en otro lenguaje de scripting con soporte para parámetros / cadenas de escape correctas para la inserción. en MySQL.

Respondido el 09 de junio de 15 a las 17:06

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

(use la ruta completa para sql_script_file si es necesario)

Si desea redirigir la salida a un archivo

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

respondido 13 mar '13, 22:03

@Gus, Primero que nada gracias por los valiosos comentarios. Funcionó a las mil maravillas para mí. Quiero que la salida sea un archivo de Excel o .csv. ¿Cómo puedo lograrlo? Gracias de antemano. - Ash_and_Perl

@Ash_and_Perl Solo edité esta respuesta, gracias a vine, no a mí, es su respuesta. Si tiene una pregunta propia, y ya ha intentado encontrar una solución por su cuenta, Le sugiero que cree una pregunta. De esa manera, puede detallar lo que intentó, cómo falló, y las personas pueden darle una respuesta completa y completa (¡y obtener puntos por ello!). - Gus

Te olvidaste -p or --password= (este último es mejor legible):

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

(Las comillas son innecesarias si está seguro de que sus credenciales / nombres no contienen espacios ni caracteres especiales).

Tenga en cuenta que la página de manual también dice que proporcionar las credenciales en la línea de comando no es seguro. Así que sigue el consejo de Bill sobre my.cnf.

Respondido el 10 de enero de 16 a las 19:01

Como se indicó anteriormente, puede usar -p para pasar la contraseña al servidor.

Pero te recomiendo esto:

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

Observe que la contraseña no está ahí. A continuación, le pedirá la contraseña. ENTONCES lo escribiría. Para que su contraseña no se registre en el historial de la línea de comandos del servidor.

Ésta es una medida de seguridad básica.

Si la seguridad no es una preocupación, simplemente eliminaría temporalmente la contraseña del usuario de la base de datos. Luego, después de la importación, vuelva a agregarlo.

De esta manera, cualquier otra cuenta que pueda tener que comparta la misma contraseña no se verá comprometida.

También parece que en su script de shell no está esperando / verificando si el archivo que está tratando de importar realmente existe. Es posible que el script de perl aún no esté terminado.

respondido 10 nov., 11:10

Te perdiste la parte "automatizada" de la pregunta y eliminar temporalmente la contraseña es una muy mala idea. - Orejas puntiagudas

Lo leo como "restaurar" y "automatizado", que significa "automatizado pero no para siempre". Pero como dije "si la seguridad no es una preocupación". Estoy de acuerdo, es REALMENTE una mala idea. - Sterling Hamilton

Lo siento si he creado confusión. Lo que quise decir con Automatizado es que tengo dos scripts de Perl que se usan para generar el archivo .sql, pero el comando para volcar ese archivo en la base de datos no lo ejecuta el script de shell, pero funciona absolutamente en el archivo si ejecuto ese comando. en una línea de comando. Quiero elevar el esfuerzo de ejecutar ese comando en la línea de comandos y ejecutarlo a través del script de shell. - MUF

Vaibav: si pudiera poner el script de shell real dentro de su pregunta, podría ayudarlo más. - Sterling Hamilton

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 - MUF

Utilizan

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

Respondido 18 Jul 18, 14:07

Para "automatizar" el proceso de importación de los .sql archivo, evitando todas las trampas que se pueden ocultar al intentar pasar archivos a través de stdin y stdout, solo dile a MySQL que ejecute el .sql archivo usando el SOURCE comando en MySQL.

La sintaxis en resumen, pero excelente, https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be, de Kshitij Sood, da el mejor punto de partida. En resumen, modifique el comando del OP de acuerdo con la sintaxis de Kshitij Sood y reemplace los comandos en eso con el SOURCE mando:

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

Si el nombre de la base de datos está incluido en el .sql archivo, se puede quitar del comando.

La presunción aquí es que el archivo generado es IMPORTANTE como una .sql archivo por su cuenta. Al no tener el archivo redirigido, canalizado o de cualquier otra manera manejado por el shell, no hay problema con la necesidad de escapar de ninguno de los caracteres en la salida generada debido al shell. Las reglas con respecto a lo que debe escaparse en un .sql archivo, por supuesto, todavía se aplica.

Cómo lidiar con los problemas de seguridad relacionados con la contraseña en la línea de comando, o en un my.cnf file, etc., se ha abordado bien en otras respuestas, con algunas sugerencias excelentes. Mi respuesta favorita, de Danny, cubre eso, incluido cómo manejar el problema cuando se trata de cron trabajos, o cualquier otra cosa.


Para abordar un comentario (¿pregunta?) en la respuesta corta que mencioné: No, no se puede usar con una sintaxis HEREDOC, ya que se proporciona ese comando de shell. HEREDOC se puede utilizar en redirección sintaxis de la versión, (sin la -Bse opción), ya que la redirección de E / S es sobre lo que se basa HEREDOC. Si necesita la funcionalidad de HEREDOC, sería mejor utilizarla en la creación de un .sql archivo, incluso si es temporal, y use ese archivo como el "comando" para ejecutar con la línea de proceso por lotes 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

Tenga en cuenta que, debido a la expansión del shell, puede utilizar variables de entorno y de shell dentro de HEREDOC. La desventaja es que debes escapar todos y cada uno tilde. MySQL los usa como delimitadores para identificadores, pero el shell, que obtiene la cadena primero, los usa como delimitadores de comandos ejecutables. Si se pierde el escape con una sola tilde de los comandos de MySQL, todo estalla en errores. Todo el problema se puede resolver utilizando un LimitString citado para el 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

Eliminar la expansión de shell de esa manera elimina la necesidad de escapar de las comillas invertidas y otros caracteres especiales de shell. También elimina la capacidad de usar variables de entorno y de shell dentro de él. Para empezar, eso prácticamente elimina los beneficios de usar un HEREDOC dentro del script de shell.

La otra opción es usar las cadenas entre comillas de varias líneas permitidas en Bash con la versión de sintaxis por lotes (con la -Bse). No conozco otros proyectiles, por lo que no puedo decir si también funcionan en ellos. Debería usar esto para ejecutar más de una .sql presentar ante la SOURCE comando de todos modos, ya que es no terminado por un ; como lo son otros comandos de MySQL, y solo se permite uno por línea. La cadena de varias líneas puede estar entre comillas simples o dobles, con los efectos normales en la expansión del shell. También tiene las mismas advertencias que el uso de la sintaxis HEREDOC para las comillas invertidas, etc.

Una solución potencialmente mejor sería utilizar un lenguaje de secuencias de comandos, Perl, Python, etc., para crear el .sql archivo, como hizo el OP, y SOURCE ese archivo usando la sintaxis de comando simple en la parte superior. Los lenguajes de secuencias de comandos son mucho mejores en la manipulación de cadenas que el shell, y la mayoría tiene procedimientos incorporados para manejar las citas y el escape necesarios cuando se trata de MySQL.

Respondido el 19 de enero de 19 a las 10:01

He escrito un script de shell que leerá los datos del archivo de propiedades y luego ejecutará el script mysql en el script de shell. compartir esto puede ayudar a otros.

#!/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

respondido 13 mar '19, 14:03

Si usted es un usuario root, entonces el uso de "sudo mysql" también funcionará. auth_socket viene habilitado por defecto para el usuario root. Estaba buscando si hay alguna forma de interpolar consultas SQL con variables bash. Y esto lo respondió. - Blaze

Una consideración importante para acceder a mysql desde un script de shell utilizado en cron, es que mysql mira al usuario que ha iniciado sesión para determinar un .my.cnf para cargar.

Eso no funciona con cron. También puede resultar confuso si está utilizando su / sudo, ya que el usuario que inició sesión podría no ser el usuario con el que se está ejecutando.

Yo uso algo como:

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

Solo asegúrese de que la propiedad y los permisos del usuario y del grupo estén configurados de manera adecuada y precisa en el archivo .my.cnf.

Respondido el 20 de enero de 17 a las 03:01

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

v_path=/etc/database_jobs
v_cnt=0

MAILTO="indd@abc.in joanson@abc.in sturt@abc.in"
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

respondido 05 nov., 15:09

mysql_config_editor set --login-path=storedPasswordKey --host=localhost --user=root --password

¿Cómo ejecuto una línea de comando con una contraseña segura? usa el editor de configuración !!!

A partir de mysql 5.6.6, puede almacenar la contraseña en un archivo de configuración y luego ejecutar comandos cli como este ...

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

--login-path reemplaza las variables ... host, usuario Y contraseña. excelente derecho!

Respondido 19 Feb 15, 16:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.