Фон:
Я переместил некоторые сайты с общего хостинга на VPS. Все работает очень гладко, за исключением тех строк кода php, которые выполняют запросы с LOAD DATA LOCAL INFILE, используя источники данных с внешних серверов (т.е. http://server1.net/getfile.php?f=101). Этот код работает (и работал в течение длительного времени) на учетной записи общего хостинга, однако эта учетная запись достигает ограничений по ресурсам, особенно в области размера / скорости базы данных.
Проблема:
Код с LOAD DATA INFILE, который загружается с адреса http: //, больше не работает после перемещения на (новый) VPS.
Система и программное обеспечение:
VPS используется в качестве веб-сервера, на котором, среди прочего, работает Ubuntu (Ubuntu 14.04) с Vesta (0.9.8 (amd64)), apache, nginx, mysql (5.5.44), app-armor. Все недавно установлено и очень мало или не изменено.
Выбор из вывода phpinfo ():
System Linux MyServer 3.13.0-62-generic #102-Ubuntu SMP Tue Aug 11 14:29:36 UTC 2015 x86_64
Apache Version Apache/2.4.7 (Ubuntu) mod_fcgid/2.3.9 PHP/5.5.9-1ubuntu4.11 OpenSSL/1.0.1f
Server Root /etc/apache2
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SERVER_SOFTWARE Apache/2.4.7 (Ubuntu) mod_fcgid/2.3.9 PHP/5.5.9-1ubuntu4.11 OpenSSL/1.0.1f
allow_url_fopen On On
allow_url_include Off
doc_root no value
docref_ext no value
docref_root no value
file_uploads On
open_basedir no value
sys_temp_dir /tmp
upload_tmp_dir /tmp
user_dir no value
cURL support enabled
mysql
Directive Local Value Master Value
mysql.allow_local_infile On On
mysqli
Directive Local Value Master Value
mysqli.allow_local_infile On On
Несколько строк из /etc/mysql/my.cnf
[client]
loose-local-infile=1
local-infile=1
[mysqld]
basedir=/usr
datadir=/var/lib/mysql
tmpdir=/tmp
local-infile=1
Ниже код работает в том же каталоге, что и файл с phpinfo()
Тестовый код:
$url = "http://myserver.net/x.csv";
$file = "/var/lib/mysql/test2.csv";
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
/* Get the HTML or whatever is linked in $url. */
$response = curl_exec($handle);
/* Check for 404 (file not found). */
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
echo("<br>Http code: ". $httpCode);
curl_close($handle);
echo "<br>Temp_name: ". $_FILES["file"]["tmp_name"];
echo "<br>Host info: " . $conn->host_info . "\n";
echo "<br>Client info: ".mysqli_get_client_info($conn) ."\n";
$conn = mysqli_init();
if (!$conn) {
die('mysqli_init failed');
}
if (!$conn->options(MYSQLI_OPT_LOCAL_INFILE, true)) {
die('Setting MYSQLI_OPT_LOCAL_INFILE failed');
}
if (!$conn->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5)) {
die('Setting MYSQLI_OPT_CONNECT_TIMEOUT failed');
}
if (!$conn->real_connect('localhost','root','pass','database')) {
die('Connect Error (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
$conn->query("LOAD DATA INFILE '". $file ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error file: " . mysqli_error($conn));
$conn->query("LOAD DATA INFILE '". $url ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error url: " . mysqli_error($conn));
$conn->query("LOAD DATA LOCAL INFILE '". $file ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error file (LOCAL): " . mysqli_error($conn));
$conn->query("LOAD DATA LOCAL INFILE '". $url ."' INTO TABLE x_import (@col1) SET ID = @col1;");
echo("<br>Error url (LOCAL): " . mysqli_error($conn));
$conn->query("SELECT * INTO OUTFILE 'andreas.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\n' FROM x_import;");
echo("<br>Error OutFile: " . mysqli_error($conn));
Результат кода:
Http code: 200
Temp_name:
Host info:
Client info: 5.5.44
Error file:
Error url: Can't get stat of '/var/lib/mysql/http:/myserver.net/x.csv' (Errcode: 2)
Error file (LOCAL): File '/var/lib/mysql/test2.csv' not found (Errcode: 13)
Error url (LOCAL): File 'http:/myserver.net/x.csv' not found (Errcode: 2)
Error OutFile: File 'andreas.txt' already exists
В php-коде используется root-аккаунт с mysql, поэтому полного доступа / привилегий нет.
Первая строка с кодом SQL (LOAD DATA INFILE без LOCAL с использованием локального файла) правильно добавляет данные из файла в базу данных.
Последняя строка с кодом INTO OUTFILE правильно создает файл в / var / lib / mysql / database / (и 2-й раз дает уже существующую ошибку)
Из всех исследований до сих пор я понимаю:
Я не понимаю, почему в URL-адресе отсутствует / отсутствует при использовании LOCAL (см. Вывод кода). Я также не понимаю, почему возникает код ошибки 13, когда LOCAL добавляется к URL (php получает код 200 в первой части кода). Мне кажется, что и php, и mysql не могут посмотреть в нужном месте по нескольким причинам.
Ниже я объясню несколько попыток многих вещей, которые я пробовал (в основном из множества других ответов на этом сайте):
Я изменил права доступа к файлам для / var / и / var / lib / на 755 (и один раз на 777), но это не изменило вывод моего тестового кода. / tmp / уже был установлен с 777.
В app-armor я перевел mysql в режим жалобы, а также попытался внести некоторые изменения в конфигурационный файл mysql для app-armor (usr.sbin.mysqld), но оба не изменили вывод тестового кода.
Полезная документация (но, возможно, я не до конца понял):
http://dev.mysql.com/doc/refman/5.5/en/load-data-local.html
Я предпочитаю использовать LOAD DATA LOCAL, но если он работает как-то иначе, я тоже счастлив.
Пожалуйста помоги. Любые вопросы и предложения приветствуются.
Я сталкиваюсь с той же проблемой, когда я пытаюсь использовать mysql load infile
(файл данных и проект на локальном хосте и удаленной базе данных). Я использую прямой mysql
команда от php
(с помощью system
функция). Вот пример моего кода:
system('mysql --local-infile -h '.$host. ' -D '.$dbname.' -u'.$dbuser.' -p'.$password." -e \"LOAD DATA LOCAL INFILE '". $pathToFile . "' INTO TABLE table FIELDS TERMINATED BY ';' (field1, field2, field3)\"");
Я надеюсь, что это может быть полезно для вас.
Других решений пока нет …