如何使用SELECT INTO OUTFILE解决MySQL Errcode 13?


114

我正在尝试使用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。


3
看到13是系统错误,可能不是这样,但是有一个mySQL设置将INTO OUTFILE限制到一个目录:dev.mysql.com/doc/refman/5.0/en/…也许值得一看设置为/tmp
Pekka 2010年

该变量在我的安装中为空,根据该文档,这意味着不应限制我的输出目录。
瑞安·奥尔森

Answers:


189

这是哪个特定的Ubuntu版本,这是Ubuntu Server Edition?

AppArmor附带了最新的Ubuntu Server Edition(例如10.04),默认情况下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包含在强制模式下,则可能是拒绝写入的程序。/var/log/messages当AppArmor阻止写入/访问时,也将写入条目。您可以做的就是编辑/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目录。我们希望您已经考虑了此问题的安全性。


2
我不想指出这一点,但是App Armor不允许这样做是有原因的。MySQL现在可以修改和读取/ data文件夹中的任何内容。只是现在不要被黑客入侵。
瑞安·沃德

2
@Serdar,与发行版一起分发的AppArmor MySQL规则集默认情况下不允许使用。这是有道理的,因为它是全新安装规则的良好基准。我相信我们应该并且可以修改规则集以适应安装后的需求。最初的要求是让MySQL写入特定目录。但是,如果上面还不太明确,则请注意的人请注意以下问题:警告:上面的更改将使MySQL可以读写/ data目录。我们希望您已经考虑了此问题的安全性。
Vin-G

1
伟大的答案!它解决了我的问题,我也试图在任何其他目录中编写。现在,我必须研究所有这些内容!:)了解这一点后,我建议其他人阅读有关apparmor(以及命令aa-status)的信息:en.wikipedia.org/wiki/AppArmor
David L

1
就我而言,这很有帮助: /your/abs/folder/ r, /your/abs/folder/** rwk, }请不要忘记在最后加上逗号!
ACV

1
它可以用/ tmp编写。请改用Windows。Linux很烂
Victor Ionescu

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,这是不推荐的

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

别忘了重启apparmor:

sudo /etc/init.d/apparmor restart


要实际上禁用mysql的apparmor,我需要做: cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands
silver_mx

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 $ 

me @ server:/ data $ pwd / data me @ server:/ data $ ls -al total 60 ... drwxrwxrwx 2 mysql mysql 4096 2010-05-06 16:27 dumptest me @ server:/ data $ mysqldump -u dbuser -p -T dumptest -B db_name --tables test输入密码:mysqldump:得到错误:1:执行“ SELECT INTO”时无法创建/写入文件“ /data/dumptest/test.txt”(错误代码:13) OUTFILE'me @ server:/ data $ sudo chmod a + rwx dumptest / me @ server:/ data $ mysqldump -u dbuser -p -T dumptest -B db_name --tables test输入密码:mysqldump:得到错误:1:(同样的错误)
瑞安·奥尔森

Oy,好吧,我没有意识到注释不会格式化,但是仔细检查了几种不同的方式。首先使用mysql:mysql拥有的目标目录,然后使用我运行转储命令的用户所拥有的目标目录,两种方式仍然给我相同的权限错误。
瑞安·奥尔森

根据记录,尽管更改了Apparmor权限,这对我还是有用的
Alex

我尝试对apparmor进行修改,但没有成功。更改权限“ chmod 777”对我有用!
Sudarshan_SMD 2015年

7

MySQL在这里变得愚蠢。它尝试在/ tmp / data /下创建文件。...因此,您可以执行以下操作:

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

然后尝试查询。经过数小时的调试问题,这对我有用。


我最喜欢这个答案。这很容易,有效,并且不需要您费心。使用管道执行此操作的另一种方法不适用于大型导出,因为已完成所有缓冲。
克里斯·塞琳

6

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

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

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


3
使用/ tmp作为示例不是一个好主意,并且您实际上不想更改/ tmp目录的所有权(在大多数情况下)。
sastorsl

更改/ tmp的所有权很不好,但是在/ tmp内创建一个临时文件夹并chown mysql:mysql解决了我的问题
Samuel Prevost


4

一些尝试:

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

1
我也会去找secure_file_priv。如果该文件已经存在,则错误消息会有所不同(不是errcode 13)。
Xavier Maillard 2010年

目前尚未设置secure_file_priv,因此据我了解,这意味着我不应在哪里写文件受限。我是否误解了这一点,如果我想能够在文件系统上的任何位置进行写操作,是否需要将其显式设置为“ /”之类的东西?
瑞安·奥尔森

另外,在运行查询之前,我正在检查文件是否不存在。
瑞安·奥尔森

感谢您的反馈。根据您的发现,我认为这些建议均不会引起您的问题。
mdma 2010年

3

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

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

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

须藤gedit /etc/apparmor.d/usr.sbin.mysqld

  • 现在将在编辑器中打开文件,请在此处添加目录

    / var / www / csv / * rw,

  • 同样,我在文件中添加了以下图像:

在此处输入图片说明

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

sudo /etc/init.d/apparmor重新启动

例如我执行以下查询到phpmyadmin查询生成器中以在csv文件中输出数据

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

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


2

在我的情况下,解决方案是使目录路径中的每个目录都可被mysqlchmod a+rx)读取和访问。该目录仍由其相对路径在命令行中指定。

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

2

我只是遇到了同样的问题。我的问题是我尝试转储到的目录没有对mysqld进程的写权限。初始sql转储将写出,但csv / txt文件的写操作将失败。看起来sql转储以当前用户身份运行,并且对csv / txt的转换以运行mysqld的用户身份运行。因此,该目录需要两个用户的写权限。


1

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

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


那对我来说似乎是一条绝对的道路。不是吗
Pekka 2010年

2
以mysql用户身份尝试此操作,以验证您可以在mysql之外创建文件:touch /data/outfile.csv
Ike Walker,2010年

1
首先,我无法执行此操作,因为mysql用户的shell设置为/ bin / false,因此无法以mysql身份登录。为了确保这不是问题的根源,我将mysql的shell设置为/ bin / bash,然后将其设置为该用户并触摸了/ data中的文件。该文件已成功创建,由mysql拥有。
瑞安·奥尔森

3
即使帐户使用“禁用”外壳之一,您也可以使用该帐户: su --shell=/bin/sh nameofaccount
Marc B 2010年

谢谢,我当时没意识到。
瑞安·奥尔森

1

Ubuntu是否使用SELinux?检查它是否已启用并强制执行。/var/log/audit/audit.log可能是帮助文件(如果这是Ubuntu粘贴的地方-这是RHEL / Fedora的位置)。


0

我在CentOs 6.7上遇到了相同的问题,在我的情况下,所有权限均已设置,但仍然发生错误。问题是SE Linux处于“强制”模式。

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

然后一切都对我有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.