Как я могу обойти MySQL Errcode 13 с помощью SELECT INTO OUTFILE?

Я пытаюсь сбросить содержимое таблицы в файл csv, используя инструкцию MySQL SELECT INTO OUTFILE. Если я это сделаю:

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 мог писать в каталог.

Это MySQL 5.0.75, работающий на Ubuntu.

Ответ 1

Какая конкретная версия Ubuntu это и является ли это версией сервера Ubuntu?

Недавние версии Ubuntu Server Edition (например, 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. Мы надеемся, что вы уже рассмотрели последствия этой проблемы для безопасности.

Ответ 2

Ubuntu использует AppArmor, и это то, что препятствует доступу /data/. Fedora использует selinux, и это предотвратит это на машине RHEL/Fedora/CentOS.

Чтобы изменить AppArmor, чтобы MySQL мог получить доступ/данные/выполнить следующие действия:

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

добавить эту строку в любом месте списка каталогов:

/data/ rw,

то выполните a:

sudo /etc/init.d/apparmor restart

Другой вариант - отключить AppArmor для mysql в целом, это НЕ РЕКОМЕНДУЕТСЯ:

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

Не забудьте перезапустить apparmor:

sudo /etc/init.d/apparmor restart

Ответ 3

Я знаю, что вы сказали, что пытались уже устанавливать разрешения для 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 $ 

Ответ 4

MySQL здесь становится глупым. Он пытается создать файлы под /tmp/data/.... Так что вы можете сделать следующее:

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

Затем попробуйте свой запрос. Это помогло мне после нескольких часов отладки проблемы.

Ответ 5

Вы можете сделать это:

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

Ответ 6

Некоторые вещи, которые нужно попробовать:

  • - это системная переменная secure_file_priv? Если это так, все файлы должны быть записаны в этот каталог.
  • убедитесь, что файл не существует. MySQL будет создавать только новые файлы, а не перезаписывать существующие.

Ответ 7

Эта проблема беспокоила меня в течение длительного времени. Я заметил, что это обсуждение не указывает на решение RHEL/Fecora. Я использую RHEL, и я не нахожу файлы конфигурации, соответствующие AppArmer на Ubuntu, но я решил свою проблему, создав каталог EVERY в каталоге PATH, доступном для чтения и доступном для mysql. Например, если вы создаете каталог /tmp, следующие две команды делают SELECT INTO OUTFILE способным выводить файл .sql AND.sql

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

Если вы создаете каталог в своем домашнем каталоге /home/tom, вы должны сделать это как для /home, так и для home/tom.

Ответ 8

В моем случае решение заключалось в том, чтобы сделать каждый каталог в пути каталога доступным и доступным с помощью mysql (chmod a+rx). Каталог по-прежнему указывал его относительный путь в командной строке.

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

Ответ 9

Я столкнулся с этой проблемой. Моя проблема была в каталоге, который я пытался сбросить, не имел разрешения на запись для процесса mysqld. Первоначальный дамп sql будет выписываться, но запись файла csv/txt завершится с ошибкой. Похоже, что дамп sql работает как текущий пользователь, а преобразование в csv/txt запускается как пользователь, на котором запущен mysqld. Таким образом, директориям нужны права на запись для обоих пользователей.

Ответ 10

У меня такая же проблема, и я исправил эту проблему, выполнив следующие шаги:

  • Операционная система: ubuntu 12.04
  • установлена ​​лампа
  • Предположим, что ваш каталог для сохранения выходного файла:/var/www/csv/

Выполните следующую команду на терминале и отредактируйте этот файл с помощью редактора 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...

Ответ 11

Вам необходимо указать абсолютный путь, а не относительный путь.

Укажите полный путь к директории /data, которую вы пытаетесь записать.

Ответ 12

Использует ли Ubuntu SELinux? Проверьте, включено ли это и принудительно. /var/log/audit/audit.log может быть helpul (если там, где Ubuntu придерживается его), что местоположение RHEL/Fedora).

Ответ 13

У меня была та же проблема на CentOs 6.7 В моем случае все разрешения были установлены, и все же произошла ошибка. Проблема заключалась в том, что SE Linux находился в режиме "принудительного исполнения".

Я переключил его на "разрешающий", используя команду sudo setenforce 0

Тогда все сработало для меня.