web-dev-qa-db-fra.com

Comment puis-je contourner le code d'erreur MySQL 13 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 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 dans lequel les fichiers de cette base de données sont stockés.

Cependant, lorsque je modifie ma requête en:

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

Je reçois:

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

Le code d'erreur 13 est une erreur d'autorisations, mais je l'obtiens même si je change de propriétaire de/data en mysql: mysql et lui donne les autorisations 777. MySQL est exécuté en tant qu'utilisateur "mysql".

Étrangement, je peux créer le fichier dans/tmp, mais pas dans un autre répertoire que j'ai essayé, même avec des autorisations définies de telle sorte que l'utilisateur mysql puisse écrire dans le répertoire.

C'est MySQL 5.0.75 qui tourne sur Ubuntu.

114
Ryan Olson

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

Les éditions récentes de Ubuntu Server (telles que 10.04) livrées avec AppArmor et le profil de MySQL sont peut-être en mode d'exécution par défaut. Vous pouvez vérifier cela en exécutant Sudo aa-status ainsi:

# 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 d'application, c'est probablement celui qui refuse l'écriture. Les entrées seraient également écrites en /var/log/messages lorsque AppArmor bloque les écritures/accès. Ce que vous pouvez faire, c'est éditer /etc/apparmor.d/usr.sbin.mysqld et ajouter /data/ et /data/* près du bas, comme ceci:

...  
/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, faites recharger les profils par AppArmor.

# 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à pris en compte les implications de ceci pour la sécurité.

187
Vin-G

Ubuntu utilise AppArmor et c’est ce qui vous empêche d’accéder à/data /. Fedora utilise selinux et cela éviterait 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

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

/data/ rw,

alors faites un:

Sudo /etc/init.d/apparmor restart

Une autre option consiste à désactiver complètement AppArmor pour mysql. NOT RECOMMENDED:

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

17
rook

Je sais que vous avez dit que vous aviez déjà essayé de définir des autorisations sur 777, mais comme j'ai la preuve qu'il s'agissait d'un problème d'autorisation, je publie ce que je lance exactement dans l'espoir 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 $ 
14
basilikode

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

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

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

7
vimdude

Tu peux le faire :

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

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 répertoire PATH lisibles et accessibles par mysql. Par exemple, si vous créez un répertoire/tmp, les deux commandes suivantes permettent à SELECT INTO OUT de générer le fichier .sql AND .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.

5
fanchyna

Quelques choses à essayer:

  • est le secure_file_priv variable système définie? Si c'est le cas, tous les fichiers doivent être écrits dans ce répertoire.
  • assurez-vous que le fichier n'existe pas - MySQL ne créera que les nouveaux fichiers, pas ceux qui seront écrasés.
4
mdma

J'ai le même problème et j'ai résolu ce problème en procédant comme suit:

  • Système d'exploitation: Ubuntu 12.04
  • lampe installée
  • supposons que votre répertoire de sauvegarde du fichier de sortie soit:/var/www/csv /

Exécutez la commande suivante sur le terminal et éditez ce fichier en utilisant l'éditeur gedit pour ajouter votre répertoire au fichier de sortie.

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

  • maintenant le fichier serait ouvert dans l'éditeur s'il vous plaît ajoutez votre répertoire il

    / var/www/csv/* rw,

  • de même, j'ai ajouté dans mon fichier l'image suivante:

enter image description here

Exécutez la commande suivante pour redémarrer les services:

Sudo /etc/init.d/apparmor restart

Par exemple, j'exécute la requête suivante dans le générateur de requêtes phpmyadmin pour exporter les données dans un fichier csv

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

Il réussit et écrit toutes les lignes avec les colonnes sélectionnées dans le fichier OUTPUT.csv ...

3
Sunny S.M

Dans mon cas, la solution consistait à rendre chaque répertoire du chemin de répertoire lisible et accessible par mysql (chmod a+rx). Le répertoire était toujours spécifié par son chemin relatif dans la ligne de commande.

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

Je viens de rencontrer ce même problème. Mon problème était que le répertoire dans lequel j'essayais de vider ne disposait pas de l'autorisation d'écriture pour le processus mysqld. Le dump SQL initial s'écrit mais l'écriture du fichier csv/txt échoue. On dirait que le dump SQL s'exécute en tant qu'utilisateur actuel et que la conversion en csv/txt est exécutée en tant qu'utilisateur qui exécute mysqld. Le répertoire doit donc disposer d'autorisations en écriture pour les deux utilisateurs.

2
Matthew McMillan

Ubuntu utilise-t-il SELinux? Vérifiez si elle est activée et appliquée. /var/log/audit/audit.log peut être utile (si c'est là où Ubuntu s'en tient, c'est l'emplacement de RHEL/Fedora).

1
Charles

Vous devez fournir un chemin absolu, pas un chemin relatif.

Indiquez le chemin d'accès complet au répertoire/data dans lequel vous essayez d'écrire.

1
Ike Walker

J'ai eu le même problème sur un CentOs 6.7. Dans mon cas, toutes les autorisations étaient définies et l'erreur était toujours survenue. Le problème était que SE Linux était en mode "mise en application".

Je l'ai commutée sur "permissive" en utilisant la commande Sudo setenforce 0

Ensuite, tout a fonctionné pour moi.

0
Stefan Bicher