代码之家  ›  专栏  ›  技术社区  ›  SCdF

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

  •  113
  • SCdF  · 技术社区  · 16 年前

    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 and 给它777个权限。MySQL正在以用户“MySQL”的身份运行。

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

    13 回复  |  直到 15 年前
        1
  •  193
  •   Vin-G    9 年前

    最近的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
    

        2
  •  18
  •   rook    16 年前

    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

    另一个选择是完全禁用AppArmor for mysql,这是 :

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

    sudo/etc/init.d/apparmor重启

        3
  •  14
  •   acorello    16 年前

    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 $ 
    
        4
  •  7
  •   vimdude    13 年前

    MySQL在这里越来越蠢了。它试图在/tmp/data/…下创建文件。。。。所以你可以做以下几点:

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

        5
  •  6
  •   fanchyna    14 年前

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

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

        6
  •  6
  •   Farvardin kiran    11 年前

    您可以这样做:

    mysql -u USERNAME --password=PASSWORD --database=DATABASE --execute='SELECT `FIELD`, `FIELD` FROM `TABLE` LIMIT 0, 10000 ' -X > file.xml
    
        7
  •  4
  •   mdma    16 年前

    一些尝试:

    • secure_file_priv 系统变量集?如果是,则所有文件都必须写入该目录。
    • 确保文件不存在-MySQL只会创建新文件,而不会覆盖现有文件。
        8
  •  3
  •   Sunny S.M    10 年前

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

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

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

      /var/www/csv/*rw,

    enter image description here

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

    sudo/etc/init.d/apparmor重启

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

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

        9
  •  2
  •   Alsciende    14 年前

    在我的例子中,解决方案是使目录路径中的每个目录都可读并可被 mysql ( chmod a+rx ). 目录仍由其在命令行中的相对路径指定。

    chmod a+rx /tmp
    chmod a+rx /tmp/migration
    etc.
    
        10
  •  2
  •   Matthew McMillan    13 年前

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

        11
  •  1
  •   Ike Walker    16 年前

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

        12
  •  1
  •   Charles    16 年前

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

        13
  •  0
  •   Stefan Bicher    10 年前

    我用命令把它改成了“允许的” sudo setenforce 0