|
日時: 2013/05/02 00:30
名前: lightbox
|
サーバーにあるデータの日々のバックアップが目的なので、
タイムスタンプが不一致のファイルのみダウンロードします
夜間バッチを想定しているので、処理結果をメールで送っています。
メール処理には、Windows の COM として有名なフリーソフトの Basp21 を使用しています
また、この手の宛先としては、同一タイトルが同日でまとめられる GMail が最適です。
除外ディレクトリは、バックアップの必要の無いソフトウェアや画像データのディレクトリに使用すると良いでしょう
php は、cgi 版では無く、cli 版を使用します。
php5 では、php-cgi.exe が cgi 版です。
UNIX OS の場合
( ※ Windows OS では、ファイル一覧取得時の文字列に違いがあります )
拡張子:
<?php
// *********************************************************
// FTP サーバからの一括ダウンロード
// *********************************************************
$obj = new COM("Basp21");
$timeout = 30;
$svname = "smtpサーバー:587";
$mailto = "宛先メールアドレス";
$mailfrom = "送り主メールアドレス\tユーザID:パスワード";
$subj = "【バックアップ処理】";
$body = "FTP サーバからの一括ダウンロード\n\n";
# ************************************************
# 接続情報
# ************************************************
$ftp_server = "ftpサーバー";
$ftp_user = "ユーザー";
$ftp_pass = "パスワード";
# ************************************************
# 位置情報
# ************************************************
# 最後に / は必要ありません
$base_dir = "/public_html";
$local_dir = "C:\\user\\land\\public_html";
# ************************************************
# 除外ディレクトリ
# ************************************************
$out = array(
"phpmyadmin"
,"dojo"
,"pfn"
,"servletapi-ja-4.0"
);
$base_dir_save = $base_dir;
# ************************************************
# 処理開始
# ************************************************
print "リモートのパス : $base_dir\n";
print "ローカルのパス : $local_dir\n";
print date("Y/m/d H:i:s") . " >>> 処理を開始しました\n";
# ************************************************
# 接続
# ************************************************
$conn = ftp_connect($ftp_server,21,$timeout);
if (!$conn) {
die('接続できません');
}
# ************************************************
# ログイン
# ************************************************
$result = @ftp_login($conn, $ftp_user, $ftp_pass);
if (!$result) {
die('ログインできません');
}
# ************************************************
# パッシブモードをオン
# ************************************************
ftp_pasv($conn, TRUE);
# ************************************************
# 一覧用配列初期化
# ************************************************
$dir = array();
$file = array();
$file_datetime = array();
# ************************************************
# ルートのディレクトリ一覧とファイル一覧の
# 配列を作成する
# ************************************************
$dir[] = $base_dir; # 開始ディレクトリのセット
$init = true;
for( $pos = 0; $pos < count($dir); $pos++ ) {
$base_dir = $dir[$pos];
$list = ftp_rawlist( $conn, $base_dir );
if ( $init ) {
$init = false;
# ********************************************
# FTP が不安定で、大量のダウンロードを回避
# したい場合の手動分割処理
# ********************************************
# $list = array_slice($list, 0, 20);
# $list = array_slice($list, 20, 20);
# $list = array_slice($list, 40, 20);
}
if ( !$list ) {
print "----EMPTY : $base_dir\n";
}
else {
print "-------OK : $base_dir\n";
}
$max = count($list);
for( $i = 0; $i < $max; $i++ ) {
# ********************************************
# ディレクトリの場合
# ********************************************
if ( substr( $list[$i], 0, 1 ) == 'd' ) {
# ********************************************
# 配列作成
# ********************************************
$data = explode( " ", $list[$i] );
# ********************************************
# 一番最後が名前
# ********************************************
$target = array_pop( $data );
# ********************************************
# 除外処理
# ********************************************
$skip = false;
for( $idx = 0; $idx < count($out); $idx++ ) {
if ( $out[$idx] == $target ) {
$skip = true;
break;
}
}
if ( $skip ) {
continue;
}
# ********************************************
# 配列にフルパスをセット
# ********************************************
if ( $target != '.' && $target != '..' ) {
$dir[] = $base_dir . '/' . $target;
}
}
# ********************************************
# ファイルの場合
# ********************************************
else {
# ********************************************
# 対象外の文字列の処理
# ********************************************
if ( substr( $list[$i], 0, 5 ) != 'total' ) {
# ********************************************
# 配列作成
# ********************************************
$data = explode( " ", $list[$i] );
# ********************************************
# 一番最後が名前
# ********************************************
$target = array_pop( $data );
# ********************************************
# 配列にフルパスをセット
# ********************************************
$file[] = $base_dir . '/' . $target;
$file_datetime[] = $list[$i];
}
}
}
}
# ************************************************
# ディレクトリ一覧からディレクトリを作成
# ************************************************
for( $pos = 0; $pos < count($dir); $pos++ ) {
$work = str_replace( $base_dir_save, $local_dir, $dir[$pos] );
$work = str_replace( "/", "\\", $work );
@mkdir( $work );
}
# ************************************************
# ダウンロード
# ************************************************
$msg = "ダウンロード対象ファイル数 : " . count($file) . "\n";
print $msg;
# 実際にダウンロードしたファイル数
$cnt = 0;
# メールログ用
$body .= $msg;
# ダウンロードループ
for( $pos = 0; $pos < count($file); $pos++ ) {
# ********************************************
# ローカルファイルのパスを作成
# ********************************************
$work = str_replace( $base_dir_save, $local_dir, $file[$pos] );
$work = str_replace( "/", "\\", $work );
# ********************************************
# リモートのタイムスタンプを作成
# ********************************************
$time_remote = ftp_mdtm($conn, $file[$pos]);
$skip = FALSE;
# ********************************************
# ローカルにファイルが存在した場合はタイムスタンプを作成
# ********************************************
if ( file_exists( $work ) ) {
# ********************************************
# ローカルのタイムスタンプを取得
# ********************************************
$time_local = fileatime($work);
if ( $time_local === FALSE ) {
$time_local = $time_remote;
}
else {
# ********************************************
# サーバが正しい事を大前提とし、
# タイムスタンプが一致したらダウンロードしない
# ********************************************
if ( $time_local == $time_remote ) {
$skip = TRUE;
}
else {
$time_local = $time_remote;
}
}
}
# ********************************************
# ローカルにファイルが存在ない場合は、
# リモートのタイムスタンプを使用
# ********************************************
else {
$time_local = $time_remote;
}
if ( !$skip ) {
# ********************************************
# ダウンロードのメッセージ作成
# ********************************************
$msg = $pos+1 . ":" . str_replace($base_dir_save . "/", "", $file[$pos]) . "\n";
print $msg;
$body .= $msg;
# ********************************************
# ダウンロード
# ********************************************
$ret = @ftp_get( $conn, $work, $file[$pos], FTP_BINARY );
if ( $ret !== FALSE ) {
$cnt++;
# ********************************************
# ダウンロードされたファイルのタイムスタンプを更新
# ********************************************
$ret = @touch( $work, $time_local );
if ( $ret === FALSE ) {
$msg = "touch エラー:$work\n";
$body .= $msg;
}
}
else {
$msg = "ftp_get エラー:$work:{$file[$pos]}\n";
$body .= $msg;
}
}
}
ftp_close($conn);
$msg = "実際のファイルダウンロード数 : $cnt";
$body .= $msg;
print "$msg\n";
print date("Y/m/d H:i:s") . " >>> 処理が終了しました\n";
$obj->SendMail($svname,$mailto,$mailfrom,$subj,$body,"");
?>
↓ftp_rawlist によるディレクトリ情報
|