
Cuando usamos un script en Bash para realizar respaldos de todas las bases de datos MySQL (excepto las de sistema), a veces nos encontramos con el mensaje:
mysqldump: Got error: 1049: "Unknown database 'Database'" when selecting the database
Este error se produce porque, al listar las bases con SHOW DATABASES, el primer elemento que aparece es el encabezado Database, y si no lo filtramos correctamente, el bucle de respaldo intentará ejecutar mysqldump Database, provocando el error de “base desconocida”. En este artículo veremos por qué sucede exactamente, y presentaremos dos soluciones sencillas para eliminar esa línea del encabezado y evitar el fallo.
¿Por qué aparece “Database” en la lista de bases?
Supongamos que tenemos un script llamado backupbases.sh con este fragmento:
#!/bin/bash
# Directorio de trabajo
DIRECTORIO=`pwd`
# Fecha de respaldo
DATE=`date +%Y-%m-%d-%H-%M`
### // Respaldando bases de MySQL \\ ###
# Seleccionar las bases a respaldar (todas menos la palabra Database que aparece al listar las bases)
LIST2=$(mysql -e "show databases" -u root --password=password | awk '{print $1}' | grep -vE '^-|^Database |^information_schema')
# Respaldar cada base y ubicar el respaldo en el directorio actual
for e in $LIST2
do
echo "respaldando $e"
mysqldump $e -u root --password=password -c > $DIRECTORIO/$e-$DATE.mysql
done
### \\ Respaldando bases de MySQL // ###
Cuando corremos mysql -e "show databases", la salida normal es:
Database
information_schema
mysql
performance_schema
database1
database2
...
- La primera línea es Database (sin comillas), que actúa como encabezado de columna.
- Luego vienen todas las bases, incluidas las de sistema como
information_schemayperformance_schema.
El problema reside en la parte:
… | awk '{print $1}' | grep -vE '^-|^Database |^information_schema'
awk '{print $1}'extrae la primera columna de cada línea, por lo que produce:Database information_schema mysql performance_schema database1 database2 ...- El patrón
^Database(con un espacio después de “Database”) no coincide con la líneaDatabase(que no tiene un espacio al final). Por tanto, “Database” no se filtra, y queda en la variable$LIST2. - Al iterar sobre
$LIST2, el bucle ejecuta primeromysqldump Database -u root ..., y MySQL devuelve:Got error: 1049: "Unknown database 'Database'" when selecting the database
Para eliminar este encabezado de manera correcta, podemos usar dos estrategias principales.
Opción 1: usar --skip-column-names al listar bases
MySQL permite omitir la fila de encabezado en la salida de consultas usando la opción --skip-column-names (o su forma corta -N). De este modo, el comando
mysql -u root --password=password --skip-column-names -e "SHOW DATABASES;"
devuelve directamente:
information_schema
mysql
performance_schema
database1
database2
...
sin la línea “Database” al inicio. Luego solo tenemos que filtrar las bases de sistema que no queremos respaldar, por ejemplo:
#!/bin/bash
# Directorio de trabajo
DIRECTORIO="$(pwd)"
# Fecha de respaldo (AAAA-MM-DD-HH-MM)
DATE="$(date +%Y-%m-%d-%H-%M)"
### // Respaldando bases de MySQL \\ ###
# Listar bases (sin cabecera) y excluir sólo information_schema y performance_schema
LIST2=$(
mysql -u root --password=password \
--skip-column-names \
-e "SHOW DATABASES;" \
| grep -Ev '^(information_schema|performance_schema)$'
)
# Respaldar cada base y guardar el archivo en el directorio actual
for e in $LIST2; do
echo "respaldando $e"
mysqldump -u root --password=password -c "$e" \
> "$DIRECTORIO/$e-$DATE.mysql"
done
### \\ Respaldando bases de MySQL // ###
¿Qué hace este script?
--skip-column-namesquita el encabezado “Database”.grep -Ev '^(information_schema|performance_schema)$'elimina exactamente las dos bases de sistema que no queremos respaldar.- El bucle
for e in $LIST2recorre únicamente los nombres de bases válidos (por ejemplo,mysql,database1,database2, …). - Para cada base, se ejecuta
mysqldumpy se genera un archivo con nombre<base>-<fecha>.mysql.
Con esto, ya no aparece la línea “Database” en $LIST2, y por ende desaparece el error 1049.
Opción 2: filtrar “Database” exacto con una expresión regular
Si prefieres no usar la opción --skip-column-names, basta con corregir el patrón de grep para que descarte la línea que es exactamente “Database” (sin espacios extra). Para ello, cambiamos el grep -vE '^-|^Database |^information_schema' por:
grep -Ev '^(Database|information_schema|performance_schema)$'
El script completo quedaría así:
#!/bin/bash
# Directorio de trabajo
DIRECTORIO="$(pwd)"
# Fecha de respaldo (AAAA-MM-DD-HH-MM)
DATE="$(date +%Y-%m-%d-%H-%M)"
### // Respaldando bases de MySQL \\ ###
# Listar bases (con encabezado) y filtrar para evitar "Database", "information_schema" y "performance_schema"
LIST2=$(
mysql -u root --password=password -e "SHOW DATABASES;" \
| awk '{print $1}' \
| grep -Ev '^(Database|information_schema|performance_schema)$'
)
# Respaldar cada base válida
for e in $LIST2; do
echo "respaldando $e"
mysqldump -u root --password=password -c "$e" \
> "$DIRECTORIO/$e-$DATE.mysql"
done
### \\ Respaldando bases de MySQL // ###
Por qué funciona
awk '{print $1}'sigue sacando la primera columna, incluidos “Database” e “information_schema”.grep -Ev '^(Database|information_schema|performance_schema)$':^…$obliga a que coincida toda la línea completa.(Database|information_schema|performance_schema)descarta exactamente esas tres entradas.
- De esta forma, “Database” ya no está en la lista
$LIST2.
Buenas prácticas adicionales
Más allá de eliminar el encabezado “Database”, conviene seguir estos consejos al crear scripts de respaldo:
- Separar credenciales
Evita poner la contraseña en texto claro dentro del script. En su lugar, crea un archivo~/.my.cnfcon contenido similar a:[client] user=root password=TU_CONTRASEÑAY ajusta el script para usar simplementemysqlymysqldumpsin-u root --password=…. - Excluir otras bases de sistema
Además deinformation_schemayperformance_schema, podrías querer excluirmysql(dependiendo de si quieres respaldar los privilegios) osys. Ajusta elgrep -Ev '…'para incluirlas en caso de no necesitar un backup de esas bases. - Almacenamiento separado por fecha
En lugar de guardar todos los.mysqlen el mismo directorio, podrías crear una subcarpeta con la fecha del día:DIR_RESPALDO="$DIRECTORIO/respaldos/$(date +%Y-%m-%d)" mkdir -p "$DIR_RESPALDO" … > "$DIR_RESPALDO/$e-$DATE.mysql"Así tendrás ordenados los respaldos por día. - Manejo de errores
Captura el código de salida demysqldumppara detectar fallos y, si uno ocurre, notifica por correo o detén el script:if ! mysqldump -u root --password="$PASSWORD" -c "$e" > "$ARCHIVO"; then echo "Error: no se pudo respaldar $e" >&2 exit 1 fi - Programar con cron
Para automatizar el respaldo diario, añade una entrada en el crontab del usuario:0 2 * * * /ruta/a/backupbases.sh >> /ruta/a/log_backupbases.log 2>&1Esto ejecuta el script cada día a las 2 AM y redirige la salida a un archivo de log.
Conclusión
El error:
mysqldump: Got error: 1049: "Unknown database 'Database'" when selecting the database
se debe a que el encabezado literal Database que MySQL imprime al listar bases no se estaba filtrando correctamente, quedando en la lista de $LIST2. Para evitarlo, puedes:
- Opción 1: usar
mysql --skip-column-names -e "SHOW DATABASES;"y luego filtrar solo las bases de sistema que no deseas respaldar. - Opción 2: mantener la salida con encabezado y ajustar
grep -vEpara excluir exactamente la líneaDatabase, junto coninformation_schemayperformance_schema.
Ambas soluciones impiden que el bucle intente respaldar una base llamada “Database” y, por tanto, evitan el error 1049. Elige la que mejor se adapte a tu entorno y, de paso, considera implementar buenas prácticas como separar las credenciales, organizar los backups por carpetas y manejar errores dentro del script. ¡Así tendrás un respaldo confiable y libre de fallos!
