rsyncを高速化するために、分散して実行することにした。
全部を1つのスクリプトとしてもいいのだが、デバグがしやすいように分割して作業を行えるようにしている。
また、下記の記述はLinuxの/usrをコピーすることを想定している。環境に応じて書き換えること。
まず、/usr/xxx以下にあるファイルまでをコピーするために以下を実行する。
# rsync --archive -v --exclude="*/*/" /usr/ /mnt/vol/voltest
このexcludeオプションをつけている場合、「/usr/xxx/yyy」のファイルとシンボリックリンクはコピーされる。しかし「/usr/xxx/zzz/」のディレクトリはコピーされない。
次に、「/usr/xxx/zzz/」のディレクトリ一覧を取得する。
# find /usr -mindepth 2 -maxdepth 2 -type d -print
このディレクトリ一覧を下記のperlスクリプトに食わせる。(下記スクリプトは” find /usr -mindepth 2 -maxdepth 2 -type d -print > list.txt”で取得したlist.txtを使う想定)
#!/usr/bin/perl use threads; use Thread::Queue; my $LOGDIR="/root/test"; my $MAXSESSION=5; my $sourcepathbase="/usr"; my $destpathbase="/mnt/vol/voltest"; my $stream = Thread::Queue->new; open(FILE,"list.txt"); while(my $tmp=<FILE>){ $stream->enqueue("$tmp"); } close(FILE); sub SyncExecute{ while(my $str = $stream->dequeue){ # 改行削除 $str =~ s/\n//ig; $str =~ s/\r//ig; # ログ出力用ファイル名 my $filename=$str; $filename =~ s/\//-/ig; $filename =~ s/\.//ig; $filename =~ s/-$//ig; $filename =~ s/#//ig; $filename =~ s/^-//ig; $filename =~ s/ //ig; my $logfile="$LOGDIR/test-$filename.log"; # rsync元と先の処理 my $tmp,$st,$ed; my $sourcepath,$destpath; $tmp=substr($str,0,1); if($tmp eq "/"){ $sourcepath=$sourcepathbase.$str."/"; $destpath=$destpathbase.$str; }else{ $sourcepath=$sourcepathbase."/".$str."/"; $destpath=$destpathbase."/".$str; } `date >> $logfile`; print "rsync -v --archive $sourcepath $destpath >> $logfile 2>&1 \n"; `rsync -v --archive $sourcepath $destpath >> $logfile 2>&1 `; `date >> $logfile`; #`sleep 5`; } } my @kids; foreach(1..$MAXSESSION){ my $kid = threads->new(\&SyncExecute,$stream); push(@kids,$kid); $stream->enqueue(undef); } print "wait\n"; foreach(@kids){ my ($return) =$_ -> join; }
このスクリプトは、rsyncの同時実行数5で、並列にrsyncを実行していくものになっている。
実行したサーバの負荷状況に応じて「my $MAXSESSION=5;」で設定している 同時実行数 を調整する。あまり大きくしすぎるとサーバからの応答が遅くなりすぎるのでほどほどに・・・