MYSQL in Outfile "Zugriff verweigert" - aber mein Benutzer hat "ALL" Zugriff .. und der Ordner ist CHMOD 777

76

Irgendwelche Ideen?

SELECT * INTO OUTFILE '/home/myacnt/docs/mysqlCSVtest.csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '*'
LINES TERMINATED BY '\n'
FROM tbl_property 
WHERE managerGroupID = {$managerGroupID}

Error:

Access denied for user 'asdfsdf'@'localhost' (using password: YES)
Shackrock
quelle
3
"ALLE PRIVILEGIEN" enthält nicht alle Berechtigungen. In diesem Fall FILEist das für SELECT INTO OUTFILEAnweisungen erforderliche Privileg nicht enthalten . Ich hatte mehrere Probleme mit dieser Nichtübereinstimmung zwischen Englisch und MySQL: dba.stackexchange.com/a/96894/53784
WAF
Wenn Sie dann auf "Der MySQL-Server wird mit der Option --secure-file-priv ausgeführt, damit er diese Anweisung nicht ausführen kann" stoßen,
hinterhältiger

Antworten:

119

Versuchen Sie, diesen SQL-Befehl auszuführen:

> grant all privileges 
  on YOUR_DATABASE.* 
  to 'asdfsdf'@'localhost' 
  identified by 'your_password';
> flush privileges; 

Es scheint, dass Sie Probleme mit der Verbindung zur Datenbank haben und nicht in den Ordner schreiben, den Sie erwähnen.

Stellen Sie außerdem sicher, dass Sie dem FILEBenutzer gewährt haben 'asdfsdf'@'localhost'.

> GRANT FILE ON *.* TO 'asdfsdf'@'localhost';
Pablo Santa Cruz
quelle
1
@Shackrock: Überprüfen Sie die aktualisierte Antwort. Stellen Sie sicher, dass Sie FILEdem Benutzer gewährt haben .
Pablo Santa Cruz
48
Hier gibt es zwei Probleme. 1) GRANT ALL macht keine GRANT FILE. 2) GRANT FILE funktioniert nur mit *. * (Dh global). Beides sind Fehler in MySQL.
Fidschiaaron
4
Zu Ihrer Information, denken Sie sorgfältig darüber nach, bevor Sie dies tun. Sie sind nicht der Datenbankadministrator. Meins war nicht erfreut festzustellen, dass ich die Privilegien geändert hatte ("Nooooooo!"). :-)
Ellen Spertus
1
Es scheint auch Probleme beim Schreiben an andere Stellen im Dateisystem als / var / lib / mysql zu geben, was der Dokumentation zu widersprechen scheint. Auch wenn der Zielordner im Besitz von mysql: mysql ist und jeder über rwx-Berechtigungen verfügt und / oder mit sudo ... (hier von Ubuntu)
aufgerufen wird
2
Sie müssen nicht verwenden müssen FLUSH PRIVILEGESnach GRANT. Dies ist nur erforderlich, wenn Sie die Berechtigungstabelle mit SQL ändern, anstatt sie zu verwenden GRANT.
Barmar
56

Ehrlich gesagt habe ich mich nicht um die Stipendien gekümmert und das hat auch ohne die Privilegien funktioniert:

echo "select * from employee" | mysql --host=HOST --port=PORT --user=UserName --password=Password DATABASE.SCHEMA > output.txt
user1028904
quelle
5
Das liegt daran, dass Sie nur ein normales SELECT durchführen, kein SELECT INTO OUTFILE (in diesem Fall eine CSV-Datei).
Aqn
5
Dies ist eine schlechte Methode für größere Tabellen, da der Client die gesamte Ergebnismenge puffert, bevor er etwas in die Datei einfügt.
Chris Seline
6
MySQL begrenzt die Datei mit dieser Methode auf der Registerkarte, was perfekt ist. Nachdem Sie ein Dutzend Dateiberechtigungen, MySQL-Einstellungen und verschiedene Berechtigungen ausprobiert hatten, die sich über 5 oder 6 verschiedene Hilfeseiten erstreckten, funktionierte dies. Sparen Sie sich die Kopfschmerzen und nutzen Sie diese.
Paul Kenjora
Vergessen Sie nicht, vor Verwendung dieser Methode zur entsprechenden Codepage zu wechseln, z. B. "chcp 1252" oder "chcp 65001", wenn die exportierten Daten Sonderzeichen enthalten.
trapper_hag
Ein weiteres Problem dabei ist das Entkommen von NULL-Werten. Die Verwendung von INFILE aus der Ausgabe dieses Befehls führt dazu, dass das Zeichenfolgenliteral "NULL" anstelle eines tatsächlichen NULL importiert wird, das mit \ N maskiert wird.
Bluefear
22

Wie @fijaaron sagt,

  1. GRANT ALL bedeutet nicht GRANT FILE
  2. GRANT FILE funktioniert nur mit *.*

Dann mach's

GRANT FILE ON *.* TO user;
e18r
quelle
4

Da cP / WHM die Möglichkeit zum Ändern von Benutzerrechten als Root in PHPMyAdmin aufgehoben hat, müssen Sie die Befehlszeile verwenden, um:

mysql>  GRANT FILE ON *.* TO 'user'@'localhost';

Schritt 2 besteht darin, diesem Benutzer das Speichern einer Datei in einem bestimmten Ordner zu ermöglichen. Es gibt einige Möglichkeiten, dies zu tun, aber am Ende habe ich einen Ordner abgelegt:

/home/user/tmp/db

und

chown mysql:mysql /home/user/tmp/db

Dadurch kann der MySQL-Benutzer die Datei schreiben. Wie bereits in früheren Postern erwähnt, können Sie auch den temporären MySQL-Ordner verwenden. Ich nehme an, dass dies nicht wirklich wichtig ist, aber Sie möchten definitiv keine 0777-Berechtigung (weltweit beschreibbar) festlegen, es sei denn, Sie möchten, dass die Welt Ihre Daten sieht. Es gibt ein potenzielles Problem, wenn Sie den Vorgang spülen und wiederholen möchten, da dies INTO OUTFILEnicht funktioniert, wenn die Datei vorhanden ist. Wenn Ihre Dateien einem anderen Benutzer gehören, unlink($file)funktioniert der Versuch, dies zu tun, nicht. Wenn Sie wie ich sind (paranoid um 0777), können Sie Ihr Zielverzeichnis festlegen mit:

chmod($dir,0777)

also kurz vor dem SQL-Befehl

chmod($dir,0755)

unmittelbar danach, gefolgt von unlink(file)Löschen der Datei. Auf diese Weise läuft alles unter Ihrem Webbenutzer und Sie müssen den MySQL-Benutzer nicht aufrufen.

Grindlay
quelle
2

Ich habe alle Lösungen ausprobiert, aber es war immer noch nicht ausreichend. Nach einigem weiteren Graben stellte ich schließlich fest, dass ich auch das Flag 'file_priv' setzen und mysql neu starten musste.

Wieder aufzunehmen :

Gewähren Sie die Privilegien:

> GRANT ALL PRIVILEGES
  ON my_database.* 
  to 'my_user'@'localhost';

> GRANT FILE ON *.* TO my_user;

> FLUSH PRIVILEGES; 

Setzen Sie die Flagge:

> UPDATE mysql.user SET File_priv = 'Y' WHERE user='my_user' AND host='localhost';

Starten Sie zum Schluss den MySQL-Server neu:

$ sudo service mysql restart

Danach konnte ich in das secure_file_privVerzeichnis schreiben . Für mich war es / var / lib / mysql-files /, aber Sie können es mit dem folgenden Befehl überprüfen:

> SHOW VARIABLES LIKE "secure_file_priv";
Eino Gourdin
quelle
1

Für zukünftige Leser ist ein einfacher Weg wie folgt, wenn sie mit Bash in großen Mengen exportieren möchten:

akshay@ideapad:/tmp$ mysql -u someuser -p test -e "select * from offices"
Enter password: 
+------------+---------------+------------------+--------------------------+--------------+------------+-----------+------------+-----------+
| officeCode | city          | phone            | addressLine1             | addressLine2 | state      | country   | postalCode | territory |
+------------+---------------+------------------+--------------------------+--------------+------------+-----------+------------+-----------+
| 1          | San Francisco | +1 650 219 4782  | 100 Market Street        | Suite 300    | CA         | USA       | 94080      | NA        |
| 2          | Boston        | +1 215 837 0825  | 1550 Court Place         | Suite 102    | MA         | USA       | 02107      | NA        |
| 3          | NYC           | +1 212 555 3000  | 523 East 53rd Street     | apt. 5A      | NY         | USA       | 10022      | NA        |
| 4          | Paris         | +33 14 723 4404  | 43 Rue Jouffroy D'abbans | NULL         | NULL       | France    | 75017      | EMEA      |
| 5          | Tokyo         | +81 33 224 5000  | 4-1 Kioicho              | NULL         | Chiyoda-Ku | Japan     | 102-8578   | Japan     |
| 6          | Sydney        | +61 2 9264 2451  | 5-11 Wentworth Avenue    | Floor #2     | NULL       | Australia | NSW 2010   | APAC      |
| 7          | London        | +44 20 7877 2041 | 25 Old Broad Street      | Level 7      | NULL       | UK        | EC2N 1HN   | EMEA      |
+------------+---------------+------------------+--------------------------+--------------+------------+-----------+------------+-----------+

Wenn Sie von Nicht-Root-Benutzern exportieren, legen Sie die Berechtigung wie unten festgelegt fest

root@ideapad:/tmp# mysql -u root -p
MariaDB[(none)]> UPDATE mysql.user SET File_priv = 'Y' WHERE user='someuser' AND host='localhost';

Starten Sie mysqld neu oder laden Sie es neu

akshay@ideapad:/tmp$ sudo su
root@ideapad:/tmp#  systemctl restart mariadb

Beispielcode-Snippet

akshay@ideapad:/tmp$ cat test.sh 
#!/usr/bin/env bash

user="someuser"
password="password"
database="test"

mysql -u"$user" -p"$password" "$database" <<EOF
SELECT * 
INTO OUTFILE '/tmp/csvs/offices.csv' 
FIELDS TERMINATED BY '|' 
ENCLOSED BY '"' 
LINES TERMINATED BY '\n'
FROM offices;
EOF

Ausführen

akshay@ideapad:/tmp$ mkdir -p /tmp/csvs
akshay@ideapad:/tmp$ chmod +x test.sh
akshay@ideapad:/tmp$ ./test.sh 
akshay@ideapad:/tmp$ cat /tmp/csvs/offices.csv 
"1"|"San Francisco"|"+1 650 219 4782"|"100 Market Street"|"Suite 300"|"CA"|"USA"|"94080"|"NA"
"2"|"Boston"|"+1 215 837 0825"|"1550 Court Place"|"Suite 102"|"MA"|"USA"|"02107"|"NA"
"3"|"NYC"|"+1 212 555 3000"|"523 East 53rd Street"|"apt. 5A"|"NY"|"USA"|"10022"|"NA"
"4"|"Paris"|"+33 14 723 4404"|"43 Rue Jouffroy D'abbans"|\N|\N|"France"|"75017"|"EMEA"
"5"|"Tokyo"|"+81 33 224 5000"|"4-1 Kioicho"|\N|"Chiyoda-Ku"|"Japan"|"102-8578"|"Japan"
"6"|"Sydney"|"+61 2 9264 2451"|"5-11 Wentworth Avenue"|"Floor #2"|\N|"Australia"|"NSW 2010"|"APAC"
"7"|"London"|"+44 20 7877 2041"|"25 Old Broad Street"|"Level 7"|\N|"UK"|"EC2N 1HN"|"EMEA"

Akshay Hegde
quelle