2010-07-27 12 views
7

Estoy usando la secuencia de comandos Copia de seguridad de la base de datos por David Walsh (http://davidwalsh.name/backup-mysql-database-php) para hacer una copia de seguridad de mi base de datos MYSQL como un archivo .sql en mi servidor.¿Por qué mi script de copia de seguridad de base de datos no funciona en php?

Creé un usuario llamado backup y le di todos los privilegios (solo para estar seguro). Luego puse el código en un archivo php y configuré un trabajo cron para ejecutar el archivo php.

Este es el código:

/* backup the db OR just a table */ 
function backup_tables($host,$user,$pass,$name,$tables = '*') 
{ 

    $link = mysql_connect($host,$user,$pass); 
    mysql_select_db($name,$link); 

    //get all of the tables 
    if($tables == '*') 
    { 
     $tables = array(); 
     $result = mysql_query('SHOW TABLES'); 
     while($row = mysql_fetch_row($result)) 
     { 
      $tables[] = $row[0]; 
     } 
    } 
    else 
    { 
     $tables = is_array($tables) ? $tables : explode(',',$tables); 
    } 

    //cycle through 
    foreach($tables as $table) 
    { 
     $result = mysql_query('SELECT * FROM '.$table); 
     $num_fields = mysql_num_fields($result); 

     $return.= 'DROP TABLE '.$table.';'; 
     $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table)); 
     $return.= "\n\n".$row2[1].";\n\n"; 

     for ($i = 0; $i < $num_fields; $i++) 
     { 
      while($row = mysql_fetch_row($result)) 
      { 
       $return.= 'INSERT INTO '.$table.' VALUES('; 
       for($j=0; $j<$num_fields; $j++) 
       { 
        $row[$j] = addslashes($row[$j]); 
        $row[$j] = ereg_replace("\n","\\n",$row[$j]); 
        if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; } 
        if ($j<($num_fields-1)) { $return.= ','; } 
       } 
       $return.= ");\n"; 
      } 
     } 
     $return.="\n\n\n"; 
    } 

    //save file 
    $handle = fopen('../backup/db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+'); 
    fwrite($handle,$return); 
    fclose($handle); 
} 

backup_tables('localhost','alupto_backup','pass','*'); 

Cuando el trabajo de cron se ejecuta, la copia de seguridad no funciona y recibo un correo electrónico con el error que aparece:


Advertencia: mysql_fetch_row(): argumento suministrado no es un recurso válido de resultados MySQL en /home5/ideapale/public_html/amator ders_basic/admin/backup.php en la línea

En la línea 18 es el código:

while($row = mysql_fetch_row($result))

cuando ejecuto el SQL (VER TABLA) en phpMyAdmin, funciona bien y me muestra una lista de todas las tablas. Pero por alguna razón, recibo un error cuando el archivo php intenta ejecutar el SQL.

¿Por qué mi script de copia de seguridad de la base de datos no funciona?

Respuesta

14

Esto no funcionará para hacer una copia de seguridad de su base de datos como una secuencia de comandos SQL, a menos que su base de datos sea simplemente una base de datos de juguetes, el equivalente de una secuencia de comandos "mundo hello".

Ese script es pésimo. No deberías usarlo para hacer una copia de seguridad de una base de datos. Ese guión ha sido publicado antes: PHP Database Dump Script - are there any issues?

  • Sin comprobación de errores después de mysql_connect() o mysql_queries(). Probablemente acaba de dar una contraseña incorrecta o algo así, pero nunca lo sabrá porque el script no verifica que la conexión fue exitosa.

  • No producirá la instrucción INSERT correcta si su base de datos contiene NULLs.

  • Los juegos de caracteres no se manejan.

  • addslashes() es not suitable para el escape de datos.

  • Los nombres de las tablas no están delimitados.

  • No realiza copias de seguridad de vistas, procedimientos, funciones o desencadenantes.

  • mysql_query() almacena los resultados, por lo que si tiene una tabla con miles de filas o más, excederá su límite de memoria PHP. De hecho, la secuencia de comandos concatena la serie de instrucciones INSERT en una sola variable de PHP. Entonces, antes de que termine, tendrá su completa de la base de datos representada en la memoria.

Nadie debería usar esa secuencia de comandos. Es una basura total, y no lo digo a la ligera.

Simplemente use shellexec() para ejecutar mysqldump.

@ Álvaro G. Vicario tiene un buen punto, no es necesario que use PHP para esta tarea. Asumí que necesitas hacer una copia de seguridad desde un script PHP. Así es como crearía una copia de seguridad desde una secuencia de comandos cron:

Cree una secuencia de comandos de la shell, se puede llamar lo que desee, p. mymysqldump.sh. Así es como lo escribiría:

: 
: ${BACKUP_HOST:="localhost"} 
: ${BACKUP_DATABASE:="mydatabase"} 
: ${BACKUP_DIR:="/opt/local/var/db/mysql5/backups"} 
: ${BACKUP_FILE:="${DATABASE}-`date +%Y%m%d%H%M%S`"} 

mysqldump -h ${BACKUP_HOST} ${BACKUP_DATABASE} > ${BACKUP_DIR}/${BACKUP_FILE} 

Por supuesto, personalice los valores de las variables según sea necesario para su entorno.

Puede notar que el nombre de usuario y la contraseña son y no en este archivo. No coloque contraseñas en las secuencias de comandos en texto sin formato para que todos puedan leerlas. En cambio, los pondremos en un archivo de opciones para hacerlo más seguro.

Cree un usuario especial del sistema operativo que vaya a ejecutar la copia de seguridad desde cron. Su sistema puede tener un usuario especial "mysql" o "_mysql" para ejecutar el servidor MySQL, pero este usuario puede estar configurado para no tener un directorio inicial válido. Necesita un usuario que tenga un directorio de inicio. Vamos a llamarlo "mybackup".

en el directorio inicial de ese usuario, crear un archivo .my.cnf con el siguiente contenido:

[mysqldump] 
user = alupto_backup 
password = xyzzy 

Donde "alupto_backup" y "XYZZY" son el nombre de usuario de MySQL y su contraseña (cambiar estos términos para su entorno). Establecer la propiedad y la forma de este archivo para que sólo su dueño puede leerlo:

chown mybackup .my.cnf 
chmod 600 .my.cnf 

Crear un directorio bin bajo la casa de este usuario y poner nuestro script de shell en ella.

mkdir ~mybackup/bin 
mv mymysqldump ~mybackup/bin 

Ahora puede ejecutar el script de shell para probarlo:

sh ~mybackup/bin/mymysqldump 

Ahora cree un archivo cron para este usuario:

crontab -u mybackup 

@daily ~mybackup/bin/mymysqldump 

Esa debe ser la misma.

+0

Y usa el 'ereg_replace()' obsoleto solo para agregar a la lista. –

+1

shellexec? ¿Por qué incluso usar PHP para ejecutar un programa a través de cron? –

+0

Ok, nunca me di cuenta de eso. ¿Conoces un buen tutorial que muestra cómo usar shellexec() para ejecutar mysqldump? – zeckdude

0

Utilice la función mysql_error() para ver de qué se queja MySQL.

+0

¿Dónde podría agregar eso? – zeckdude

0

Tienes que asegurarte de que mysql_query no devuelva primero un flujo no continuo. Pruebe esto:

.... 

if (false !== ($result = mysql_query('SHOW TALBES')) { 
    while($row = mysql_fetch_row($result)) 
    { 
     $tables[] = $row[0]; 
    } 
} else { 
    // see Mchl's point about mysql_error 
} 
+0

¿Qué escribiría en la cláusula else? – zeckdude

+0

Un simple 'echo mysql_error()' sería un buen comienzo. Es solo para decir qué pasa con la consulta. Sin embargo, cualquier declaración de depuración sería suficiente. – efritz

3

El guión se ve muy débil en mi humilde opinión. Debe considerar usar mysqldump si está disponible en su sistema.

actualización

La línea de comandos básica sería:

mysqldump -hYOURHOSTNAME -uYOURUSER -pYOURPASSWORD infocap > dump.sql 

Puede probar mysqldump en el equipo local y, una vez que estés satisfecho con los resultados, ya sea crear un script de shell o agregarlo directamente como una tarea cron.

+0

Parece una buena opción. ¿Conoces un buen tutorial que muestre cómo hacerlo? La documentación de MYSQL no es tan fácil de entender. – zeckdude

+0

@zeckdude: Vea la actualización –

Cuestiones relacionadas