Come posso aggirare MySQL Errcode 13 con SELECT INTO OUTFILE?


114

Sto cercando di scaricare il contenuto di una tabella in un file csv utilizzando un'istruzione MySQL SELECT INTO OUTFILE. Se lo faccio:

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

outfile.csv verrà creato sul server nella stessa directory in cui sono archiviati i file del database.

Tuttavia, quando cambio la mia query in:

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

Ottengo:

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

Errcode 13 è un errore di autorizzazioni, ma lo ottengo anche se cambio la proprietà di / data in mysql: mysql e gli do i permessi 777. MySQL è in esecuzione come utente "mysql".

Stranamente posso creare il file in / tmp, ma non in qualsiasi altra directory che ho provato, anche con i permessi impostati in modo tale che l'utente mysql possa scrivere nella directory.

Questo è MySQL 5.0.75 in esecuzione su Ubuntu.


3
Visto che il 13 è un errore di sistema, probabilmente non lo è, ma esiste un'impostazione di mySQL che limita INTO OUTFILE a una directory: dev.mysql.com/doc/refman/5.0/en/… forse vale la pena dare un'occhiata se è impostato su /tmp.
Pekka

Quella variabile è vuota sulla mia installazione, il che secondo quel documento significa che le mie directory di output non dovrebbero essere limitate.
Ryan Olson

Risposte:


189

Quale particolare versione di Ubuntu è questa ed è questa Ubuntu Server Edition?

Le recenti edizioni di Ubuntu Server (come la 10.04) vengono fornite con AppArmor e il profilo di MySQL potrebbe essere in modalità di applicazione per impostazione predefinita. Puoi verificarlo eseguendo in questo sudo aa-statusmodo:

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

Se mysqld è incluso in modalità enforce, probabilmente è quello che nega la scrittura. Le voci verrebbero scritte anche /var/log/messagesquando AppArmor blocca le operazioni di scrittura / accesso. Quello che puoi fare è modificare /etc/apparmor.d/usr.sbin.mysqlde aggiungere /data/e /data/*vicino alla parte inferiore in questo 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,**  
}

Quindi fai in modo che AppArmor ricarichi i profili.

# sudo /etc/init.d/apparmor reload

ATTENZIONE: la modifica sopra consentirà a MySQL di leggere e scrivere nella directory / data. Ci auguriamo che tu abbia già considerato le implicazioni sulla sicurezza di questo.


2
Odio farlo notare, ma c'è una ragione per cui App Armor non lo consente. MySQL ora ha la capacità di modificare e leggere qualsiasi cosa nella cartella / data. Basta non farti hackerare ora.
Ryan Ward

2
@Serdar, Il set di regole AppArmor MySQL distribuito con la distribuzione non lo consente per impostazione predefinita . Questo ha senso in quanto è una buona base di regole per una nuova installazione. Credo che dovremmo essere e siamo autorizzati a modificare le regole per soddisfare le nostre esigenze dopo l'installazione. Era intenzione del richiedente originale consentire a MySQL di scrivere nelle directory specifiche. Ma se non è prontamente esplicito sopra, una nota per altre persone che si imbattono in questa soluzione: ATTENZIONE: la modifica sopra consentirà a MySQL di leggere e scrivere nella directory / data. Ci auguriamo che tu abbia già considerato le implicazioni sulla sicurezza di questo.
Vin-G

1
BELLA RISPOSTA!!! Ha risolto il mio problema, stavo anche cercando di scrivere in qualsiasi altra directory. Ora, devo ricercare di cosa si trattava! :) Imparando questo, consiglio ad altre persone di leggere su apparmor (e quindi, il comando aa-status): en.wikipedia.org/wiki/AppArmor
David L

1
Nel mio caso questo ha aiutato: /your/abs/folder/ r, /your/abs/folder/** rwk, }non dimenticare di includere la virgola alla fine!
ACV

1
funziona per scrivere in / tmp. Usa invece Windows. Linux fa schifo
Victor Ionescu

17

Ubuntu utilizza AppArmor e questo è ciò che ti impedisce di accedere a / data /. Fedora usa selinux e questo lo impedirebbe su una macchina RHEL / Fedora / CentOS.

Per modificare AppArmor per consentire a MySQL di accedere ai / dati / procedere come segue:

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

aggiungi questa riga ovunque nell'elenco delle directory:

/data/ rw,

quindi fai un:

sudo /etc/init.d/apparmor restart

Un'altra opzione è disabilitare completamente AppArmor per mysql, questo NON è RACCOMANDATO :

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

Non dimenticare di riavviare apparmor:

sudo /etc/init.d/apparmor restart


Per disabilitare effettivamente apparmor per mysql dovevo fare: cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands
silver_mx

14

So che hai detto che hai già provato a impostare i permessi su 777, ma poiché ho la prova che per me si trattava di un problema di autorizzazione, sto postando quello che corro esattamente sperando che possa aiutare. Ecco la mia esperienza:

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 $ 

me @ server: / data $ pwd / dati me @ server: / data $ ls -al total 60 ... drwxrwxrwx 2 mysql mysql 4096 2010-05-06 16:27 dumptest me @ server: / data $ mysqldump -u dbuser -p -T dumptest -B db_name --tables test Immettere la password: mysqldump: errore ricevuto: 1: impossibile creare / scrivere nel file "/data/dumptest/test.txt" (Errcode: 13) durante l'esecuzione di "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 Immettere la password: mysqldump: errore ricevuto: 1: ( stesso errore)
Ryan Olson

Oy, beh, non sapevo che i commenti non sarebbero stati formattati, ma ricontrollato in diversi modi. Prima con la directory di destinazione di proprietà di mysql: mysql, quindi con la directory di destinazione di proprietà dell'utente stavo eseguendo il comando dump, entrambi i modi mi danno ancora lo stesso errore di autorizzazioni.
Ryan Olson

Per la cronaca, questo ha funzionato per me nonostante abbia cambiato le autorizzazioni dell'apparmor
Alex

Ho provato ad apportare modifiche ad apparmor, ma non ha funzionato. La modifica dell'autorizzazione "chmod 777" ha funzionato per me!
Sudarshan_SMD

7

MySQL sta diventando stupido qui. Prova a creare file in / tmp / data / .... Quindi quello che puoi fare è quanto segue:

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

Quindi prova la tua query. Questo ha funzionato per me dopo ore di debug del problema.


Mi piace di più questa risposta. È facile, funziona e non richiede l'uso di apparmor. L'altro modo di farlo utilizzando le pipe non funziona bene per le esportazioni di grandi dimensioni a causa di tutto il buffering che viene eseguito.
Chris Seline

6

Questo problema mi ha infastidito per molto tempo. Ho notato che questa discussione non indica la soluzione su RHEL / Fecora. Sto usando RHEL e non trovo i file di configurazione corrispondenti ad AppArmer su Ubuntu, ma ho risolto il mio problema rendendo OGNI directory nella directory PATH leggibile e accessibile da mysql. Ad esempio, se crei una directory / tmp, i seguenti due comandi rendono SELECT INTO OUTFILE in grado di produrre il file .sql AND .sql

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

Se crei una directory nella tua home directory / home / tom, devi farlo sia per / home che per / home / tom.


3
Usare / tmp come esempio non è una buona idea e davvero non si vuole cambiare la proprietà della directory / tmp (nella maggior parte dei casi).
sastorsl

Cambiare la proprietà di / tmp è sbagliato, ma la creazione di una cartella temporanea all'interno di / tmp ha chown mysql:mysqlrisolto il mio problema
Samuel Prevost,

6

Puoi farlo :

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

Grazie! È possibile controllare l'output come CSV?
Hamman Samuel

4

Alcune cose da provare:

  • è secure_file_privimpostata la variabile di sistema? Se lo è, tutti i file devono essere scritti in quella directory.
  • assicurati che il file non esista: MySQL creerà solo nuovi file, non sovrascriverà quelli esistenti.

1
Vorrei anche scegliere secure_file_priv. Se il file esiste già, il messaggio di errore è diverso (non errcode 13).
Xavier Maillard

secure_file_priv non è attualmente impostato, quindi da quanto ho capito significa che non dovrei essere limitato a dove posso scrivere i file. Sto fraintendendo questo e devo impostarlo esplicitamente su qualcosa come "/" se voglio essere in grado di scrivere ovunque sul file system?
Ryan Olson

Inoltre, sto controllando che il file non esista prima di eseguire la query.
Ryan Olson

Grazie per il feedback. Sulla base dei tuoi risultati, non credo che nessuno di questi suggerimenti causi il tuo problema.
mdma

3

Ho lo stesso problema e ho risolto questo problema seguendo i passaggi:

  • Sistema operativo: ubuntu 12.04
  • lampada installata
  • supponiamo che la directory in cui salvare il file di output sia: / var / www / csv /

Esegui il seguente comando sul terminale e modifica questo file utilizzando l'editor gedit per aggiungere la tua directory al file di output.

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

  • ora il file verrebbe aperto nell'editor per favore aggiungi la tua directory lì

    / var / www / csv / * rw,

  • allo stesso modo ho aggiunto nel mio file, come la seguente immagine data:

inserisci qui la descrizione dell'immagine

Esegui il comando successivo per riavviare i servizi:

sudo /etc/init.d/apparmor riavvio

Ad esempio, eseguo la seguente query nel generatore di query phpmyadmin per visualizzare i dati nel file csv

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

Ha fatto con successo e scrive tutte le righe con le colonne selezionate nel file OUTPUT.csv ...


2

Nel mio caso, la soluzione era rendere ogni directory nel percorso della directory leggibile e accessibile da mysql( chmod a+rx). La directory era ancora specificata dal relativo percorso nella riga di comando.

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

2

Mi sono imbattuto nello stesso problema. Il mio problema era che la directory in cui stavo cercando di eseguire il dump non aveva l'autorizzazione di scrittura per il processo mysqld. Il dump sql iniziale verrebbe scritto ma la scrittura del file csv / txt fallirebbe. Sembra che il dump sql venga eseguito come l'utente corrente e la conversione in csv / txt venga eseguita come l'utente che esegue mysqld. Quindi la directory necessita dei permessi di scrittura per entrambi gli utenti.


1

È necessario fornire un percorso assoluto, non un percorso relativo.

Fornisci il percorso completo della directory / data in cui stai tentando di scrivere.


Mi sembra un percorso assoluto. Non è?
Pekka

2
Prova questo come utente mysql per verificare che puoi creare il file al di fuori di mysql:touch /data/outfile.csv
Ike Walker

1
Innanzitutto non ho potuto farlo perché la shell dell'utente mysql era impostata su / bin / false, quindi non ho potuto accedere come mysql. Solo per assicurarmi che ciò non contribuisse al problema, ho impostato la shell di mysql su / bin / bash, ho fatto il su a quell'utente e ho toccato un file in / data. Il file è stato creato con successo, di proprietà di mysql.
Ryan Olson

3
Puoi su a un account anche se sta utilizzando una delle shell "disabilita": su --shell=/bin/sh nameofaccount
Marc B

Grazie, non ne ero consapevole.
Ryan Olson

1

Ubuntu usa SELinux? Controlla per vedere se è abilitato e imposto. /var/log/audit/audit.log potrebbe essere utile (se è lì che Ubuntu lo attacca, quella è la posizione RHEL / Fedora).


0

Ho avuto lo stesso problema su un CentOs 6.7 Nel mio caso sono state impostate tutte le autorizzazioni e l'errore si è verificato ancora. Il problema era che SE Linux era in modalità "imposizione".

L'ho impostato su "permissivo" usando il comando sudo setenforce 0

Poi tutto ha funzionato per me.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.