116

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

4

13 回答 13

193

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

最近的 Ubuntu 服务器版本(例如 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 包含在强制模式中,那么它可能是拒绝写入的那个。/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 目录。我们希望您已经考虑过这对安全的影响。

于 2010-06-07T02:23:30.833 回答
18

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

于 2010-06-07T02:41:30.297 回答
15

我知道您说过您已经尝试将权限设置为 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 $ 
于 2010-05-06T20:16:41.287 回答
7

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

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

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

于 2012-06-18T22:00:34.033 回答
6

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

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

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

于 2012-02-21T01:17:15.487 回答
6

你可以这样做 :

mysql -u USERNAME --password=PASSWORD --database=DATABASE --execute='SELECT `FIELD`, `FIELD` FROM `TABLE` LIMIT 0, 10000 ' -X > file.xml
于 2014-03-19T09:02:18.090 回答
4

一些事情要尝试:

  • secure_file_priv系统变量设置了吗?如果是,则必须将所有文件写入该目录。
  • 确保文件不存在 - MySQL 只会创建新文件,不会覆盖现有文件。
于 2010-06-04T05:04:39.763 回答
3

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

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

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

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

于 2015-09-16T08:00:05.627 回答
2

就我而言,解决方案是使目录路径中的每个目录都可以通过mysql( chmod a+rx) 读取和访问。该目录仍由其在命令行中的相对路径指定。

chmod a+rx /tmp
chmod a+rx /tmp/migration
etc.
于 2012-02-10T15:26:01.260 回答
2

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

于 2013-02-01T17:24:04.880 回答
1

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

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

于 2010-05-06T19:07:10.930 回答
1

Ubuntu 使用 SELinux 吗?检查它是否已启用并强制执行。/var/log/audit/audit.log 可能会有所帮助(如果那是 Ubuntu 坚持的地方——那是 RHEL/Fedora 的位置)。

于 2010-06-07T02:30:01.513 回答
0

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

我使用命令将其切换为“允许”sudo setenforce 0

然后一切都为我解决了。

于 2015-11-25T06:55:00.810 回答