使用PHP进行mysqldump

14

我有一个PHP脚本,需要传递远程服务器的MySQL连接细节,并且我想要它执行一个mysqldump命令。为了做到这一点,我正在使用php的exec()函数:

<?php
exec("/usr/bin/mysqldump -u mysql-user -h 123.145.167.189 -pmysql-pass database_name > /path-to-export/file.sql", $output);
?>
当正确的登录详细信息传递给它时,它将完美地工作。 然而,我在检查它是否按预期执行以及如果它没有按预期执行则找出原因方面遇到了麻烦。 $output 数组返回为空,而当我直接在命令行上运行命令时,会打印出一条消息告诉我登录失败了。我想捕获这样的错误消息并显示它们。有什么想法吗?
6个回答

17

您应该检查&$return_var参数,它是exec函数的第三个参数。

$return_var = NULL;
$output = NULL;
$command = "/usr/bin/mysqldump -u mysql-user -h 123.145.167.189 -pmysql-pass database_name > /path-to-export/file.sql";
exec($command, $output, $return_var);

在Unix中的惯例是,当出现错误时,进程返回除0以外的任何值

因此,您可以:

if($return_var) { /* there was an error code: $return_var, see the $output */ }

1
这是链接:http://php.net/manual/en/function.exec.php,我认为更好的说法是:“按照Unix的惯例,当出现问题时,进程返回除0以外的任何内容”。 :) - Dany Khalife
有没有办法知道$return_var的每个值代表什么,这样我就可以将其翻译成有意义的错误消息?我猜对于每个命令都不同。 - Ross McLellan
如果$return_var不等于零,则$output必须具有错误代码,因为程序将错误写入stderr,而不是您重定向到文件的stdout。'if($return_var) { die($output); }' - Burak Tamtürk
1
不幸的是不行。是的,$return_var 返回一个正整数,我现在正在使用它来确定命令是否成功执行或者是否出了问题,这至少给了我们一些想法。然而,使用 MySQLdump(还没有注意到我们以同样方式运行的其他命令)$output 是一个空数组。当直接在命令行上运行完全相同的命令时,它会给我们一个相关的错误,告诉我们哪些权限是错误或者缺失的。 - Ross McLellan
1
@RossMcLellan:看看这个问题 - Fabio Mora

8
我找到的解决方案是在子shell中运行命令,然后将stderr输出到stdout (2>&1)。这样,如果有错误消息,$output变量就会被填充。
例如:
exec("(mysqldump -uroot -p123456 my_database table_name > /path/to/dump.sql) 2>&1", $output, $exit_status);

var_dump($exit_status); // (int) The exit status of the command (0 for success, > 0 for errors)
echo "<br />";
var_dump($output); // (array) If exit status != 0 this will handle the error message. 

结果:

整数(6)

数组(1) { [0]=> 字符串(46) "mysqldump: 找不到表: "table_name"" }

希望能帮到你!


1
不确定为什么这不是正确的答案。简单、直接的代码可以得到所需的信息! - globalSchmidt

4

我正在寻找完全相同的解决方案,然后我记得我几年前已经解决了这个问题,但是已经忘记了。

由于这个页面在谷歌搜索中排名很高,所以我来分享一下我的解决方法:

<?php
define("BACKUP_PATH", "/full/path/to/backup/folder/with/trailing/slash/");

$server_name   = "your.server.here";
$username      = "your_username";
$password      = "your_password";
$database_name = "your_database_name";
$date_string   = date("Ymd");

$cmd = "mysqldump --hex-blob --routines --skip-lock-tables --log-error=mysqldump_error.log -h {$server_name} -u {$username} -p{$password} {$database_name} > " . BACKUP_PATH . "{$date_string}_{$database_name}.sql";

$arr_out = array();
unset($return);

exec($cmd, $arr_out, $return);

if($return !== 0) {
    echo "mysqldump for {$server_name} : {$database_name} failed with a return code of {$return}\n\n";
    echo "Error message was:\n";
    $file = escapeshellarg("mysqldump_error.log");
    $message = `tail -n 1 $file`;
    echo "- $message\n\n";
}
?>

我总是忘记mysqldump的--log-error=[/path/to/error/log/file]部分!

这个选项可以将错误日志输出到指定的文件路径,方便我们查找问题。


我尝试了这个答案,但无法使其工作。我正在运行本地的WAMP服务器,我运行的目录是www/test/index.php。我已将BACKUP_PATH设置为“/test/”,并创建了一个名为“mysqlydump_error.log”的文件,并将其放置在“test”目录中。我收到了错误消息,但它没有显示错误,错误日志也为空。我确保我的用户也有权限。求助? - Andrew Fox
现在我可以让备份文件出现了,但是它是空白的。 - Andrew Fox
@AndrewFox,Rick说:“路径不应该是/www/test/或者可能是/var/www/test/,这取决于你的配置。从你想要放置日志文件的目录执行pwd命令,并将其与尾随斜杠一起放入其中。” - Nathan Tuggy
我现在已经确定了路径,因为文件按预期出现了,但是文件是空的。 - Andrew Fox
我在CodeIgniter中使用了上述解决方案,但是出现了错误:mysqldump: Got error: 1045: Access denied for user 'username'@'localhost' (using password: YES) when trying to connect. - hrishi

4

因为这行代码将标准输出重定向到 > /path-to-export/file.sql,所以请尝试以下操作:

<?php 
exec("/usr/bin/mysqldump -u mysql-user -h 123.145.167.189 -pmysql-pass database_name", $output);
/* $output will have sql backup, then save file with these codes */
$h=fopen("/path-to-export/file.sql", "w+");
fputs($h, $output);
fclose($h);
?> 

如果你问我,这有点牵强。 - Dany Khalife
我的母语是土耳其语,与英语相去甚远,这就阻止我写出有力的答案。他说 $output 是空的,我解释了它为空的原因。$output 是 stdout ,如果他使用 ">" (意思是将 stdout 重定向到文件),他将没有输出,这是完全合理的。但是还有 stderr,如果存在错误,$output 将在此情况下报告错误,即使他已将 stdout 重定向到文件中。顺便说一句,他问了 $output。 - Burak Tamtürk
是的,我完全同意,我只是想说有一种更简单的方法来做这件事 :) - Dany Khalife
谢谢。我喜欢这个想法。不幸的是,我刚刚测试了一下,即使没有 > /path-to-export/file.sql 重定向输出,它也不会将错误消息返回到 $output 变量中。 - Ross McLellan
$output 只会包含 mysqldump 的输出,而不是特殊消息。如果您想使用我的解决方案,必须检查 $output 是否有特殊错误。如果出现错误,mysqldump 将返回一行指示存在错误的字符串。您需要解析此字符串。在其他解决方案中,如果 $return_var 不等于 0,则输出只会有 stderr,这意味着错误描述。 - Burak Tamtürk
是的,stdout 已经被重定向到文件,但 OP 希望从命令获取 stderr,而 exec 无法获取。 - dmnc

1
由于exec()只获取重定向到文件的stdout,因此我们在文件中只有部分或缺失的结果,并且我们不知道原因。我们必须从stderr获取消息,而exec()无法做到这一点。有几种解决方案,所有解决方案都已经被找到,这只是一个总结。
  1. Jon的解决方案:记录mysqldump的错误并单独处理(不能适用于每个命令)。
  2. 将输出重定向到不同的文件,例如mysqldump ... 2> error.log 1> dump.sql,并像前一个解决方案一样单独读取错误日志。
  3. JazZ的解决方案:将转储写为子shell,并将子shell的stderr重定向到可以由php exec()放入$output变量的stdout中。
  4. Pascal的解决方案:最好使用proc_open()而不是exec(),因为我们可以直接从管道中获取stdoutstderr

-1
请写下面的代码以获取数据库导出为.sql文件。
<?php exec('mysqldump --user=name_user --password=password_enter --host=localhost database_name > filenameofsql.sql'); ?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接