2010-05-06 31 views
108

Estoy tratando de volcar el contenido de una tabla en un archivo csv usando una instrucción MySQL SELECT INTO OUTFILE. Si hago:¿Cómo puedo evitar MySQL Errcode 13 con SELECT INTO OUTFILE?

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

outfile.csv se crea en el servidor en el mismo directorio de archivos de esta base de datos se almacenan en

Sin embargo, cuando cambio mi consulta a:.

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

me sale:

ERROR 1 (HY000): Can't create/write to file '/data/outfile.csv' (Errcode: 13) 

Errcode 13 es un error de permisos, pero lo consigo, incluso si cambio de titularidad de/datos a mysql: mysql y darle 777 permisos. MySQL se ejecuta como usuario "mysql".

Extrañamente puedo crear el archivo en/tmp, pero no en ningún otro directorio que haya probado, incluso con permisos establecidos de tal manera que el usuario mysql debería poder escribir en el directorio.

Esta es MySQL 5.0.75 corriendo en Ubuntu.

+3

Como el 13 es un error del sistema, probablemente esto no sea así, pero hay una configuración mySQL que limita INTO OUTFILE a un directorio: http://dev.mysql.com/doc/refman/5.0/en/server -system-variables.html # sysvar_secure_file_priv tal vez vale la pena echar un vistazo si está configurado en '/ tmp'. –

+0

Esa variable está en blanco en mi instalación, lo que según ese documento significa que mis directorios de salida no deberían estar limitados. –

Respuesta

180
Qué determinada versión de Ubuntu

es esto y es este servidor Edición de Ubuntu?

recientes ediciones de Ubuntu Server (por ejemplo, 10,04) buque con un perfil de AppArmor y de MySQL podría ser en modo obligatorio por defecto. Esto se puede comprobar mediante la ejecución de sudo aa-status así:

# 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. 

Si mysqld está incluido en modo de aplicación, entonces es probable que el negar la escritura. Las entradas también se escribirían en /var/log/messages cuando AppArmor bloquee las escrituras/accesos. Lo que puede hacer es editar y añadir /etc/apparmor.d/usr.sbin.mysqld/data/ y /data/* cerca de la parte inferior de este modo:

... 
/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,** 
} 

y después hacen que AppArmor vuelva a cargar los perfiles.

# sudo /etc/init.d/apparmor reload 

ADVERTENCIA: el cambio anterior permitirá a MySQL leer y escribir en el directorio/data.Esperamos que ya haya considerado las implicaciones de seguridad de esto.

+0

Esto era Ubuntu 9.04, pero AppArmor estaba negando la escritura. Muchas gracias, esto me solucionó esto. –

+0

feliz de ayudar :) –

+0

omg- ¡gracias! estado atascado en esto por mucho tiempo. – therealsix

1

es necesario proporcionar una ruta absoluta, no una ruta relativa.

proporcionar la ruta completa al directorio/datos que está intentando escribir.

+0

Eso parece un camino absoluto para mí. ¿No lo es? –

+0

Es una ruta absoluta, sí. –

+2

Pruebe esto como el usuario de mysql para verificar que puede crear el archivo fuera de mysql: 'touch/data/outfile.csv' –

13

Sé que dijo que ya ha probado la configuración de permisos a 777, pero como tengo una evidencia de que para mí fue un problema de permisos les dejo lo que exactamente correr con la esperanza de que pueda ayudar. Aquí está mi experiencia:

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 $ 
+0

mí @ servidor:/data $ pwd /datos mí @ servidor:/datos $ ls -al total de 60 ... drwxrwxrwx 2 mysql 4096 2010-05-06 16:27 dumptest mí @ servidor:/data $ mysqldump -u dbuser -p -T dumptest -B nombre_bd -tables test Ingrese la contraseña: mysqldump: Error obtenido: 1: No se puede crear/escribir en el archivo '/data/dumptest/test.txt' (Errcode: 13) al ejecutar 'SELECT INTO OUTFILE' me @ server:/data $ sudo chmod a + rwx dumptest/ me @ server:/data $ mysqldump -u dbuser -p -T dumptest -B db_name --tables test Introduzca la contraseña: mysqldump: Obtuvo el error: 1: (mismo error) –

+0

Oy, bueno, no se dio cuenta de que los comentarios no se formatearían, sino que se verificaron de varias maneras diferentes. Primero con el directorio de destino propiedad de mysql: mysql, luego con el directorio de destino propiedad del usuario en el que estaba ejecutando el comando de volcado, ambas formas todavía me dan el mismo error de permisos. –

+0

Para el registro, esto funcionó para mí a pesar de haber cambiado los permisos de apparmor – Alex

4

Algunas cosas para probar:

  • es el sistema de secure_file_priv conjunto de variables? Si es así, todos los archivos se deben escribir en ese directorio.
  • asegúrese de que el archivo no exista: MySQL solo creará nuevos archivos, no sobrescribirá los existentes.
+1

También iría por secure_file_priv. Si el archivo ya existe, el mensaje de error es diferente (no errcode 13). –

+0

secure_file_priv no está configurado actualmente, por lo que entiendo que eso significa que no debería estar limitado en cuanto a dónde puedo escribir archivos. ¿Lo estoy malinterpretando y necesito configurarlo explícitamente como '/' si quiero poder escribir en cualquier parte del sistema de archivos? –

+0

Además, estoy comprobando que el archivo no existe antes de ejecutar la consulta. –

1

¿Ubuntu usa SELinux? Verifique si está habilitado y se aplica. /var/log/audit/audit.log puede ser de ayuda (si es ahí donde lo pega Ubuntu, esa es la ubicación de RHEL/Fedora).

17

Ubuntu usa AppArmor y eso es lo que le impide acceder a/data /. Fedora usa selinux y eso evitaría esto en una máquina RHEL/Fedora/CentOS.

Para modificar AppArmor para permitir MySQL para acceder a/data/hacer el seguimiento:

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

añadir esta línea en cualquier lugar de la lista de directorios:

/data/ rw,

luego hacer una :

sudo /etc/init.d/apparmor restart

Otra opción es desactivar AppArmor para MySQL por completo, esto se NO RECOMENDADO:

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

No olvide reiniciar apparmor:

sudo /etc/init.d/apparmor restart

+0

Para desactivar realmente apparmor para mysql que necesitaba hacer: https://www.cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands/ –

2

En mi caso, la solución era hacer que todos los directorios en la ruta del directorio fueran legibles y accesibles al mysql (chmod a+rx). El directorio todavía estaba especificado por su ruta relativa en la línea de comando.

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

Este problema me ha estado molestando durante mucho tiempo. Noté que esta discusión no señala la solución en RHEL/Fecora. Estoy usando RHEL y no encuentro los archivos de configuración correspondientes a AppArmer en Ubuntu, pero resolví mi problema al hacer que TODOS los directorios sean legibles y accesibles por mysql. Por ejemplo, si crea un directorio/tmp, los siguientes dos comandos hacen SELECT INTO OUTFILE capaz de emitir la .sql y el archivo .sql

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

Si crea un directorio en su directorio/home/tom, debe hacer esto para/home y/home/tom.

+3

Usar/tmp como ejemplo no es bueno idea, y realmente no desea cambiar la propiedad del directorio/tmp (en la mayoría de los casos). – sastorsl

+0

chown resolvió mi vida – adrian4aes

6

MySQL se está poniendo estúpido aquí. Se trata de crear archivos en/tmp/datos/.... Así que lo que puede hacer es la siguiente:

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

Luego probar su consulta. Esto funcionó para mí después de horas de depurar el problema.

+0

Me gusta esta respuesta mejor. Es fácil, funciona, y no requiere que te alarmes con la apparmor.La otra forma de hacerlo utilizando tuberías no funciona bien para grandes exportaciones debido a todo el almacenamiento en búfer que se realiza. –

2

Acabo de encontrarme con este mismo problema. Mi problema era que el directorio en el que intentaba ingresar no tenía permiso de escritura para el proceso de mysqld. El volcado inicial de sql se escribiría pero la escritura del archivo csv/txt fallaría. Parece que el volcado sql se ejecuta como el usuario actual y la conversión a csv/txt se ejecuta como el usuario que ejecuta mysqld. Entonces, el directorio necesita permisos de escritura para ambos usuarios.

4

Usted puede hacer esto:

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

Tengo mismo problema y me fijo este problema siguiendo los pasos:

  • Sistema operativo: Ubuntu 12.04
  • lámpara instalada
  • suponga que su el directorio para guardar el archivo de salida es:/var/www/csv/

Execute following command on terminal and edit this file using gedit editor to add your directory to output file.

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

  • ahora archivo se abrió en el editor favor agregue su directorio no

    /var/www/csv/* rw,

  • del mismo modo que se han añadido en mi archivo, de la siguiente imagen dada:

enter image description here

Execute next command to restart services :

sudo /etc/init.d/apparmor reiniciar

For example I execute following query into phpmyadmin query builder to output data in csv file

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

que se haga con éxito y escribir todas las filas con columnas seleccionadas en un archivo OUTPUT.CSV ...

0

Tuve el mismo problema en un CentOs 6.7 En mi caso, se establecieron todos los permisos y aún se produjo el error. El problema era que el SE Linux estaba en el modo de "hacer cumplir".

me cambiaron a "permisiva" con el comando sudo setenforce 0

Entonces todo salió bien para mí.

Cuestiones relacionadas