Как мне решить проблему с –secure-file-priv в MySQL?

Вопрос или проблема

Я изучаю MySQL и пробовал использовать оператор LOAD DATA. Когда я использовал его следующим образом:

LOAD DATA INFILE "text.txt" INTO table mytable;

Я получил следующую ошибку:

Сервер MySQL работает с опцией –secure-file-priv, поэтому он не может выполнить это выражение

Как мне исправить эту ошибку?

Я проверил другой вопрос с таким же сообщением об ошибке, но все равно не могу найти решение.

Я использую MySQL 5.6

Все работает как задумано. Ваш сервер MySQL был запущен с опцией –secure-file-priv, которая ограничивает директории, из которых вы можете загружать файлы с помощью LOAD DATA INFILE.

Используйте SHOW VARIABLES LIKE "secure_file_priv";, чтобы увидеть настроенную директорию.

У вас есть два варианта:

  1. Переместите ваш файл в директорию, указанную в secure-file-priv.
  2. Отключите secure-file-priv. Это должно быть удалено из параметров запуска и не может быть изменено динамически. Для этого проверьте параметры запуска MySQL (в зависимости от платформы) и my.ini.

Я решил эту проблему, используя опцию LOCAL в команде:

LOAD DATA LOCAL INFILE "text.txt" INTO TABLE mytable;

Вы можете найти больше информации здесь.

Если указано LOCAL, файл считывается клиентской программой на клиентском хосте и отправляется на сервер. Файл можно указать как полное имя пути, чтобы указать его точное местоположение. Если указать его как относительное имя пути, имя интерпретируется относительно директории, в которой была запущена клиентская программа.

На Ubuntu 14 и Mysql 5.5.53 эта настройка, кажется, включена по умолчанию. Чтобы отключить ее, вам нужно добавить secure-file-priv = "" в ваш файл my.cnf в группе конфигурации mysqld. Например:

[mysqld]
secure-file-priv = ""

@vhu Я выполнил SHOW VARIABLES LIKE "secure_file_priv"; и он вернул C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\, поэтому, когда я ввел это, всё равно не сработало.

Когда я напрямую зашел в файл my.ini, я обнаружил, что путь немного по-другому отформатирован:

C:/ProgramData/MySQL/MySQL Server 8.0/Uploads

Затем, когда я запустил его с этим, все сработало. Единственное различие заключалось в направлении слэшей.

Я работаю на MySQL 5.7.11 на Debian, команда, которая сработала для меня, чтобы увидеть директорию, выглядит следующим образом:

mysql> SELECT @@global.secure_file_priv;

Вот что сработало для меня на Windows 7 для отключения secure-file-priv (Опция #2 из ответа vhu):

  1. Остановите службу MySQL, перейдя в services.msc.
  2. Перейдите в C:\ProgramData\MySQL\MySQL Server 5.6 (ProgramData был скрытой папкой в моем случае).
  3. Откройте файл my.ini в блокноте.
  4. Поиск ‘secure-file-priv’.
  5. Закомментируйте строку, добавив ‘#’ в начале строки. Для MySQL Server 5.7.16 и выше комментирование не сработает. Вам нужно установить его в пустую строку, как это – secure-file-priv=""
  6. Сохраните файл.
  7. Запустите службу MySQL, перейдя в services.msc.

Если файл находится локально на вашем компьютере, используйте LOCAL в вашей команде

LOAD DATA LOCAL INFILE "text.txt" INTO table mytable;

То, что сработало для меня:

  1. Поместите ваш файл внутри папки, указанной в secure-file-priv.

    Чтобы найти это, наберите:

    mysql> show variables like "secure_file_priv";  
    
  2. Проверьте, есть ли у вас local_infile = 1.

    Сделайте это, набрав:

    mysql> show variables like "local_infile";
    

    Если вы получите:

    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | local_infile  | OFF   |
    +---------------+-------+
    

    То установите его в одно, набрав:

    mysql> set global local_infile = 1;
    
  3. Укажите полный путь к вашему файлу. В моем случае:

    mysql> load data infile "C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/file.txt" into table test;
    

Эта тема была просмотрена 570000 раз на момент этой публикации. Честно говоря, когда MySQL стал нашей чрезмерно защитной и неразумной мамой? Какое время, затрачиваемое на попытки обеспечения безопасности – что на самом деле только сковывает нас!

После многих поисков и множественных попыток всё потерпело неудачу.
Мое решение:

Что сработало для меня:

  1. Импортировать файл .csv через импорт PhpMyAdmin на старом сервере (если он большой, сделайте в командной строке)
  2. Сгенерировать файл .sql.
  3. Скачать файл .sql.
  4. Импортировать файл .sql через MySQL Workbench.

Для версии MySQL 8.0 вы можете сделать следующее:

mysql.server stop
mysql.server start --secure-file-priv=''

Это сработало для меня на Mac High Sierra.

У меня была такая же проблема с ‘secure-file-priv’. Закомментирование в .ini файле не сработало, как и перемещение файла в директорию, указанную ‘secure-file-priv’.

В конце концов, как предложил dbc, установка ‘secure-file-priv’ равным пустой строке сработала. Так что, если кто-то застрял после того, как попробовал ответы выше, надеюсь, это поможет.

Если вы работаете на Ubuntu, вам также может потребоваться настроить Apparmor, чтобы разрешить MySQL запись в вашу папку, например, вот моя конфигурация:

Добавьте эту строку в файл /etc/apparmor.d/usr.sbin.mysqld :

/var/lib/mysql-files/* rw

Затем добавьте эти 2 конфигурационные строки в секции /etc/mysql/my.cnf:

[client]
loose-local-infile = 1

[mysqld]
secure-file-priv = ""

Вот мой SQL:

select id from blahs into outfile '/var/lib/mysql-files/blahs';

Это сработало для меня. Удачи!

У меня были все sorts проблем с этим. Я менял my.cnf и всякие безумные вещи, которые другие версии этой проблемы пытались показать.

Что сработало для меня:

Ошибка, которую я получал

Сервер MySQL работает с опцией --secure-file-priv, поэтому он не может выполнить это выражение

Я смог это исправить, открыв /usr/local/mysql/support-files/mysql.server и изменив следующую строку:

$bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" -- $other_args >/dev/null &
  wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?

на

$bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" --secure-file-priv="" $other_args >/dev/null &
  wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?

Я создал скрипт импорта NodeJS, если вы работаете с nodeJS и ваши данные в следующем формате (двойная кавычка + запятая и \n новая строка)

INSERT INTO <your_table> VALUEs( **CSV LINE **)

Этот скрипт настроен на выполнение по адресу http://localhost:5000/import.

Он идет построчно и создает строку запроса

"city","city_ascii","lat","lng","country","iso2","iso3","id"
"Tokyo","Tokyo","35.6850","139.7514","Japan","JP","JPN","1392685764",
...

server.js

const express = require('express'),
   cors = require('cors'),
   bodyParser = require('body-parser'),
   cookieParser = require('cookie-parser'),
   session = require('express-session'),
   app = express(),
   port = process.env.PORT || 5000,
   pj = require('./config/config.json'),
   path = require('path');

app.use(bodyParser.json());
app.use(cookieParser());
app.use(cors());

app.use(
   bodyParser.urlencoded({
      extended: false,
   })
);

var Import = require('./routes/ImportRoutes.js');

app.use('/import', Import);
if (process.env.NODE_ENV === 'production') {
   // установить статическую папку
   app.use(express.static('client/build'));

   app.get('*', (req, res) => {
      res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
   });
}

app.listen(port, function () {
   console.log('Сервер работает на порту: ' + port);
});

ImportRoutes.js

const express = require('express'),
   cors = require('cors'),
   fs = require('fs-extra'),
   byline = require('byline'),
   db = require('../database/db'),
   importcsv = express.Router();

importcsv.use(cors());

importcsv.get('/csv', (req, res) => {

   function processFile() {
      return new Promise((resolve) => {
         let first = true;
         var sql, sqls;
         var stream = byline(
            fs.createReadStream('../PATH/TO/YOUR!!!csv', {
               encoding: 'utf8',
            })
         );

         stream
            .on('data', function (line, err) {
               if (line !== undefined) {
                  sql="INSERT INTO <your_table> VALUES (" + line.toString() + ');';
                  if (first) console.log(sql);
                  first = false;
                  db.sequelize.query(sql);
               }
            })
            .on('finish', () => {
               resolve(sqls);
            });
      });
   }

   async function startStream() {
      console.log('начат поток');
      const sqls = await processFile();
      res.end();
      console.log('ВСЁ ГОТОВО');
   }

   startStream();
});

module.exports = importcsv;

db.js – это файл конфигурации

const Sequelize = require('sequelize');
const db = {};
const sequelize = new Sequelize(
   config.global.db,
   config.global.user,
   config.global.password,
   {
      host: config.global.host,
      dialect: 'mysql',
      logging: console.log,
      freezeTableName: true,

      pool: {
         max: 5,
         min: 0,
         acquire: 30000,
         idle: 10000,
      },
   }
);

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Отказ от ответственности: Это не идеальное решение – я просто публикую это для разработчиков, которые работают под временными рамками и имеют много данных для импорта и сталкиваются с этой нелепой проблемой. Я потратил много времени на это и надеюсь сэкономить другое время разработчика.

MySQL использует эту системную переменную для управления тем, откуда вы можете импортировать свои файлы

mysql> SHOW VARIABLES LIKE "secure_file_priv";
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv | NULL  |
+------------------+-------+

Итак, проблема в том, как изменить системные переменные, такие как secure_file_priv.

  1. выключите mysqld
  2. sudo mysqld_safe --secure_file_priv=""

Теперь вы можете видеть это:

mysql> SHOW VARIABLES LIKE "secure_file_priv";
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv |       |
+------------------+-------+

На macOS Catalina я следовал следующим шагам, чтобы установить secure_file_priv

1. Остановите службу MySQL

 sudo /usr/local/mysql/support-files/mysql.server stop

2. Перезапустите MySQL, назначая системные переменные –secure_file_priv

sudo /usr/local/mysql/support-files/mysql.server start --secure-file-priv=YOUR_FILE_DIRECTORY

Примечание: добавление пустого значения исправило проблему для меня, и MySQL будет экспортировать данные в директорию /usr/local/mysql/data/YOUR_DB_TABLE/EXPORT_FILE

sudo /usr/local/mysql/support-files/mysql.server start --secure-file-priv=

Спасибо

sudo /usr/local/mysql/support-files/mysql.server start --secure-file-priv='' --local-infile

Это сработало для указанного пути на моем компьютере; вам, возможно, придется изменить ваш путь.

Затем используйте:

mysql -u root -p

Одним важным пунктом является то, что ваш CSV должен находиться в папке данных MySQL. На моем компьютере он находится по адресу: /usr/local/mysql-8.0.18-macos10.14-x86_64/data

Вы можете изменить разрешения папки, если необходимо, чтобы положить CSV в папку данных.

Настройка:
macOS Catalina версии 10.15.5
MySQL версии 8.0.18

Вот объяснение secure_file_priv:

А вот объяснение LOAD DATA:

В моем случае используется MySQL из официального образа Docker, поэтому мне нужно было разобраться, как установить secure_file_priv.

  • Чтобы лучше понять, что такое secure_file_priv, я прочитал о нем по ссылке выше;
  • И прочитал, что говорит DockerHub о MySQL, https://hub.docker.com/_/mysql

Чтобы узнать (docker) mysql по умолчанию:

$ docker run -it --rm mysql --verbose --help
Переменные (--variable-name=value)
и логические опции {FALSE|TRUE}          Значение (после считывания параметров)
----------------------------------------- -----------------------------
...
local-infile                              FALSE
...
secure-file-priv                          NULL
...

На самом деле, (внутри контейнера,) конфигурационный файл говорит:

root@a2b1e0c46541:/# cat /etc/mysql/my.cnf
#
# (...лицензия...)
#
# Файл конфигурации сервера MySQL.
#
# Для объяснений смотрите
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL

# Пользовательская конфигурация должна располагаться здесь
!includedir /etc/mysql/conf.d/

Используя официальный образ (как объяснено в README):

$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=secret -d mysql \
         --secure_file_priv=/data

Если вы хотите разрешить загрузку LOCAL INFILE, определите также опцию local_infile=TRUE.

Теперь вы должны иметь возможность LOAD DATA INFILE '/data/data.csv' INTO TABLE some_table.

ПРИМЕЧАНИЕ: В той же задаче — как только была решена проблема “INFILE” (выше) — я столкнулся с проблемами с пустыми значениями в моих данных CSV, на которые ответ (и вопрос) оказался очень полезным: https://stackoverflow.com/a/5968530/687896 .

В Linux вам нужно отредактировать файл my.cnf в

/etc/mysql/my.cnf

и изменить параметр 26 номер строки следующим образом:

secure-file-priv= <ваш путь к данным, например /home/user/data>

Затем перезапустите MySQL и попробуйте снова.

в docker
вам нужно смонтировать ваш файл my.cnf с файлом my.cnf в вашем контейнере с этой командой в docker-compose или добавить вручную:

volumes:
  - ./persistent:/var/lib/mysql
  - ./conf/my.cnf:/etc/mysql/my.cnf

затем измените /conf/my.cnf на вашем хосте и настройте параметр secure-file-priv как в предыдущем подходе, кроме того, вам нужно смонтировать ваши данные в контейнере mysql и установить этот путь для параметра secure-file-priv, перезапустить ваши службы, и наконец, вы сможете загрузить ваши данные.

вы можете проверить вашу конфигурацию с помощью этой команды :

SHOW VARIABLES LIKE "secure_file_priv";

Я добавил LOCAL в команду, но это создало еще одну проблему:

Загрузка локальных данных отключена - это должно быть включено как на клиентской, так и на серверной стороне

Для решения этой проблемы я просто следовал трем шагам по здесь

У меня возникла эта проблема на Windows 10. “–secure-file-priv в MySQL” Чтобы решить эту проблему, я сделал следующее.

  1. В поиске Windows (внизу слева) я ввел “powershell”.
  2. Щелкнул правой кнопкой мыши на PowerShell и запустил от имени администратора.
  3. Перешел в папку bin сервера. (C:\Program Files\MySQL\MySQL Server 5.6\bin);
  4. Ввел ./mysqld
  5. Нажал “Enter”

Сервер запустился, как и ожидалось.

Не меняя никаких конфигурационных файлов..

  1. узнайте значение secure_file_priv, используя команду, опубликованную @vhu: SHOW VARIABLES LIKE "secure_file_priv".
  2. определите полный путь для вашего запроса, например: select * from table into outfile 'secure_file_priv_PATH/OUTPUT-FILE' ... остальная часть вашего запроса

это сработало для меня в mysql-shell на ubuntu 18.04 LTS mysql 5.7.29

Для MacOS Mojave, работающего на MySQL 5.6.23, у меня возникла эта проблема с записью файлов, но не с загрузкой их. (Не видно с предыдущими версиями Mac OS). Поскольку большинство ответов на этот вопрос касались других систем, я подумал, что опубликую файл my.cnf, который решил эту (и проблемы с сокетом тоже), на случай, если это поможет другим пользователям Mac. Это /etc/my.cnf

[client]
default-character-set=utf8

[mysqld]
character-set-server=utf8
secure-file-priv = ""
skip-external-locking

(Интернационализация не имеет отношения к вопросу.)

Ничего больше не требуется. Просто выключите сервер MySQL, а затем снова включите его в параметрах (мы говорим о Mac), чтобы это подействовало.

Я столкнулся с той же проблемой здесь, ERRORCODE 2. Да, большинство ответов имеют смысл, однако я попробовал самый простой метод :

Я использовал двойные слэши в пути к файлу.

мой пример пути с полным запросом >> ПОПРОБУЙТЕ это и, пожалуйста, дайте знать, если это сработало для вас.

LOAD DATA LOCAL INFILE “E:\Irfan One Drive\OneDrive – Qtech\Documents\Suppliers\HB\Extended\HotelTransferZone.csv”
INTO TABLE temp_hb_transfer
FIELDS TERMINATED BY ‘|’
OPTIONALLY ENCLOSED BY ‘”‘
LINES TERMINATED BY ‘\n’

В Ubuntu 20.04:
Запустите следующую команду, чтобы найти my.cnf в системе:

commandlocate my.cnf

Теперь: отредактируйте этот файл

sudo vim /etc/mysql/my.cnf

Добавьте следующую строку в конце:

[mysqld]
secure-file-priv = ""

Теперь вы можете импортировать файлы, эта ошибка будет устранена.
Или вы можете использовать файл Mysql Workbench для импорта:
ссылка: https://blog.skyvia.com/how-to-import-csv-file-into-mysql-table-in-4-different-ways/

Для OSX Sonoma с установкой homebrew, вот что мне нужно было сделать:

% mysql --help | grep -A2 "Default options are read”
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /opt/homebrew/etc/my.cnf ~/.my.cn

/etc/my.cnf не существует. /etc/mysql/my.cnf не существует. Но /opt/homebrew/etc/my.cnf уже существует. Я отредактировал и добавил опцию, показанную в других ответах (secure-file-priv):

[mysqld]
bind-address = 127.0.0.1
mysqlx-bind-address = 127.0.0.1
secure-file-priv = ""

Затем

brew services stop mysql
brew services start mysql

Затем подключился к базе данных с помощью mysql cli и выполнил:

SELECT * FROM mytable
INTO OUTFILE '/Users/myuser/Downloads/mytable.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '\"'
LINES TERMINATED BY '\n’;

И это сработало.

Ответ или решение

Как разрешить ошибку –secure-file-priv в MySQL

Когда вы работаете с MySQL и пытаетесь использовать команду LOAD DATA, вы можете столкнуться с ошибкой:

The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

Это сообщение об ошибке указывает на то, что сервер MySQL был запущен с параметром --secure-file-priv, который ограничивает доступ к файлам для загрузки всего лишь из определенных директорий.

Шаги для разрешения проблемы

Чтобы справиться с этой ошибкой, вам предстоит рассмотреть несколько вариантов:

1. Проверьте значение переменной secure_file_priv

Первым шагом является проверка текущего значения переменной secure_file_priv. Это можно сделать с помощью следующей SQL-команды:

SHOW VARIABLES LIKE 'secure_file_priv';

Эта команда вернет директорию, из которой MySQL позволяет загружать файлы. Если значение равно NULL, это означает, что файлы могут быть загружены из любого места.

2. Переместите файл в разрешенную директорию

Если вы получили путь к директории в результате предыдущей команды, вам нужно переместить ваш файл (например, text.txt) в эту директорию. После перемещения файла, убедитесь, что вы указали его полное имя (включая путь) в вашей команде LOAD DATA:

LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/text.txt' INTO TABLE mytable;

3. Используйте опцию LOCAL

Если ваш файл находится на локальной машине и вы не хотите перемещать его в заданную директорию, вы можете использовать опцию LOCAL в команде LOAD DATA. Пример:

LOAD DATA LOCAL INFILE 'text.txt' INTO TABLE mytable;

Однако стоит отметить, что использование этой опции требует, чтобы как сервер, так и клиент имели включенную настройку local_infile. Убедитесь в этом с помощью:

SHOW VARIABLES LIKE 'local_infile';

Если значение равно OFF, вы можете включить его следующим образом:

SET GLOBAL local_infile = 1;

4. Отключите secure-file-priv

Если вы решите отключить параметр secure-file-priv, имейте в виду, что это может снизить безопасность и должно быть сделано только если вы точно знаете, что это необходимо для вашего окружения. Для этого вам нужно будет отредактировать конфигурационный файл MySQL (например, my.cnf или my.ini):

[mysqld]
secure-file-priv=""

После изменения файла необходимо перезапустить сервер MySQL, чтобы изменения вступили в силу:

sudo systemctl restart mysql

5. Убедитесь в совместимости путей файлов

Иногда ошибки могут возникать из-за несовместимости формата пути. Убедитесь, что используете правильный формат для операционной системы (например, двойные обратные слеши для Windows, одинарные прямые слеши в Unix-системах).

Заключение

Работа с MySQL и параметром secure-file-priv может быть непростой задачей, но с правильными шагами и методами вы сможете без проблем загружать и экспортировать свои данные. Выбор подходящего решения будет зависеть от ваших конкретных условий и требований к безопасности.

Оцените материал
Добавить комментарий

Капча загружается...