Таак, написал automatic remote backup tool, PHP скрипт дампит MySQL базы, записывает их локально и закачивает на удаленный FTP... Только вот проблем... Хост ругается: ftp_put() [function.ftp-put]: php_connect_nonb() failed: Operation now in progress (115) (2) Саппорт отвечает: We do not allow the FTP functions to be used against remote FTP servers. Так вот ищу простую альтернативу ftp_*, есть идея передавать имя файла (которое генерируется разное!) GET запросом удаленному скрипту, а тот скачает и запишет файл. Но как реализовать, вообще не думается Буду благодарен за куски кода, примеры, обяснения... Спасибо что дочитали
Ну например так: 1 хост, который делает дамп: PHP: <?php /* { Тут делаешь дамп и сораняешь файл локально } */ $damp_file = "db.sql"; //Тут имя файл который сдампился echo file_get_contents("http://my_server_2/saver.php?file=".$damp_file); //Тут ты передаешь хосту №2 какой файл ему скачивать ?> Хост №2 который скачивает PHP: <?php $server_1 = "http://server_nomer_1/"; //Тут адрес сервера откуда скачивать $dump_file = $_GET['file']; $file_prefix = "saved_"; if(file_put_contents($file_prefix.$dump_file,file_get_contents($server_1.$dump_file))) { echo "File_saved!"; }else echo "File dont saved"; ?> Ну впринципе и все. 1 скрипт напишет File_saved! если файл успешно скачен вторым сервером. На втором сервере появится файл saved_db.sql Ну думаю схема понятна. ))) Если файл большой, то во втором скрипте скачивай "побайтово". функция fread() //практикуем убийство серверов?)))
Ожидается что будет большой, и еще 50 штук таких... Базы phpBB3 =) Иначе все понятно, спасибо огромное, щас в репу стукну Няя, я не убиец =) Я наемный убиец =) ...а так, сайто строитель...
скрипт, который дампит (в переменной $server указать путь до скрипта, который скачивает): Code: <?php /*тут дамп в переменную $dump*/ $server = 'http://fsdfdsf.ru/example.php'; //путь до второго файла @ini_set('max_execution_time', 0); $name = "dump".date("YmdHis").".sql"; if( @file_put_contents( $name, $dump ) ) { echo 'Сохранили дамп...'.PHP_EOL; $path = $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"].$name; $content = file_get_contents( $server.'?put='.urlencode($path) ); if( $content == 'success' ) echo 'Сервер успешно сохранил наш дамп.'.PHP_EOL; else echo 'Серверу не удалось сохранить наш дамп.'.PHP_EOL; } else echo 'Дамп сохранить не удалось. Проверь chmod.'; ?> скрипт для сохранения дампа: Code: <?php $dir = '/dumps/'; //папка с дампами $file = "http://".stripslashes(urldecode(trim($_GET['put']))); if( file_put_contents( $dir."dump".date("Y-m-d+H-i-s"), file_get_contents($file) ) ) { die('success'); } else die('false'); ?> /*писалось на скорую руку, подправьте если что не так*/
^_WhitE_DeMoN_^ если блокируются только функции ftp_*, напишите свой класс на сокетах, благо FTP - простейший протокол Или еще проще: PHP: file_put_contents("ftp://user:[email protected]/file.txt", file_get_contents('имя_локального_файла'));
FTP - не обязательно. Нужно только реализовать закачку файла с одного сервера на другой, а как ето уже проблем... Со сокетами не знаком, но придется доки курить... ini_set('allow_url_fopen', 'On'); не помогло...
слать через POST, если файлы большие (или ограничение на POST), то кусками с указанием сегментов вначале сделать запрос на передачу файла, в POST параметрах указать имя файла, логин/пароль, хэш всего файла, его размер. Далее, получив согласие получателя и код сессии начинаем передавать сегменты файла: указать только начало, конец, контрольную сумму (на всякий) обрывка; сессию на файл Принимающий собирает по кускам, проверяет получившуюся контрольную сумму и всё. Ну и написать проверку, что если были ранее начаты сессии с незаконченными передачами, которые не обновлялись более часа, то их стоит удалить. куски файла можно зипировать.. а если и в base64 закодировать, то можно и GET-ом передать xD правда там на заголовки больше уйдёт трафика, но система будет работать
При base64 строка увеличиться в несколько раз, а метод GET при отправки большого количества данных какбе не лучший вариант. ^_WhitE_DeMoN_^, Ты сокетами, надеюсь, отправлял заголовки?
я об этом и говорю, что заголовки ппц будут ^_WhitE_DeMoN_^, написл для тебя функцию с коментами. Если не новиш в php, то дальше сам разрулишь (функцию можешь не изучать, просто используй как надо, хотя в ней многое не учтено, но для простых запросов хватит) PHP: function HTTP_request($serv='127.0.0.1', $port=80, $timeout=30, $host='localhost', $addr='/index.php', $post=null, $cookies=null){ $str='';$heads=''; if(is_array($post))if(count($post)>0){ $method='POST'; $str.="\r\n\r"; foreach($post as $k=>$v){ $str.='&'.$k.'='.urlencode($v); } $str{4}="\n"; $heads.="\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: ".(strlen($str)-4); } if(!isset($method)){ $method='GET'; //$heads.="\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; $str="\r\n\r\n"; } if(is_array($cookies))if(count($cookies)>0){ $cook="\r\nCookie: "; foreach($cookies as $k=>$v){$cook.=$k.'='.urlencode($v).'; ';} $heads.=substr($cook,0,-2); } if(false!=($f=@fsockopen($serv, $port, $errno, $errstr, $timeout))){ $ss=''; fputs ($f, "$method $addr HTTP/1.1".$heads."\r\nHost: $host\r\nConnection: close".$str); while (!feof($f)) { $ss.=fgets($f, 512); } fclose($f); }else return array(false, $errstr); return array(true, $ss); } // вернёт массив 0=>сокет сконнектил 1=> если не сконнектил, то текст ошибки, иначе овтет сервера ////////////////////////// ////// $serv='127.0.0.1'; // IP или домен сервера $port=80; // порт $host='localhost'; // Что передавать в заголовке HOST $addr='/index.php';// Адрес до страницы на сайте $timeout=30; // таймаут соединения $post=array(); // массив с переменными в формате ($var1 => $value1, $var2 => $value2...) {в $var# желательно использовать только латину} $cookie=array();// cookies заполняется аналогично $post print_r(HTTP_request($serv, $port, $timeout, $host, $addr, $post, $cookie));
^_WhitE_DeMoN_^, ошибка есть, тут: $str{4}="\n"; надо $str{3}="\n"; А где возвращает 1? я тут RFC протокола перечитал, увидел следующее на счёт Content-Length: Длина тела объекта (entity-body) - это длина тела сообщения (message-body), полученного после декодирования всех кодирований передачи. Т.е., как я понял, сюда надо вписывать не длину закодированного контента, а длину контента до кодирования. В нэте в примерах показывают обратное, т.е. указывают длину закодированного контента. Вобщем немного переделал функцию (тут длина до кодирования): PHP: function HTTP_request($serv='127.0.0.1', $port=80, $timeout=30, $host='localhost', $addr='/', $post=null, $cookies=null){ $str='';$heads=''; if(is_array($post))if(count($post)>0){ $method='POST'; $str.="\r\n\r"; $Len=0; foreach($post as $k=>$v){ $str.='&'.$k.'='.urlencode($v); $Len+=2+strlen($k)+strlen($v); } $Len-=1; $str{3}="\n"; $heads.="\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: ".$Len; } if(!isset($method)){ $method='GET'; //$heads.="\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; $str="\r\n\r\n"; } if(is_array($cookies))if(count($cookies)>0){ $cook="\r\nCookie: "; foreach($cookies as $k=>$v){$cook.=$k.'='.urlencode($v).'; ';} $heads.=substr($cook,0,-2);unset($cook); } if(false!=($f=@fsockopen($serv, $port, $errno, $errstr, $timeout))){ $ss=''; fputs ($f, "$method $addr HTTP/1.1".$heads."\r\nHost: $host\r\nConnection: close".$str); while(!feof($f)){$ss.=fread($f, 512);} fclose($f); }else return array(false, $errstr); return array(true, $ss); } надеюсь в Content-Length учитываются разделители и названия переменных Кстати, чтобы передавать бинарные данные, лучше использовать MIME без всякого кодирования. Этим же способом передают фотки с текстом за 1 раз. С момента прошлого поста я успел написать функцию, реализующую MIME в POST, только не закончил. В функции нет возможности аутентификации (Digest Authentication), но эти заголовки несложно дописать вручную. Если надо, могу поделиться.