114 votes

Comment contourner l'Errcode 13 de MySQL avec SELECT INTO OUTFILE ?

J'essaie de vider le contenu d'une table dans un fichier csv à l'aide d'une instruction MySQL SELECT INTO OUTFILE. Si je le fais :

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

outfile.csv sera créé sur le serveur dans le même répertoire que celui où sont stockés les fichiers de cette base de données.

Cependant, lorsque je change ma requête en :

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

J'ai compris :

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

L'Errcode 13 est une erreur de permissions, mais je l'obtiens même si je change la propriété de /data en mysql:mysql et lui donne des permissions 777. MySQL est exécuté en tant qu'utilisateur "mysql".

Bizarrement, je peux créer le fichier dans /tmp, mais pas dans les autres répertoires que j'ai essayés, même avec des autorisations définies de telle sorte que l'utilisateur mysql devrait pouvoir écrire dans le répertoire.

Il s'agit de MySQL 5.0.75 fonctionnant sur Ubuntu.

187voto

Vin-G Points 2441

De quelle version particulière d'Ubuntu s'agit-il et s'agit-il d'Ubuntu Server Edition ?

Les éditions récentes d'Ubuntu Server (comme la 10.04) sont livrées avec AppArmor et le profil de MySQL peut être en mode d'application par défaut. Vous pouvez le vérifier en exécutant sudo aa-status comme ça :

# 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 inclus dans le mode "enforce", alors c'est probablement lui qui refuse l'écriture. Les entrées seraient également écrites dans /var/log/messages quand AppArmor bloque les écritures/accès. Ce que vous pouvez faire, c'est éditer /etc/apparmor.d/usr.sbin.mysqld et ajouter /data/ y /data/* près du fond comme ça :

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

Et ensuite faire en sorte que AppArmor recharge les profils.

# sudo /etc/init.d/apparmor reload

ATTENTION : la modification ci-dessus permettra à MySQL de lire et d'écrire dans le répertoire /data. Nous espérons que vous avez déjà considéré les implications de sécurité de ceci.

17voto

Rook Points 34698

Ubuntu utilise AppArmor et c'est ce qui vous empêche d'accéder à /data/. Fedora utilise selinux et cela empêcherait cela sur une machine RHEL/Fedora/CentOS.

Pour modifier AppArmor afin de permettre à MySQL d'accéder à /data/, procédez comme suit :

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

ajouter cette ligne n'importe où dans la liste des répertoires :

/data/ rw,

puis faites un :

sudo /etc/init.d/apparmor restart

Une autre option consiste à désactiver complètement AppArmor pour mysql. NON RECOMMANDÉ :

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

N'oubliez pas de redémarrer Apparmor :

sudo /etc/init.d/apparmor restart

14voto

spaceCamel Points 826

Je sais que vous avez dit que vous avez déjà essayé de mettre les permissions à 777, mais comme j'ai une preuve que pour moi c'était un problème de permission, je poste ce que j'ai exactement exécuté en espérant que cela puisse aider. Voici mon expérience :

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 $

7voto

vimdude Points 988

MySQL devient stupide ici. Il essaie de créer des fichiers sous /tmp/data/..... Donc ce que vous pouvez faire est le suivant :

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

Alors essayez votre requête. Cela a fonctionné pour moi après des heures de débogage du problème.

5voto

fanchyna Points 519

Ce problème me préoccupe depuis longtemps. J'ai remarqué que cette discussion n'indique pas la solution sur RHEL/Fecora. J'utilise RHEL et je ne trouve pas les fichiers de configuration correspondant à AppArmer sur Ubuntu, mais j'ai résolu mon problème en rendant TOUS les répertoires du PATH lisibles et accessibles par mysql. Par exemple, si vous créez un répertoire /tmp, les deux commandes suivantes rendent SELECT INTO OUTFILE capable de sortir le fichier .sql ET .sql

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

Si vous créez un répertoire dans votre répertoire personnel /home/tom, vous devez le faire à la fois pour /home et /home/tom.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X