- Вопрос или проблема
- Ответ или решение
- Как разрешить ошибку –secure-file-priv в MySQL
- Шаги для разрешения проблемы
- 1. Проверьте значение переменной secure_file_priv
- 2. Переместите файл в разрешенную директорию
- 3. Используйте опцию LOCAL
- 4. Отключите secure-file-priv
- 5. Убедитесь в совместимости путей файлов
- Заключение
Вопрос или проблема
Я изучаю 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";
, чтобы увидеть настроенную директорию.
У вас есть два варианта:
- Переместите ваш файл в директорию, указанную в
secure-file-priv
. - Отключите
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):
- Остановите службу MySQL, перейдя в
services.msc
. - Перейдите в
C:\ProgramData\MySQL\MySQL Server 5.6
(ProgramData
был скрытой папкой в моем случае). - Откройте файл
my.ini
в блокноте. - Поиск ‘secure-file-priv’.
- Закомментируйте строку, добавив ‘#’ в начале строки. Для MySQL Server 5.7.16 и выше комментирование не сработает. Вам нужно установить его в пустую строку, как это –
secure-file-priv=""
- Сохраните файл.
- Запустите службу MySQL, перейдя в
services.msc
.
Если файл находится локально на вашем компьютере, используйте LOCAL в вашей команде
LOAD DATA LOCAL INFILE "text.txt" INTO table mytable;
То, что сработало для меня:
-
Поместите ваш файл внутри папки, указанной в
secure-file-priv
.Чтобы найти это, наберите:
mysql> show variables like "secure_file_priv";
-
Проверьте, есть ли у вас
local_infile = 1
.Сделайте это, набрав:
mysql> show variables like "local_infile";
Если вы получите:
+---------------+-------+ | Variable_name | Value | +---------------+-------+ | local_infile | OFF | +---------------+-------+
То установите его в одно, набрав:
mysql> set global local_infile = 1;
-
Укажите полный путь к вашему файлу. В моем случае:
mysql> load data infile "C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/file.txt" into table test;
Эта тема была просмотрена 570000 раз на момент этой публикации. Честно говоря, когда MySQL стал нашей чрезмерно защитной и неразумной мамой? Какое время, затрачиваемое на попытки обеспечения безопасности – что на самом деле только сковывает нас!
После многих поисков и множественных попыток всё потерпело неудачу.
Мое решение:
Что сработало для меня:
- Импортировать файл
.csv
через импорт PhpMyAdmin на старом сервере (если он большой, сделайте в командной строке) - Сгенерировать файл
.sql
. - Скачать файл
.sql
. - Импортировать файл
.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
.
- выключите
mysqld
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” Чтобы решить эту проблему, я сделал следующее.
- В поиске Windows (внизу слева) я ввел “powershell”.
- Щелкнул правой кнопкой мыши на PowerShell и запустил от имени администратора.
- Перешел в папку bin сервера. (C:\Program Files\MySQL\MySQL Server 5.6\bin);
- Ввел ./mysqld
- Нажал “Enter”
Сервер запустился, как и ожидалось.
Не меняя никаких конфигурационных файлов..
- узнайте значение
secure_file_priv
, используя команду, опубликованную @vhu:SHOW VARIABLES LIKE "secure_file_priv"
. - определите полный путь для вашего запроса, например:
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
может быть непростой задачей, но с правильными шагами и методами вы сможете без проблем загружать и экспортировать свои данные. Выбор подходящего решения будет зависеть от ваших конкретных условий и требований к безопасности.