ฉันจะไปรอบ ๆ MySQL Errcode 13 ด้วย SELECT INTO OUTFILE ได้อย่างไร


114

ฉันพยายามถ่ายโอนเนื้อหาของตารางไปยังไฟล์ csv โดยใช้คำสั่ง MySQL SELECT INTO OUTFILE ถ้าฉันทำ:

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

outfile.csv จะถูกสร้างขึ้นบนเซิร์ฟเวอร์ในไดเร็กทอรีเดียวกันไฟล์ของฐานข้อมูลนี้ถูกเก็บไว้ใน.

อย่างไรก็ตามเมื่อฉันเปลี่ยนแบบสอบถามเป็น:

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

ฉันเข้าใจ:

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

Errcode 13 เป็นข้อผิดพลาดเกี่ยวกับสิทธิ์ แต่ฉันได้รับแม้ว่าฉันจะเปลี่ยนความเป็นเจ้าของ / data เป็น mysql: mysql และให้สิทธิ์ 777 MySQL ทำงานในฐานะผู้ใช้ "mysql"

น่าแปลกที่ฉันสามารถสร้างไฟล์ใน / tmp แต่ไม่ได้อยู่ในไดเร็กทอรีอื่น ๆ ที่ฉันได้ลองแม้ว่าจะมีการตั้งค่าสิทธิ์เช่นนั้นผู้ใช้ mysql ควรจะสามารถเขียนลงในไดเร็กทอรีได้

นี่คือ MySQL 5.0.75 ที่ทำงานบน Ubuntu


3
เมื่อเห็นว่า 13 เป็นข้อผิดพลาดของระบบอาจจะไม่ใช่ แต่มีการตั้งค่า mySQL ที่ จำกัด INTO OUTFILE ไปยังไดเร็กทอรี: dev.mysql.com/doc/refman/5.0/en/…อาจจะคุ้มค่าที่จะดูอย่างรวดเร็วไม่ว่าจะเป็น ตั้งค่าเป็น/tmp.
Pekka

ตัวแปรนั้นว่างเปล่าในการติดตั้งของฉันซึ่งตามเอกสารนั้นหมายความว่าไดเรกทอรีผลลัพธ์ของฉันไม่ควรถูก จำกัด
Ryan Olson

คำตอบ:


189

Ubuntu รุ่นนี้เป็นรุ่นใดและเป็น Ubuntu Server Edition หรือไม่

Ubuntu Server Editions ล่าสุด (เช่น 10.04) มาพร้อมกับ AppArmor และโปรไฟล์ของ MySQL อาจอยู่ในโหมดบังคับใช้ตามค่าเริ่มต้น คุณสามารถตรวจสอบสิ่งนี้ได้โดยดำเนินการ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 รวมอยู่ในโหมดบังคับใช้แสดงว่าอาจเป็นการปฏิเสธการเขียน รายการจะถูกเขียน/var/log/messagesเมื่อ AppArmor บล็อกการเขียน / การเข้าถึง สิ่งที่คุณทำได้คือแก้ไข/etc/apparmor.d/usr.sbin.mysqldและเพิ่ม/data/และ/data/*ใกล้ด้านล่างดังนี้:

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

จากนั้นให้ AppArmor โหลดโปรไฟล์อีกครั้ง

# sudo /etc/init.d/apparmor reload

คำเตือน: การเปลี่ยนแปลงข้างต้นจะอนุญาตให้ MySQL อ่านและเขียนไปยังไดเร็กทอรี / data เราหวังว่าคุณจะได้พิจารณาถึงผลกระทบด้านความปลอดภัยของสิ่งนี้แล้ว


2
ฉันเกลียดที่จะชี้ให้เห็น แต่มีเหตุผลที่ App Armor ไม่อนุญาตให้ทำเช่นนี้ ขณะนี้ MySQL มีความสามารถในการแก้ไขและอ่านอะไรก็ได้ในโฟลเดอร์ / data อย่าเพิ่งโดนแฮ็กตอนนี้
Ryan Ward

2
@Serdar ที่ AppArmor MySQL ruleset กระจายกับ distro ไม่อนุญาตให้มันไปโดยปริยาย สิ่งนี้สมเหตุสมผลเนื่องจากเป็นพื้นฐานที่ดีของกฎสำหรับการติดตั้งใหม่ ฉันเชื่อว่าเราควรจะเป็นและได้รับอนุญาตให้แก้ไขชุดกฎเพื่อให้เหมาะกับความต้องการของเราหลังการติดตั้ง เป็นความตั้งใจเดิมของผู้ถามที่จะอนุญาตให้ MySQL เขียนไปยังไดเร็กทอรีเฉพาะ แต่ถ้ามันไม่ชัดเจนในทันทีข้างต้นข้อควรทราบสำหรับผู้ที่สะดุดกับการแก้ปัญหานี้: คำเตือน: การเปลี่ยนแปลงข้างต้นจะอนุญาตให้ MySQL อ่านและเขียนไปยังไดเร็กทอรี / data เราหวังว่าคุณจะได้พิจารณาถึงผลกระทบด้านความปลอดภัยของสิ่งนี้แล้ว
Vin-G

1
คำตอบที่ดี !!! มันแก้ปัญหาของฉันได้ฉันพยายามเขียนในไดเรกทอรีอื่นด้วย ตอนนี้ฉันต้องค้นคว้าว่าทั้งหมดนี้เกี่ยวกับอะไร! :) เรียนรู้เกี่ยวกับเรื่องนี้ฉันขอแนะนำให้คนอื่นอ่านเกี่ยวกับ apparmor (และด้วยเหตุนี้คำสั่ง aa-status): en.wikipedia.org/wiki/AppArmor
David L

1
ในกรณีของฉันสิ่งนี้ช่วยได้: /your/abs/folder/ r, /your/abs/folder/** rwk, }อย่าลืมใส่เครื่องหมายจุลภาคในตอนท้าย!
ACV

1
มันใช้งานได้ในการเขียนใน / tmp ใช้ windows แทน Linux sucks
Victor Ionescu

17

Ubuntu ใช้ AppArmor และนั่นคือสิ่งที่ป้องกันไม่ให้คุณเข้าถึง / data / Fedora ใช้ selinux และจะป้องกันไม่ให้เกิดปัญหานี้กับเครื่อง RHEL / Fedora / CentOS

ในการแก้ไข AppArmor เพื่ออนุญาตให้ MySQL เข้าถึง / ข้อมูล / ทำดังต่อไปนี้:

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

เพิ่มบรรทัดนี้ที่ใดก็ได้ในรายการไดเรกทอรี:

/data/ rw,

จากนั้นทำ:

sudo /etc/init.d/apparmor restart

อีกทางเลือกหนึ่งคือการปิดใช้งาน AppArmor สำหรับ mysql ทั้งหมดนี้ไม่แนะนำ :

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

อย่าลืมรีสตาร์ท apparmor:

sudo /etc/init.d/apparmor restart


เพื่อปิดการใช้งานจริง AppArmor สำหรับ MySQL ที่ผมต้องทำ: cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands
silver_mx

14

ฉันรู้ว่าคุณบอกว่าคุณได้ลองตั้งค่าการอนุญาตเป็น 777 แล้ว แต่เนื่องจากฉันมีหลักฐานว่าสำหรับฉันมันเป็นปัญหาการอนุญาตฉันจึงโพสต์สิ่งที่ฉันหวังว่ามันจะช่วยได้ นี่คือประสบการณ์ของฉัน:

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 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 ป้อนรหัสผ่าน: mysqldump: มีข้อผิดพลาด: 1: ไม่สามารถสร้าง / เขียนไปยังไฟล์ '/data/dumptest/test.txt' (Errcode: 13) เมื่อเรียกใช้ '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 ป้อนรหัสผ่าน: mysqldump: Got error: 1 :( ข้อผิดพลาดเดียวกัน)
Ryan Olson

เอาละไม่รู้ว่าความคิดเห็นจะไม่จัดรูปแบบ แต่ตรวจสอบวิธีต่างๆสองสามวิธี อันดับแรกด้วยไดเร็กทอรีเป้าหมายที่เป็นของ mysql: mysql จากนั้นด้วยไดเร็กทอรีเป้าหมายที่เป็นของผู้ใช้ฉันกำลังเรียกใช้คำสั่งดัมพ์เนื่องจากทั้งสองวิธียังคงให้ข้อผิดพลาดสิทธิ์เดียวกันกับฉัน
Ryan Olson

สำหรับบันทึกสิ่งนี้ใช้ได้ผลสำหรับฉันแม้ว่าจะมีการเปลี่ยนแปลงการอนุญาตของ apparmor
Alex

ฉันพยายามแก้ไข apparmor แต่มันไม่ได้ผล การเปลี่ยนสิทธิ์ 'chmod 777' ใช้ได้ผลสำหรับฉัน!
Sudarshan_SMD

7

MySQL เริ่มโง่ที่นี่ มันพยายามสร้างไฟล์ภายใต้ / tmp / data / .... ดังนั้นสิ่งที่คุณทำได้มีดังต่อไปนี้:

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

จากนั้นลองใช้คำถามของคุณ สิ่งนี้ใช้ได้ผลสำหรับฉันหลังจากผ่านไปหลายชั่วโมงของการแก้ไขข้อบกพร่อง


ฉันชอบคำตอบนี้ที่สุด เป็นเรื่องง่ายใช้งานได้และไม่ต้องการให้คุณใช้แอปอาร์มอร์ วิธีอื่นในการทำโดยใช้ท่อไม่ได้ผลดีสำหรับการส่งออกจำนวนมากเนื่องจากการบัฟเฟอร์ทั้งหมดที่ทำ
Chris Seline

6

ปัญหานี้รบกวนจิตใจฉันมานานแล้ว ฉันสังเกตว่าการสนทนานี้ไม่ได้ชี้ให้เห็นถึงการแก้ปัญหาของ RHEL / Fecora ฉันใช้ RHEL และฉันไม่พบไฟล์คอนฟิกูเรชันที่ตรงกับ AppArmer บน Ubuntu แต่ฉันแก้ไขปัญหาของฉันโดยทำให้ทุกไดเร็กทอรีในไดเร็กทอรี PATH สามารถอ่านและเข้าถึงได้โดย mysql ตัวอย่างเช่นหากคุณสร้างไดเร็กทอรี / tmp คำสั่งสองคำสั่งต่อไปนี้ทำให้ SELECT INTO OUTFILE สามารถส่งออกไฟล์. sql AND .sql

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

หากคุณสร้างไดเร็กทอรีในโฮมไดเร็กทอรี / home / tom คุณต้องดำเนินการนี้สำหรับทั้ง / home และ / home / tom


3
การใช้ / tmp เป็นตัวอย่างไม่ใช่ความคิดที่ดีและคุณไม่ต้องการเปลี่ยนความเป็นเจ้าของไดเร็กทอรี / tmp (ในกรณีส่วนใหญ่)
sastorsl

การเปลี่ยนความเป็นเจ้าของ / tmp นั้นไม่ดี แต่การสร้างโฟลเดอร์ temp ภายใน / tmp และchown mysql:mysqlแก้ไขปัญหาของฉัน
Samuel Prevost

6

คุณสามารถทำได้:

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

ขอบคุณ! สามารถควบคุมเอาต์พุตเป็น CSV ได้หรือไม่?
Hamman Samuel

4

สิ่งที่ควรลอง:

  • คือ secure_file_privชุดตัวแปรระบบ? ถ้าเป็นเช่นนั้นไฟล์ทั้งหมดจะต้องถูกเขียนลงในไดเร็กทอรีนั้น
  • ตรวจสอบให้แน่ใจว่าไม่มีไฟล์อยู่ - MySQL จะสร้างไฟล์ใหม่เท่านั้นไม่เขียนทับไฟล์ที่มีอยู่

1
ฉันจะไปที่ secure_file_priv ด้วย หากไฟล์มีอยู่แล้วข้อความแสดงข้อผิดพลาดจะแตกต่างออกไป (ไม่ใช่ errcode 13)
Xavier Maillard

ไม่ได้ตั้งค่า secure_file_priv ในขณะนี้ดังนั้นตามที่ฉันเข้าใจนั่นหมายความว่าฉันไม่ควรถูก จำกัด ว่าจะเขียนไฟล์ได้ที่ไหน ฉันเข้าใจผิดหรือไม่และฉันจำเป็นต้องตั้งค่าอย่างชัดเจนเป็นบางอย่างเช่น '/' หรือไม่ถ้าฉันต้องการที่จะสามารถเขียนที่ใดก็ได้บนระบบไฟล์?
Ryan Olson

นอกจากนี้ฉันกำลังตรวจสอบว่าไม่มีไฟล์ก่อนที่จะเรียกใช้แบบสอบถาม
Ryan Olson

ขอบคุณสำหรับความคิดเห็น. จากการค้นพบของคุณฉันไม่คิดว่าคำแนะนำเหล่านี้ทำให้เกิดปัญหาของคุณ
mdma

3

ฉันมีปัญหาเดียวกันและฉันแก้ไขปัญหานี้โดยทำตามขั้นตอน:

  • ระบบปฏิบัติการ: ubuntu 12.04
  • ติดตั้งหลอดไฟ
  • สมมติว่าไดเร็กทอรีของคุณบันทึกไฟล์เอาต์พุตคือ: / var / www / csv /

ดำเนินการคำสั่งต่อไปนี้บนเทอร์มินัลและแก้ไขไฟล์นี้โดยใช้โปรแกรมแก้ไข gedit เพื่อเพิ่มไดเร็กทอรีของคุณไปยังไฟล์เอาต์พุต

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

  • ตอนนี้ไฟล์จะถูกเปิดในตัวแก้ไขโปรดเพิ่มไดเร็กทอรีของคุณที่นั่น

    / var / www / csv / * rw,

  • ในทำนองเดียวกันฉันได้เพิ่มในไฟล์ของฉันดังภาพต่อไปนี้:

ใส่คำอธิบายภาพที่นี่

ดำเนินการคำสั่งถัดไปเพื่อเริ่มบริการใหม่:

sudo /etc/init.d/apparmor รีสตาร์ท

ตัวอย่างเช่นฉันเรียกใช้แบบสอบถามต่อไปนี้ในตัวสร้างแบบสอบถาม phpmyadmin เพื่อส่งออกข้อมูลในไฟล์ csv

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

ทำได้สำเร็จและเขียนแถวทั้งหมดพร้อมคอลัมน์ที่เลือกลงในไฟล์ OUTPUT.csv ...


2

ในกรณีของฉันวิธีแก้ปัญหาคือทำให้ทุกไดเร็กทอรีในพา ธ ไดเร็กทอรีสามารถอ่านได้และเข้าถึงได้โดยmysql( chmod a+rx) ไดเร็กทอรียังคงถูกระบุโดยพา ธ สัมพัทธ์ในบรรทัดรับคำสั่ง

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

2

ฉันเพิ่งพบปัญหาเดียวกันนี้ ปัญหาของฉันคือไดเร็กทอรีที่ฉันพยายามถ่ายโอนข้อมูลไม่มีสิทธิ์เขียนสำหรับกระบวนการ mysqld การถ่ายโอนข้อมูล sql เริ่มต้นจะเขียนออกมา แต่การเขียนไฟล์ csv / txt จะล้มเหลว ดูเหมือนว่าการถ่ายโอนข้อมูล sql จะทำงานเป็นผู้ใช้ปัจจุบันและการแปลงเป็น csv / txt จะถูกเรียกใช้ในฐานะผู้ใช้ที่กำลังเรียกใช้ mysqld ดังนั้นไดเรกทอรีจึงต้องการสิทธิ์ในการเขียนสำหรับผู้ใช้ทั้งสอง


1

คุณต้องระบุเส้นทางที่แน่นอนไม่ใช่เส้นทางสัมพัทธ์

ระบุพา ธ แบบเต็มไปยังไดเร็กทอรี / data ที่คุณพยายามเขียนถึง


นั่นดูเหมือนเส้นทางที่แน่นอนสำหรับฉัน มันไม่ใช่เหรอ?
Pekka

2
ลองใช้สิ่งนี้ในฐานะผู้ใช้ mysql เพื่อตรวจสอบว่าคุณสามารถสร้างไฟล์นอก mysql:touch /data/outfile.csv
Ike Walker

1
ก่อนอื่นฉันไม่สามารถทำได้เนื่องจากเชลล์ของผู้ใช้ mysql ถูกตั้งค่าเป็น / bin / false ดังนั้นฉันจึงไม่สามารถล็อกอินด้วย mysql ได้ เพื่อให้แน่ใจว่าไม่ได้มีส่วนทำให้เกิดปัญหาฉันตั้งค่าเชลล์ของ mysql เป็น / bin / bash ให้กับผู้ใช้รายนั้นและแตะไฟล์ใน / data ไฟล์ถูกสร้างสำเร็จโดย mysql เป็นเจ้าของ
Ryan Olson

3
คุณสามารถฟ้องร้องบัญชีได้แม้ว่าจะใช้เชลล์ "ปิดการใช้งาน" ตัวใดตัวหนึ่ง: su --shell=/bin/sh nameofaccount
Marc B

ขอบคุณฉันไม่ทราบเรื่องนั้น
Ryan Olson

1

Ubuntu ใช้ SELinux หรือไม่ ตรวจสอบว่ามีการเปิดใช้งานและบังคับใช้หรือไม่ /var/log/audit/audit.log อาจช่วยได้ (ถ้าเป็นที่ที่ Ubuntu ติดไว้นั่นคือตำแหน่ง RHEL / Fedora)


0

ฉันมีปัญหาเดียวกันกับ CentOs 6.7 ในกรณีของฉันมีการตั้งค่าสิทธิ์ทั้งหมดและยังคงเกิดข้อผิดพลาด ปัญหาคือ SE Linux อยู่ในโหมด "บังคับใช้"

ฉันเปลี่ยนเป็น "อนุญาต" โดยใช้คำสั่ง sudo setenforce 0

จากนั้นทุกอย่างก็ได้ผลสำหรับฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.