我怎样才能绕过MySQL的Errcode 13与SELECT INTO OUTFILE?

我正在尝试使用MySQL SELECT INTO OUTFILE语句将表的内容转储到csv文件。 如果我做:

SELECT column1, column2 INTO OUTFILE 'outfile.csv' FIELDS TERMINATED BY ',' FROM table_name; 

outfile.csv将在服务器上的这个数据库的文件存储在同一个目录下被创build。

但是,当我将我的查询更改为:

 SELECT column1, column2 INTO OUTFILE '/data/outfile.csv' FIELDS TERMINATED BY ',' FROM table_name; 

我得到:

 ERROR 1 (HY000): Can't create/write to file '/data/outfile.csv' (Errcode: 13) 

Errcode 13是一个权限错误,但即使我将/ data的所有权更改为mysql:mysql,并给予它777权限,我也可以得到它。 MySQL以用户“mysql”运行。

奇怪的是我可以在/ tmp中创build文件,而不是在我试过的任何其他目录下,即使设置了权限,以使用户mysql应该能够写入目录。

这是在Ubuntu上运行的MySQL 5.0.75。

Ubuntu的哪个特定版本是这个,并且是这个Ubuntu服务器版本?

最近的Ubuntu服务器版本(如10.04)与AppArmor一起提供,MySQL的configuration文件默认情况下可能处于强制模式。 你可以通过像这样执行sudo aa-status来检查:

 # sudo aa-status 5 profiles are loaded. 5 profiles are in enforce mode. /usr/lib/connman/scripts/dhclient-script /sbin/dhclient3 /usr/sbin/tcpdump /usr/lib/NetworkManager/nm-dhcp-client.action /usr/sbin/mysqld 0 profiles are in complain mode. 1 processes have profiles defined. 1 processes are in enforce mode : /usr/sbin/mysqld (1089) 0 processes are in complain mode. 

如果强制模式中包含mysqld,则可能是拒绝写入的人。 当AppArmor阻止写入/访问时,条目也将写入/var/log/messages 。 你可以做的是编辑/etc/apparmor.d/usr.sbin.mysqld并在底部附近添加/data//data/* ,如下所示:

 ... /usr/sbin/mysqld { ... /var/log/mysql/ r, /var/log/mysql/* rw, /var/run/mysqld/mysqld.pid w, /var/run/mysqld/mysqld.sock w, **/data/ r, /data/* rw,** } 

然后使AppArmor重新加载configuration文件。

 # sudo /etc/init.d/apparmor reload 

警告:上面的更改将允许MySQL读取和写入/ data目录。 我们希望你已经考虑过这个安全问题。

Ubuntu使用AppArmor,这是什么阻止你访问/ data /。 Fedora使用selinux,这将阻止在RHEL / Fedora / CentOS机器上。

修改AppArmor以允许MySQL访问/ data /执行以下操作:

sudo gedit /etc/apparmor.d/usr.sbin.mysqld

在目录列表中的任何位置添加此行:

/data/ rw,

然后做一个:

sudo /etc/init.d/apparmor restart

另一个选项是完全禁用MySQL的AppArmor,这是不build议的

sudo mv /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/

不要忘记重新启动apparmor:

sudo /etc/init.d/apparmor restart

我知道你说过,你已经设置了权限设置为777,但是因为我有一个证据,对我来说这是一个权限问题,我正在发布我正在运行的希望它可以帮助。 这是我的经验:

 tmp $ pwd /Users/username/tmp tmp $ mkdir bkptest tmp $ mysqldump -u root -T bkptest bkptest mysqldump: Got error: 1: Can't create/write to file '/Users/username/tmp/bkptest/people.txt' (Errcode: 13) when executing 'SELECT INTO OUTFILE' tmp $ chmod a+rwx bkptest/ tmp $ mysqldump -u root -T bkptest bkptest tmp $ ls bkptest/ people.sql people.txt tmp $ 

MySQL在这里变得很愚蠢。 它试图在/ tmp / data /下创build文件。所以你可以做的是以下几点:

 mkdir /tmp/data mount --bind /data /tmp/data 

然后尝试您的查询。 经过几个小时的debugging问题后,这工作对我来说。

你可以这样做 :

 mysql -u USERNAME --password=PASSWORD --database=DATABASE --execute='SELECT `FIELD`, `FIELD` FROM `TABLE` LIMIT 0, 10000 ' -X > file.xml 

有些事情要尝试:

  • secure_file_priv系统variables集? 如果是,则必须将所有文件写入该目录。
  • 确保文件不存在 – MySQL将只创build新文件,不会覆盖现有的文件。

这个问题一直困扰着我很久。 我注意到这个讨论并没有指出RHEL / Fecora上的解决scheme。 我正在使用RHEL,而且在Ubuntu上找不到与AppArmer相对应的configuration文件,但是通过使目录PATH中的EVERY目录可读并且可以通过mysql访问,我解决了我的问题。 例如,如果您创build一个目录/ tmp,则以下两个命令使SELECT INTO OUTFILE能够输出.sql和.sql文件

 chown mysql:mysql /tmp chmod a+rx /tmp 

如果您在主目录/ home / tom中创build目录,则必须对/ home和/ home / tom执行此操作。

在我的情况下,解决scheme是使目录path中的每个目录都可读并且可以通过mysql访问( chmod a+rx )。 该目录仍由命令行中的相对path指定。

 chmod a+rx /tmp chmod a+rx /tmp/migration etc. 

我遇到了同样的问题。 我的问题是我试图转储到的目录没有mysqld进程的写权限。 最初的sql转储会写出来,但写入csv / txt文件将失败。 看起来,sql dump作为当前用户运行,并且转换为csv / txt作为运行mysqld的用户运行。 所以这个目录需要两个用户的写权限。

我有同样的问题,我通过以下步骤解决了这个问题:

  • 操作系统:Ubuntu 12.04
  • 灯安装
  • 假设你的目录保存输出文件是:/ var / www / csv /

在terminal上执行以下命令并使用gedit编辑器编辑该文件以将您的目录添加到输出文件。

sudo gedit /etc/apparmor.d/usr.sbin.mysqld

  • 现在文件将在编辑器中打开,请在那里添加您的目录

    / var / www / csv / * rw,

  • 同样我已经添加在我的文件中,如下图所示:

在这里输入图像描述

执行下一条命令重启服务:

sudo /etc/init.d/apparmor restart

例如,我执行以下查询到phpmyadmin查询生成器来输出CSV文件中的数据

 SELECT colName1, colName2,colName3 INTO OUTFILE '/var/www/csv/OUTFILE.csv' FIELDS TERMINATED BY ',' FROM tableName; 

它成功完成并将所有选定列的行写入OUTPUT.csv文件…

您需要提供绝对path,而不是相对path。

提供您要写入的/ data目录的完整path。

Ubuntu使用SELinux吗? 检查是否已启用并执行。 /var/log/audit/audit.log可能是有帮助的(如果这是Ubuntu的支持,那就是RHEL / Fedora的位置)。

我在CentOs 6.7上遇到了同样的问题。在我的情况下,所有的权限都被设置了,但仍然出现了错误。 问题是SE Linux处于“执行”模式。

我使用命令sudo setenforce 0将其切换为“宽容”

然后,一切都为我工作。