如何使用SELECT INTO OUTFILE绕过MySQL Errcode 13?

时间:2010-05-06 18:00:25

标签: mysql sql into-outfile

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

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

outfile.csv将在服务器上创建,该数据库的文件存储在同一目录中。

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

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中创建文件,只是在我尝试的任何其他目录中都没有,即使权限设置使得用户mysql应该能够写入目录。

这是在Ubuntu上运行的MySQL 5.0.75。

13 个答案:

答案 0 :(得分:185)

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

最近的Ubuntu Server Editions(例如10.04)附带AppArmor,MySQL的配置文件默认情况下可能处于强制模式。你可以像这样执行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重新加载配置文件。

# sudo /etc/init.d/apparmor reload

警告:上述更改将允许MySQL读取/写入/ data目录。我们希望您已经考虑过这一点的安全隐患。

答案 1 :(得分:17)

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,这是 NOT RECOMMENDED

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

不要忘记重启apparmor:

sudo /etc/init.d/apparmor restart

答案 2 :(得分:14)

我知道你说过你已经尝试过设置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 $ 

答案 3 :(得分:6)

MySQL在这里变得愚蠢。它尝试在/ tmp / data / ....下创建文件。所以你可以做的是:

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

然后尝试您的查询。经过几个小时的调试后,这对我有用。

答案 4 :(得分:4)

有些事情要尝试:

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

答案 5 :(得分:4)

这个问题困扰了我很长一段时间。我注意到这个讨论没有指出RHEL / Fecora上的解决方案。我正在使用RHEL而且我没有在Ubuntu上找到与AppArmer相对应的配置文件,但是我通过使目录PATH中的每个目录都可以被mysql读取和访问来解决了我的问题。例如,如果创建目录/ tmp,则以下两个命令使SELECT INTO OUTFILE能够输出.sql和.sql文件

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

如果在主目录/ home / tom中创建目录,则必须同时为/ home和/ home / tom执行此操作。

答案 6 :(得分:4)

你可以这样做:

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

答案 7 :(得分:3)

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

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

在终端上执行以下命令,并使用gedit编辑器编辑此文件,将目录添加到输出文件中。

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

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

    / var / www / csv / * rw,

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

enter image description here

  

执行下一个命令以重启服务:

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文件...

答案 8 :(得分:2)

就我而言,解决方案是让目录路径中的每个目录都可由mysqlchmod a+rx)读取和访问。该目录仍由命令行中的相对路径指定。

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

答案 9 :(得分:2)

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

答案 10 :(得分:1)

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

提供您尝试写入的/ data目录的完整路径。

答案 11 :(得分:1)

Ubuntu是否使用SELinux?检查它是否已启用并强制执行。 /var/log/audit/audit.log可能是helpul(如果那是Ubuntu坚持的地方 - 那就是RHEL / Fedora的位置)。

答案 12 :(得分:0)

我在CentOs 6.7上遇到了同样的问题 在我的情况下,所有权限都已设置,但仍然发生错误。问题是SE Linux处于"强制执行"。

模式

我把它改为" permissive"使用命令sudo setenforce 0

然后一切都适合我。