Почему мой сценарий резервного копирования базы данных не работает в php?

Я использую сценарий резервного копирования базы данных Дэвида Уолша ( http://davidwalsh.name/backup-mysql-database-php ) для резервного копирования моей базы данных MYSQL в виде файла .sql на моем сервере.

Я создал пользователя с именем backup и дал ему все привилегии (просто чтобы убедиться). Затем я поместил код в файл php и установил задание cron для запуска php-файла.

Это код:

/* 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','*'); 

Когда выполняется задание cron, резервная копия не работает, и я получаю сообщение с появлением ошибки:

Предупреждение : mysql_fetch_row (): предоставленный аргумент не является допустимым ресурсом результата MySQL в /home5/ideapale/public_html/amatorders_basic/admin/backup.php в строке 18

В строке 18 указан этот код:

while($row = mysql_fetch_row($result))

Когда я запускаю SQL (SHOW TABLES) в phpMyAdmin, он отлично работает и показывает мне список всех таблиц. Но по какой-то причине я получаю сообщение об ошибке, когда php-файл пытается запустить SQL.

Почему мой сценарий резервного копирования базы данных не работает?

    Это не будет работать для резервного копирования вашей базы данных в виде SQL-скрипта, если только ваша база данных не является только игрушечной базой данных, эквивалентной сценарию «привет мир».

    Этот сценарий ужасен. Вы не должны использовать его для резервного копирования базы данных. Этот скрипт был опубликован раньше: PHP Database Dump Script – есть ли какие-либо проблемы?

    • Нет проверки ошибок после mysql_connect () или mysql_queries (). Вероятно, вы просто указали неверный пароль или что-то еще, но вы никогда не узнаете, потому что сценарий не проверяет, что соединение было успешным.

    • Он не будет выдавать правильную инструкцию INSERT, если ваша база данных содержит любые NULL.

    • Наборы символов не обрабатываются.

    • addslashes () не подходит для экранирования данных.

    • Имена таблиц не ограничены.

    • Не создает резервные копии представлений, процедур, функций или триггеров.

    • mysql_query () буферизует результаты, поэтому, если у вас есть таблица с тысячами строк или более, вы превысите предел памяти PHP. Фактически, скрипт объединяет ряд инструкций INSERT в одну переменную PHP. Поэтому, прежде чем он закончится, вы будете иметь всю свою базу данных, представленную в памяти.

    Никто никогда не должен использовать этот сценарий. Это полный мусор, и я не говорю это легкомысленно.

    Просто используйте shellexec () для запуска mysqldump.

    @ Álvaro G. Vicario имеет хороший момент, вам не нужно даже использовать PHP для этой задачи. Я предполагал, что вам нужно сделать резервную копию из PHP-скрипта. Вот как я создам резервную копию из cron-скрипта:

    Создайте сценарий оболочки, его можно назвать любым, например, mymysqldump.sh. Вот как я написал бы это:

     : : ${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} 

    Разумеется, настройте значения переменных по мере необходимости для вашей среды.

    Вы можете заметить, что имя пользователя и пароль не указаны в этом файле. Пожалуйста, не вводите пароли в сценарии в виде простого текста, чтобы каждый мог их прочитать. Вместо этого мы помещаем их в файл опций, чтобы сделать его более безопасным.

    Создайте специального пользователя операционной системы, который будет запускать резервное копирование из cron. У вашей системы может быть специальный пользовательский «mysql» или «_mysql» для запуска MySQL Server, но у этого пользователя может быть настроен отсутствие действительного домашнего каталога. Вам нужен пользователь, у которого есть домашний каталог. Назовем это «mybackup».

    В домашнем каталоге этого пользователя создайте файл .my.cnf со следующим содержимым:

     [mysqldump] user = alupto_backup password = xyzzy 

    Где «alupto_backup» и «xyzzy» – это имя пользователя MySQL и его пароль (измените их для вашей среды). Установите право собственности и режим этого файла, чтобы только его владелец мог прочитать его:

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

    Создайте каталог bin в этом доме пользователя и вставьте в него наш скрипт.

     mkdir ~mybackup/bin mv mymysqldump ~mybackup/bin 

    Теперь вы можете запустить скрипт оболочки, чтобы проверить его:

     sh ~mybackup/bin/mymysqldump 

    Теперь создайте cron-файл для этого пользователя:

     crontab -u mybackup @daily ~mybackup/bin/mymysqldump 

    Это должно быть так.

    Скрипт выглядит очень слабым IMHO. Вы должны рассмотреть возможность использования mysqldump, который он доступен в вашей системе.

    Обновить

    Основной командной строкой будет:

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

    Вы можете протестировать mysqldump на вашем локальном компьютере и, как только вы довольны результатами, либо создайте сценарий оболочки, либо добавьте его непосредственно в качестве задачи cron.

    Используйте функцию mysql_error (), чтобы узнать, о чем говорит MySQL.

    Вы должны убедиться, что mysql_query сначала не возвращает поток. Попробуй это:

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