SELECT INTO OUTFILE ile MySQL Errcode 13'ü nasıl aşabilirim?


114

MySQL SELECT INTO OUTFILE deyimini kullanarak bir tablonun içeriğini bir csv dosyasına dökmeye çalışıyorum. Eğer yaparsam:

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

outfile.csv, sunucuda bu veritabanının dosyalarının depolandığı dizinde oluşturulacaktır.

Ancak, sorgumu şu şekilde değiştirdiğimde:

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

Alırım:

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

Errcode 13 bir izin hatasıdır, ancak / data'nın sahipliğini mysql: mysql olarak değiştirsem ve 777 izinlerini versem bile anlıyorum. MySQL, "mysql" kullanıcısı olarak çalışıyor.

Garip bir şekilde dosyayı / tmp içinde oluşturabilirim, ancak denediğim herhangi bir dizinde değil, mysql kullanıcısının dizine yazabilmesi için izinler ayarlanmış olsa bile.

Bu, Ubuntu'da çalışan MySQL 5.0.75'tir.


3
13'ün bir sistem hatası olduğunu düşünürsek , bu muhtemelen değildir, ancak INTO OUTFILE'ı bir dizine sınırlayan bir mySQL ayarı vardır: dev.mysql.com/doc/refman/5.0/en/… belki hızlı bir şekilde bakmaya değer mi? olarak ayarlayın /tmp.
Pekka

Bu değişken kurulumumda boş, bu belgeye göre çıktı dizinlerimin sınırlandırılmaması gerektiği anlamına geliyor.
Ryan Olson

Yanıtlar:


189

Bu, Ubuntu'nun hangi özel sürümü ve bu Ubuntu Sunucu Sürümü?

En son Ubuntu Sunucu Sürümleri (10.04 gibi) AppArmor ile birlikte gelir ve MySQL'in profili varsayılan olarak zorlama modunda olabilir. Bunu şu şekilde çalıştırarak kontrol edebilirsiniz sudo aa-status:

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

Mysqld zorlama moduna dahil edilmişse, muhtemelen yazmayı reddendir. Girişler, /var/log/messagesAppArmor yazma / erişimleri engellediğinde de yazılacaktır . Yapabilecekleriniz, aşağıdaki gibi düzenlemek /etc/apparmor.d/usr.sbin.mysqldve eklemek /data/ve /data/*en altına eklemektir :

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

Ve sonra AppArmor'un profilleri yeniden yüklemesini sağlayın.

# sudo /etc/init.d/apparmor reload

UYARI: Yukarıdaki değişiklik MySQL'in / data dizinini okumasına ve yazmasına izin verecektir. Umarız bunun güvenlik sonuçlarını zaten düşünmüşsünüzdür.


2
Bunu belirtmekten nefret ediyorum, ancak App Armor'ın buna izin vermemesinin bir nedeni var. MySQL artık / data klasöründeki herhangi bir şeyi değiştirme ve okuma yeteneğine sahiptir. Sadece şimdi saldırıya uğramayın.
Ryan Ward

2
@Serdar, Dağıtım ile dağıtılan AppArmor MySQL kural seti buna varsayılan olarak izin vermiyor . Bu, yeni bir kurulum için iyi bir kural temeli olduğu için mantıklıdır. Kurulum sonrası ihtiyaçlarımıza uyması için kural setlerini değiştirmemiz gerektiğine ve izin verildiğine inanıyorum. Asıl soran kişinin amacı MySQL'in belirli dizinlere yazmasına izin vermekti. Ancak yukarıda açıkça belirtilmemişse, bu çözüme tökezleyen diğer insanlara bir not: UYARI: Yukarıdaki değişiklik MySQL'in / data dizinini okuyup yazmasına izin verecektir. Umarız bunun güvenlik sonuçlarını zaten düşünmüşsünüzdür.
Vin-G

1
MÜKEMMEL CEVAP!!! Sorunumu çözdü, başka bir dizine de yazmaya çalışıyordum. Şimdi, tüm bunların neyle ilgili olduğunu araştırmalıyım! :) Bunu öğrenirken, başkalarına apparmor (ve dolayısıyla aa-status komutunu) okumalarını tavsiye ederim: en.wikipedia.org/wiki/AppArmor
David L

1
Benim durumumda bu yardımcı oldu: /your/abs/folder/ r, /your/abs/folder/** rwk, }Sonuna virgül eklemeyi unutmayın!
ACV

1
/ tmp içinde yazmaya çalışır. Bunun yerine pencereleri kullanın. Linux berbat
Victor Ionescu

17

Ubuntu, AppArmor kullanıyor ve bu, / data / erişimini engelleyen şeydir. Fedora selinux kullanıyor ve bu bir RHEL / Fedora / CentOS makinesinde bunu önleyecektir.

AppArmor'u MySQL'in / verilere erişmesine izin verecek şekilde değiştirmek için aşağıdakileri yapın:

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

bu satırı dizinler listesinin herhangi bir yerine ekleyin:

/data/ rw,

o zaman şunu yapın:

sudo /etc/init.d/apparmor restart

Diğer bir seçenek de mysql için AppArmor'u tamamen devre dışı bırakmaktır, bu TAVSİYE EDİLMEZ :

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

Apparmor'u yeniden başlatmayı unutmayın:

sudo /etc/init.d/apparmor restart


Aslında mysql için apparmor'u devre dışı bırakmak için yapmam gerekiyordu: cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands
silver_mx

14

Önceden izinleri 777'ye ayarlamayı denediğinizi söylediğini biliyorum, ancak benim için bunun bir izin sorunu olduğuna dair bir kanıtım olduğundan, yardımcı olabileceğini umarak tam olarak çalıştırdığım şeyi gönderiyorum. İşte deneyimim:

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 / data me @ server: / data $ ls -al toplam 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 Şifreyi girin: mysqldump: Hata var: 1: 'SELECT INTO' çalıştırılırken '/data/dumptest/test.txt' dosyası oluşturulamıyor / yazılamıyor (Hata kodu: 13) OUTFILE 'me @ server: / data $ sudo chmod a + rwx dumptest / me @ server: / data $ mysqldump -u dbuser -p -T dumptest -B db_name --tables test Şifre girin: mysqldump: Hata var: 1: ( aynı hata)
Ryan Olson

Oy, yorumların formatlanmayacağının farkında değildi, ancak birkaç farklı yolu iki kez kontrol etti. İlk önce mysql: mysql'e ait hedef dizinle, ardından kullanıcıya ait hedef dizinde dump komutunu çalıştırıyordum, çünkü her iki yol da bana aynı izin hatasını veriyor.
Ryan Olson

Kayıt için, uygulama izinlerini değiştirmeme rağmen bu benim için çalıştı
Alex

Bir aparatta değişiklik yapmayı denedim, işe yaramadı. 'Chmod 777' iznini değiştirmek benim için çalıştı!
Sudarshan_SMD

7

MySQL burada aptallaşıyor. / Tmp / data / .... altında dosya oluşturmaya çalışır. Yani yapabilecekleriniz şudur:

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

Ardından sorgunuzu deneyin. Bu, sorunu saatlerce ayıkladıktan sonra benim için çalıştı.


Bu cevabı en çok beğendim. Kolay, işe yarıyor ve bir aparey ile uğraşmanıza gerek yok. Borular kullanarak yapmanın diğer yolu, yapılan tüm tamponlama nedeniyle büyük dışa aktarımlar için iyi sonuç vermez.
Chris Seline

6

Bu sorun beni uzun zamandır rahatsız ediyor. Bu tartışmanın RHEL / Fecora'daki çözüme işaret etmediğini fark ettim. RHEL kullanıyorum ve Ubuntu'da AppArmer'a karşılık gelen yapılandırma dosyalarını bulamıyorum, ancak PATH dizinindeki HER dizini mysql tarafından okunabilir ve erişilebilir hale getirerek sorunumu çözdüm. Örneğin, bir / tmp dizini oluşturursanız, aşağıdaki iki komut SELECT INTO OUTFILE'ı .sql VE .sql dosyasının çıktısını alabilir.

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

/ Home / tom ana dizininizde bir dizin oluşturursanız, bunu hem / home hem de / home / tom için yapmanız gerekir.


3
Örnek olarak / tmp kullanmak iyi bir fikir değildir ve / tmp dizininin sahipliğini gerçekten değiştirmek istemezsiniz (çoğu durumda).
sastorsl

/ Tmp'nin sahipliğini değiştirmek kötü, ancak / tmp içinde geçici bir klasör oluşturmak ve chown mysql:mysqlsorunumu çözdü
Samuel Prevost

6

Bunu yapabilirsiniz :

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

Teşekkürler! Çıkışı CSV olarak kontrol etmek mümkün mü?
Hamman Samuel

4

Deneyebileceğiniz bazı şeyler:

  • olan secure_file_privsistem değişkeni kümesi? Eğer öyleyse, tüm dosyalar o dizine yazılmalıdır.
  • dosyanın mevcut olmadığından emin olun - MySQL yalnızca yeni dosyalar oluşturur, mevcut dosyaların üzerine yazmaz.

1
Ayrıca secure_file_priv için de giderdim. Dosya zaten mevcutsa, hata mesajı farklıdır (hata kodu 13 değil).
Xavier Maillard

secure_file_priv şu anda ayarlanmadı, bu yüzden anladığım kadarıyla bu, dosyaları nereye yazabileceğim konusunda sınırlandırılmamam gerektiği anlamına geliyor. Bunu yanlış mı anlıyorum ve dosya sisteminde herhangi bir yere yazabilmek istiyorsam bunu açıkça '/' gibi bir şeye ayarlamam gerekir mi?
Ryan Olson

Ayrıca, sorguyu çalıştırmadan önce dosyanın var olmadığını kontrol ediyorum.
Ryan Olson

Geri dönüşünüz için teşekkür ederiz. Bulgularınıza göre, bu önerilerin ikisinin de sorununuza neden olduğunu düşünmüyorum.
mdma

3

Aynı sorunu yaşıyorum ve bu sorunu aşağıdaki adımları izleyerek çözdüm:

  • İşletim sistemi: ubuntu 12.04
  • lamba takılı
  • çıktı dosyasını kaydetmek için dizininizin: / var / www / csv / olduğunu varsayalım

Terminalde aşağıdaki komutu çalıştırın ve dizininizi çıktı dosyasına eklemek için gedit editörü kullanarak bu dosyayı düzenleyin.

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

  • şimdi dosya düzenleyicide açılacak lütfen dizininizi buraya ekleyin

    / var / www / csv / * rw,

  • aynı şekilde, aşağıdaki resim gibi dosyama ekledim:

görüntü açıklamasını buraya girin

Hizmetleri yeniden başlatmak için sonraki komutu yürütün:

sudo /etc/init.d/apparmor yeniden başlat

Örneğin, csv dosyasında veri çıkışı sağlamak için phpmyadmin sorgu oluşturucuya aşağıdaki sorguyu çalıştırıyorum

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

Başarıyla yapıldı ve seçilen sütunlara sahip tüm satırları OUTPUT.csv dosyasına yazdı ...


2

Benim durumumda çözüm, dizin yolundaki her dizini mysql( chmod a+rx) tarafından okunabilir ve erişilebilir hale getirmekti . Dizin, komut satırındaki göreceli yolu ile hala belirtiliyordu.

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

2

Ben de aynı problemle karşılaştım. Benim sorunum, dökmeye çalıştığım dizinin mysqld işlemi için yazma iznine sahip olmamasıydı. İlk sql dökümü yazılır, ancak csv / txt dosyasının yazımı başarısız olur. Görünüşe göre sql dökümü geçerli kullanıcı olarak çalışıyor ve csv / txt'ye dönüştürme mysqld'yi çalıştıran kullanıcı olarak çalıştırılıyor. Yani dizinin her iki kullanıcı için de yazma izinlerine ihtiyacı var.


1

Göreceli bir yol değil, mutlak bir yol sağlamanız gerekir.

Yazmaya çalıştığınız / data dizininin tam yolunu girin.


Bu bana mutlak bir yol gibi görünüyor. Değil mi?
Pekka

2
Dosyayı mysql dışında oluşturabileceğinizi doğrulamak için bunu mysql kullanıcısı olarak deneyin:touch /data/outfile.csv
Ike Walker

1
Öncelikle yapamadım çünkü mysql kullanıcısının kabuğu / bin / false olarak ayarlandı, bu yüzden mysql olarak oturum açamadım. Soruna katkıda bulunmadığından emin olmak için, mysql'ın kabuğunu / bin / bash olarak ayarladım, o kullanıcıya su'd ve / data içindeki bir dosyaya dokundum. Dosya, mysql'ye ait başarıyla oluşturuldu.
Ryan Olson

3
"Devre dışı bırakma" kabuklarından birini kullanıyor olsa bile bir hesaba dava açabilirsiniz: su --shell=/bin/sh nameofaccount
Marc B

Teşekkürler, bunun farkında değildim.
Ryan Olson

1

Ubuntu SELinux kullanıyor mu? Etkin olup olmadığını ve uygulanıp uygulanmadığını kontrol edin. /var/log/audit/audit.log yardımcı olabilir (eğer Ubuntu bunu yapıştırıyorsa - bu RHEL / Fedora konumudur).


0

CentOs 6.7'de aynı sorunu yaşadım. Benim durumumda tüm izinler ayarlandı ve hala hata oluştu. Sorun, SE Linux'un "zorlama" modunda olmasıydı.

Komutu kullanarak "müsaadeli" olarak değiştirdim sudo setenforce 0

Sonra her şey benim için çalıştı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.