Làm cách nào tôi có thể sử dụng MySQL Errcode 13 với SELECT INTO OUTFILE?


114

Tôi đang cố gắng kết xuất nội dung của bảng vào tệp csv bằng cách sử dụng câu lệnh MySQL SELECT INTO OUTFILE. Nếu tôi làm:

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

outfile.csv sẽ được tạo trên máy chủ trong cùng thư mục mà tệp của cơ sở dữ liệu này được lưu trữ.

Tuy nhiên, khi tôi thay đổi truy vấn của mình thành:

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

Tôi có:

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

Errcode 13 là một lỗi quyền, nhưng tôi vẫn nhận được nó ngay cả khi tôi thay đổi quyền sở hữu / dữ liệu thành mysql: mysql và cấp cho nó 777 quyền. MySQL đang chạy với tư cách người dùng "mysql".

Kỳ lạ là tôi có thể tạo tệp trong / tmp, không phải trong bất kỳ thư mục nào khác mà tôi đã thử, ngay cả với các quyền được thiết lập để người dùng mysql có thể ghi vào thư mục.

Đây là MySQL 5.0.75 chạy trên Ubuntu.


3
Xem như số 13 là lỗi hệ thống, đây có thể không phải là nó, nhưng có một cài đặt mySQL giới hạn INTO OUTFILE vào một thư mục: dev.mysql.com/doc/refman/5.0/en/… có thể đáng để xem nhanh. đặt thành /tmp.
Pekka

Biến đó trống trên cài đặt của tôi, theo tài liệu đó có nghĩa là các thư mục đầu ra của tôi không được giới hạn.
Ryan Olson

Câu trả lời:


189

Đây là phiên bản cụ thể nào của Ubuntu và đây có phải là Phiên bản Ubuntu Server không?

Các phiên bản Ubuntu Server gần đây (chẳng hạn như 10.04) đi kèm với AppArmor và hồ sơ của MySQL có thể ở chế độ thực thi theo mặc định. Bạn có thể kiểm tra điều này bằng cách thực hiện sudo aa-statusnhư sau:

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

Nếu mysqld được bao gồm trong chế độ thực thi, thì nó có thể là chế độ từ chối ghi. Các mục nhập cũng sẽ được ghi /var/log/messageskhi AppArmor chặn việc ghi / truy cập. Những gì bạn có thể làm là chỉnh sửa /etc/apparmor.d/usr.sbin.mysqldvà thêm /data//data/*gần cuối như vậy:

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

Và sau đó làm cho AppArmor tải lại các cấu hình.

# sudo /etc/init.d/apparmor reload

CẢNH BÁO: thay đổi ở trên sẽ cho phép MySQL đọc và ghi vào thư mục / data. Chúng tôi hy vọng bạn đã xem xét các tác động bảo mật của điều này.


2
Tôi ghét phải chỉ ra điều này, nhưng có lý do App Armor không cho phép điều này. MySQL hiện có khả năng sửa đổi và đọc bất kỳ thứ gì trong thư mục / data. Chỉ cần không bị hack ngay bây giờ.
Ryan Ward

2
@Serdar, Bộ quy tắc AppArmor MySQL được phân phối với bản phân phối không cho phép nó theo mặc định . Điều này có ý nghĩa vì nó là một quy tắc cơ bản tốt để cài đặt mới. Tôi tin rằng chúng ta nên được và được phép sửa đổi các bộ quy tắc để phù hợp với nhu cầu của chúng ta sau khi cài đặt. Ý định ban đầu của người hỏi là cho phép MySQL ghi vào các thư mục cụ thể. Nhưng nếu nó không rõ ràng ở trên, một lưu ý cho những người gặp phải giải pháp này: CẢNH BÁO: thay đổi ở trên sẽ cho phép MySQL đọc và ghi vào thư mục / data. Chúng tôi hy vọng bạn đã xem xét các tác động bảo mật của điều này.
Vin-G

1
CÂU TRẢ LỜI CHÍNH XÁC!!! Nó đã giải quyết được vấn đề của tôi, tôi cũng đang cố gắng viết trong bất kỳ thư mục nào khác. Bây giờ, tôi phải nghiên cứu xem tất cả những điều này là gì! :) Tìm hiểu về điều này, tôi khuyên những người khác nên đọc về apparmor (và do đó, lệnh aa-status): en.wikipedia.org/wiki/AppArmor
David L

1
Trong trường hợp của tôi, điều này đã hữu ích: /your/abs/folder/ r, /your/abs/folder/** rwk, }đừng quên thêm dấu phẩy ở cuối!
ACV

1
nó hoạt động để viết trong / tmp. Sử dụng cửa sổ để thay thế. Linux tệ
Victor Ionescu

17

Ubuntu sử dụng AppArmor và điều đó ngăn bạn truy cập / data /. Fedora sử dụng selinux và điều đó sẽ ngăn chặn điều này trên máy RHEL / Fedora / CentOS.

Để sửa đổi AppArmor để cho phép MySQL truy cập / dữ liệu / làm như sau:

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

thêm dòng này vào bất cứ đâu trong danh sách thư mục:

/data/ rw,

sau đó làm một:

sudo /etc/init.d/apparmor restart

Một tùy chọn khác là tắt hoàn toàn AppArmor cho mysql, điều này KHÔNG ĐƯỢC KHUYẾN CÁO :

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

Đừng quên khởi động lại ứng dụng:

sudo /etc/init.d/apparmor restart


Để AppArmor thực sự vô hiệu hóa cho mysql tôi cần phải làm: cyberciti.biz/faq/ubuntu-linux-howto-disable-apparmor-commands
silver_mx

14

Tôi biết bạn nói rằng bạn đã thử đặt quyền thành 777, nhưng tôi có bằng chứng cho thấy đối với tôi đó là vấn đề về quyền, tôi đang đăng những gì tôi thực hiện chính xác với hy vọng nó có thể giúp ích. Đây là kinh nghiệm của tôi:

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 tổng cộng 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 Nhập mật khẩu: mysqldump: Có lỗi: 1: Không thể tạo / ghi vào tệp '/data/dumptest/test.txt' (Mã lỗi: 13) khi thực hiện 'CHỌN VÀO OUTFILE 'me @ server: / data $ sudo chmod a + rwx dumptest / me @ server: / data $ mysqldump -u dbuser -p -T dumptest -B db_name --tables test Nhập mật khẩu: mysqldump: Có lỗi: 1: ( cùng một lỗi)
Ryan Olson

Oy, tốt, không nhận ra nhận xét sẽ không định dạng, nhưng đã kiểm tra kỹ một số cách khác nhau. Đầu tiên với thư mục đích thuộc sở hữu của mysql: mysql, sau đó với thư mục đích do người dùng sở hữu mà tôi đang chạy lệnh kết xuất, cả hai cách vẫn cho tôi cùng một lỗi quyền.
Ryan Olson

Đối với hồ sơ, điều này làm việc cho tôi mặc dù đã thay đổi các điều khoản AppArmor
Alex

Tôi đã thử sửa đổi ứng dụng, nó không hoạt động. Thay đổi quyền 'chmod 777' đã làm việc cho tôi!
Sudarshan_SMD

7

MySQL đang trở nên ngu ngốc ở đây. Nó cố gắng tạo các tệp dưới / tmp / data / .... Vì vậy, những gì bạn có thể làm như sau:

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

Sau đó, hãy thử truy vấn của bạn. Điều này đã làm việc cho tôi sau nhiều giờ gỡ lỗi vấn đề.


Tôi thích câu trả lời này nhất. Nó rất dễ dàng, nó hoạt động và nó không yêu cầu bạn tương lai với ứng dụng. Cách làm khác bằng cách sử dụng đường ống không hoạt động tốt đối với hàng xuất khẩu lớn vì tất cả các bộ đệm được thực hiện.
Chris Seline

6

Vấn đề này đã làm phiền tôi trong một thời gian dài. Tôi nhận thấy rằng cuộc thảo luận này không chỉ ra giải pháp trên RHEL / Fecora. Tôi đang sử dụng RHEL và tôi không tìm thấy các tệp cấu hình tương ứng với AppArmer trên Ubuntu, nhưng tôi đã giải quyết vấn đề của mình bằng cách đặt MỌI thư mục trong thư mục PATH có thể đọc và truy cập được bằng mysql. Ví dụ: nếu bạn tạo một thư mục / tmp, hai lệnh sau làm cho SELECT INTO OUTFILE có thể xuất ra tệp .sql VÀ .sql

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

Nếu bạn tạo một thư mục trong thư mục chính / home / tom, bạn phải thực hiện việc này cho cả / home và / home / tom.


3
Sử dụng / tmp làm ví dụ không phải là một ý tưởng hay và bạn thực sự không muốn thay đổi quyền sở hữu của thư mục / tmp (trong hầu hết các trường hợp).
sastorsl

Thay đổi quyền sở hữu / tmp là không tốt, nhưng tạo một thư mục tạm thời bên trong / tmp và chown mysql:mysqlgiải quyết vấn đề của tôi
Samuel Prevost

6

Bạn có thể làm được việc này :

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

Cảm ơn! Có thể kiểm soát đầu ra dưới dạng CSV không?
Hamman Samuel

4

Một số điều cần thử:

  • secure_file_priv biến hệ thống thiết lập? Nếu có, tất cả các tệp phải được ghi vào thư mục đó.
  • đảm bảo rằng tệp không tồn tại - MySQL sẽ chỉ tạo tệp mới, không ghi đè lên tệp hiện có.

1
Tôi cũng sẽ sử dụng secure_file_priv. Nếu tệp đã tồn tại, thông báo lỗi sẽ khác (không phải mã lỗi 13).
Xavier Maillard

secure_file_priv hiện chưa được đặt, vì vậy tôi hiểu điều đó có nghĩa là tôi không bị giới hạn về nơi tôi có thể ghi tệp. Tôi có hiểu nhầm điều đó không và tôi có cần đặt nó thành một cái gì đó như '/' một cách rõ ràng nếu tôi muốn có thể ghi ở bất kỳ đâu trên hệ thống tệp không?
Ryan Olson

Ngoài ra, tôi đang kiểm tra xem tệp không tồn tại trước khi chạy truy vấn.
Ryan Olson

Cảm ơn vì bạn đã phản hồi. Dựa trên những phát hiện của bạn, tôi không nghĩ rằng một trong những đề xuất này gây ra sự cố của bạn.
mdma

3

Tôi gặp sự cố tương tự và tôi đã khắc phục sự cố này bằng các bước sau:

  • Hệ điều hành: ubuntu 12.04
  • đèn được lắp đặt
  • giả sử thư mục của bạn để lưu tệp đầu ra là: / var / www / csv /

Thực hiện lệnh sau trên terminal và chỉnh sửa tệp này bằng trình chỉnh sửa gedit để thêm thư mục của bạn vào tệp đầu ra.

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

  • bây giờ tệp sẽ được mở trong trình chỉnh sửa, vui lòng thêm thư mục của bạn vào đó

    / var / www / csv / * rw,

  • tương tự như vậy, tôi đã thêm vào tệp của mình, như hình ảnh sau:

nhập mô tả hình ảnh ở đây

Thực hiện lệnh tiếp theo để khởi động lại dịch vụ:

sudo /etc/init.d/apparmor khởi động lại

Ví dụ: tôi thực hiện truy vấn sau vào trình tạo truy vấn phpmyadmin để xuất dữ liệu trong tệp csv

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

Nó đã thực hiện thành công và ghi tất cả các hàng với các cột đã chọn vào tệp OUTPUT.csv ...


2

Trong trường hợp của tôi, giải pháp là làm cho mọi thư mục trong đường dẫn thư mục có thể đọc được và có thể truy cập bằng mysql( chmod a+rx). Thư mục vẫn được chỉ định bởi đường dẫn tương đối của nó trong dòng lệnh.

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

2

Tôi vừa gặp phải vấn đề tương tự. Vấn đề của tôi là thư mục mà tôi đang cố gắng đưa vào không có quyền ghi cho quy trình mysqld. Kết xuất sql ban đầu sẽ được ghi ra nhưng việc ghi tệp csv / txt sẽ không thành công. Có vẻ như kết xuất sql chạy với tư cách người dùng hiện tại và chuyển đổi sang csv / txt được chạy với tư cách người dùng đang chạy mysqld. Vì vậy, thư mục cần quyền ghi cho cả hai người dùng.


1

Bạn cần cung cấp một đường dẫn tuyệt đối, không phải một đường dẫn tương đối.

Cung cấp đường dẫn đầy đủ đến thư mục / data mà bạn đang cố gắng ghi vào.


Đó trông giống như một con đường tuyệt đối đối với tôi. Không phải nó?
Pekka

2
Hãy thử điều này với tư cách là người dùng mysql để xác minh rằng bạn có thể tạo tệp bên ngoài mysql:touch /data/outfile.csv
Ike Walker

1
Đầu tiên, tôi không thể làm điều đó vì trình bao của người dùng mysql được đặt thành / bin / false, vì vậy tôi không thể đăng nhập bằng mysql. Chỉ để đảm bảo rằng điều đó không góp phần vào vấn đề, tôi đã đặt shell của mysql thành / bin / bash, su'd cho người dùng đó và chạm vào một tệp trong / data. Tệp đã được tạo thành công, thuộc sở hữu của mysql.
Ryan Olson

3
Bạn có thể truy cập tài khoản ngay cả khi tài khoản đó đang sử dụng một trong các trình bao "vô hiệu hóa": su --shell=/bin/sh nameofaccount
Marc B

Cảm ơn, tôi đã không biết về điều đó.
Ryan Olson

1

Ubuntu có sử dụng SELinux không? Kiểm tra xem nó có được bật và thực thi hay không. /var/log/audit/audit.log có thể là trợ giúp (nếu đó là nơi Ubuntu gắn nó - đó là vị trí RHEL / Fedora).


0

Tôi đã gặp sự cố tương tự trên CentOs 6.7 Trong trường hợp của tôi, tất cả các quyền đã được đặt và vẫn xảy ra lỗi. Vấn đề là SE Linux đang ở chế độ "thực thi".

Tôi đã chuyển nó thành "cho phép" bằng lệnh sudo setenforce 0

Sau đó, mọi thứ đã ổn thỏa với tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.