Cum pot să ocolesc Errcode 13 MySQL cu SELECT INTO OUTFILE? (Programare, Mysql, Sql, În Fișierul De Ieșire)

Ryan Olson a intrebat.

Încerc să descarc conținutul unui tabel într-un fișier csv folosind o instrucțiune MySQL SELECT INTO OUTFILE. Dacă fac:

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

outfile.csv va fi creat pe server în același director în care sunt stocate fișierele acestei baze de date.

Cu toate acestea, atunci când îmi schimb interogarea în:

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

obțin:

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

Errcode 13 este o eroare de permisiuni, dar o obțin chiar dacă schimb proprietatea /data în mysql:mysql și îi dau permisiuni 777. MySQL rulează ca utilizator „mysql”.

În mod ciudat, pot crea fișierul în /tmp, dar nu și în niciun alt director pe care l-am încercat, chiar și cu permisiunile setate astfel încât utilizatorul mysql ar trebui să poată scrie în director.

Acesta este MySQL 5.0.75 care rulează pe Ubuntu.

Comentarii

  • Având în vedere că 13 este o eroare de sistem, probabil că nu asta este, dar există o setare MySQL care limitează INTO OUTFILE la un director: dev.mysql.com/doc/refman/5.0/en/… poate că merită să verificați rapid dacă este setată la /tmp. –  > Por Pekka.
  • Această variabilă este goală pe instalarea mea, ceea ce, conform acestui document, înseamnă că directoarele mele de ieșire nu ar trebui să fie limitate. –  > Por Ryan Olson.
13 răspunsuri
Vin-G

Ce versiune particulară de Ubuntu este aceasta și este Ubuntu Server Edition?

Edițiile recente de Ubuntu Server (cum ar fi 10.04) sunt livrate cu AppArmor și profilul MySQL ar putea fi în mod implicit în modul de impunere. Puteți verifica acest lucru executând sudo aa-status în felul următor:

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

Dacă mysqld este inclus în modul enforce, atunci el este cel care probabil refuză scrierea. De asemenea, ar fi scrise intrări în /var/log/messages atunci când AppArmor blochează scrierile/accesele. Ceea ce puteți face este să editați /etc/apparmor.d/usr.sbin.mysqld și să adăugați /data/ și /data/* lângă partea de jos, astfel:

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

Și apoi faceți ca AppArmor să reîncarce profilurile.

# sudo /etc/init.d/apparmor reload

AVERTISMENT: modificarea de mai sus va permite MySQL să citească și să scrie în directorul /data. Sperăm că v-ați gândit deja la implicațiile de securitate ale acestui lucru.

user1544337

Comentarii

  • Nu-mi place să subliniez acest lucru, dar există un motiv pentru care App Armor nu permite acest lucru. MySQL are acum capacitatea de a modifica și de a citi orice în directorul /data. Doar să nu fiți hackuit acum. –  > Por Ryan Ward.
  • @Serdar, Setul de reguli AppArmor MySQL distribuit împreună cu distribuția nu permite acest lucru în mod implicit. Acest lucru are sens, deoarece este o bună bază de reguli pentru o instalare nouă. Cred că ar trebui și ni se permite să modificăm seturile de reguli pentru a se potrivi nevoilor noastre post-instalare. Intenția inițiala a fost de a permite MySQL să scrie în anumite directoare. Dar, dacă nu este ușor de explicitat mai sus, o notă pentru alte persoane care se împiedică de această soluție: AVERTISMENT: modificarea de mai sus va permite MySQL să citească și să scrie în directorul /data. Sperăm că v-ați gândit deja la implicațiile de securitate ale acestui lucru. –  > Por Vin-G.
  • RĂSPUNS EXCELENT!!! Mi-a rezolvat problema, încercam și eu să scriu în orice alt director. Acum, trebuie să cercetez despre ce era vorba! 🙂 Aflând despre asta, recomand și altor persoane să citească despre apparmor (și, prin urmare, despre comanda aa-status): ro.wikipedia.org/wiki/AppArmor –  > Por David L.
  • În cazul meu, acest lucru a ajutat: /your/abs/folder/ r, /your/abs/folder/** rwk, } nu uitați să includeți virgula la sfârșit! –  > Por ACV.
  • funcționează pentru a scrie în /tmp. Folosiți în schimb windows. –  > Por Victor Ionescu.
rook

Ubuntu folosește AppArmor și asta este ceea ce te împiedică să accesezi /data/. Fedora folosește selinux și asta ar împiedica acest lucru pe o mașină RHEL/Fedora/CentOS.

Pentru a modifica AppArmor pentru a permite MySQL să acceseze /data/ faceți următoarele:

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

adăugați această linie oriunde în lista de directoare:

/data/ rw,

apoi faceți un :

sudo /etc/init.d/apparmor restart

O altă opțiune este de a dezactiva AppArmor pentru mysql cu totul, aceasta este NU ESTE RECOMANDATĂ:

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

Nu uitați să reporniți Appmor:

sudo /etc/init.d/apparmor restart

Comentarii

protoboolean

Știu că ai spus că ai încercat deja să setezi permisiunile la 777, dar cum am o dovadă că pentru mine a fost o problemă de permisiuni, postez ce am rulat mai exact în speranța că poate ajuta. Iată care este experiența mea:

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 $ 

Comentarii

  • [email protected]:/data$ pwd /data [email protected]:/data$ ls -al total 60 … drwxrwxrwxrwx 2 mysql mysql 4096 2010-05-06 16:27 dumptest [email protected]:/data$ mysqldump -u dbuser -p -T dumptest -B db_name –tables test Introduceți parola: mysqldump: Am primit o eroare: 1: Nu se poate crea/scrie în fișierul ‘/data/dumptest/test.txt’ (Errcode: 13) când se execută ‘SELECT INTO OUTFILE’ [email protected]:/data$ sudo chmod a+rwx dumptest/ [email protected]:/data$ mysqldump -u dbuser -p -T dumptest -B db_name –tables test Introduceți parola: mysqldump: Am primit o eroare: 1: (aceeași eroare) –  > Por Ryan Olson.
  • Oy, ei bine, nu mi-am dat seama că comentariile nu ar formata, dar am verificat de două ori câteva moduri diferite. În primul rând cu directorul țintă deținut de mysql:mysql, apoi cu directorul țintă deținut de utilizatorul cu care executam comanda dump, ambele moduri îmi dau în continuare aceeași eroare de permisiuni. –  > Por Ryan Olson.
  • Pentru înregistrare, acest lucru a funcționat pentru mine în ciuda faptului că am schimbat permisiunile apparmor –  > Por Alex.
  • Am încercat să fac modificări la apparmor, dar nu a funcționat. Schimbarea permisiunii ‘chmod 777’ a funcționat pentru mine! –  > Por Sudarshan_SMD.
vimdude

MySQL devine prost aici. Încearcă să creeze fișiere sub /tmp/data/…. Deci, ceea ce puteți face este următorul lucru:

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

Apoi, încercați interogarea. Acest lucru a funcționat pentru mine după ore întregi de depanare a problemei.

Comentarii

  • Îmi place cel mai mult acest răspuns. Este ușor, funcționează și nu necesită să te chinui cu apparmor. Celălalt mod de a face acest lucru folosind pipe nu funcționează bine pentru exporturi mari din cauza tuturor tamponărilor care se fac. –  > Por Chris Seline.
fanchyna

Această problemă mă deranjează de mult timp. Am observat că această discuție nu indică soluția pe RHEL/Fecora. Eu folosesc RHEL și nu găsesc fișierele de configurare corespunzătoare lui AppArmer pe Ubuntu, dar mi-am rezolvat problema făcând ca TOATE directoarele din directorul PATH să fie citite și accesibile de către mysql. De exemplu, dacă creați un director /tmp, următoarele două comenzi fac ca SELECT INTO OUTFILE să poată scoate fișierul .sql ȘI .sql

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

Dacă creați un director în directorul de acasă /home/tom, trebuie să faceți acest lucru atât pentru /home cât și pentru /home/tom.

Comentarii

  • Folosirea /tmp ca exemplu nu este o idee bună și chiar nu doriți să schimbați proprietatea directorului /tmp (în majoritatea cazurilor). –  > Por sastorsl.
  • Schimbarea proprietății lui /tmp este un lucru rău, dar crearea unui dosar temporar în interiorul lui /tmp și chown mysql:mysql mi-a rezolvat problema –  > Por Samuel Prevost.
Navrattan Yadav

Puteți face acest lucru :

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

Comentarii

  • Mulțumesc! Este posibil să controlați ieșirea ca CSV? –  > Por Hamman Samuel.
mdma

Câteva lucruri de încercat:

  • este secure_file_priv variabila de sistem este setată? Dacă este, toate fișierele trebuie să fie scrise în acel director.
  • asigurați-vă că fișierul nu există – MySQL va crea doar fișiere noi, nu le va suprascrie pe cele existente.

Comentarii

  • De asemenea, aș opta pentru secure_file_priv. Dacă fișierul există deja, mesajul de eroare este diferit (nu errcode 13). –  > Por Xavier Maillard.
  • secure_file_priv nu este setat în prezent, așa că, din câte înțeleg eu, înseamnă că nu ar trebui să fiu limitat în ceea ce privește locul unde pot scrie fișiere. Înțeleg greșit și trebuie să îl setez în mod explicit la ceva de genul „/” dacă vreau să pot scrie oriunde în sistemul de fișiere? –  > Por Ryan Olson.
  • De asemenea, verific dacă fișierul nu există înainte de a rula interogarea. –  > Por Ryan Olson.
  • Vă mulțumim pentru feedback. Pe baza constatărilor dvs., nu cred că niciuna dintre aceste sugestii nu cauzează problema dvs. –  > Por mdma.
Sunny S.M

Am aceeași problemă și eu am rezolvat această problemă prin următorii pași:

  • Sistem de operare : ubuntu 12.04
  • Lampă instalată
  • să presupunem că directorul în care se salvează fișierul de ieșire este : /var/www/csv/

Executați următoarea comandă pe terminal și editați acest fișier utilizând editorul gedit pentru a adăuga directorul dvs. la fișierul de ieșire.

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

  • acum fișierul va fi deschis în editor, vă rugăm să adăugați directorul dvs. acolo

    /var/www/csv/* rw,

  • de asemenea, am adăugat în fișierul meu, după cum urmează în imaginea de mai jos:

Executați următoarea comandă pentru a reporni serviciile :

sudo /etc/init.d/apparmor restart

De exemplu, am executat următoarea interogare în phpmyadmin query builder pentru a scoate datele în fișierul csv

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

Aceasta a fost efectuată cu succes și scrie toate rândurile cu coloanele selectate în fișierul OUTPUT.csv…

Mai multe informații

În cazul meu, soluția a fost să fac fiecare director din calea directoarelor să poată fi citit și accesat de către mysql (chmod a+rx). Directorul era în continuare specificat prin calea sa relativă în linia de comandă.

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

Matthew McMillan

Tocmai m-am confruntat cu aceeași problemă. Problema mea a fost că directorul în care încercam să fac dumping nu avea permisiunea de scriere pentru procesul mysqld. Descărcarea inițială sql ar scrie, dar scrierea fișierului csv/txt ar eșua. Se pare că descărcarea sql se execută ca utilizator curent, iar conversia în csv/txt se execută ca utilizator care rulează mysqld. Deci, directorul are nevoie de permisiuni de scriere pentru ambii utilizatori.

Ike Walker

Trebuie să furnizați o cale absolută, nu o cale relativă.

Furnizați calea completă către directorul /data în care încercați să scrieți.

Comentarii

  • Mie mi se pare că este o cale absolută. Nu este așa? –  > Por Pekka.
  • Încercați acest lucru ca utilizator mysql pentru a verifica dacă puteți crea fișierul în afara mysql: touch /data/outfile.csv –  > Por Ike Walker.
  • Mai întâi nu am putut face acest lucru deoarece shell-ul utilizatorului mysql era setat la /bin/false, deci nu m-am putut conecta ca mysql. Doar pentru a mă asigura că acest lucru nu contribuie la problemă, am setat shell-ul lui mysql la /bin/bash, am făcut su’d la acel utilizator și am atins un fișier în /data. Fișierul a fost creat cu succes, fiind deținut de mysql. –  > Por Ryan Olson.
  • Puteți face su la un cont chiar dacă acesta folosește unul dintre shell-urile „disable”: su --shell=/bin/sh nameofaccount –  > Por Marc B.
  • Mulțumesc, nu știam acest lucru. –  > Por Ryan Olson.
Charles

Folosește Ubuntu SELinux? Verificați dacă este activat și dacă se aplică. /var/log/audit/audit.log ar putea fi de ajutor (dacă Ubuntu îl pune acolo – aceasta este locația RHEL/Fedora).

Stefan Bicher

Am avut aceeași problemă pe un CentOs 6.7În cazul meu toate permisiunile au fost setate și totuși a apărut eroarea. Problema era că SE Linux era în modul „enforcing”.

L-am schimbat în „permissive” folosind comanda sudo setenforce 0

Apoi totul a funcționat pentru mine.