rsync3で高速差分フルバックアップ

rsync --link-dest --rsync-path など


結局こうなった(現段階でのメモ)

CMD=/usr/local/bin/rsync
STRAGE=/var/backup
OLDEST=`date --date '7 days ago' +%Y%m%d`
LATEST=`date --date '1 days ago' +%Y%m%d`

for HOST in `ls $STRAGE`;
do
  if [ -f $STRAGE/$HOST ] ; then
    continue
  fi

  HOSTNAME=`cat $STRAGE/$HOST/hostname.txt`
  echo "backup start : $HOSTNAME"

  if [ -d $STRAGE/$HOST/$OLDEST ] ; then
    rm -fr $STRAGE/$HOST/$OLDEST
  fi

  if [ -d $STRAGE/$HOST/current ] ; then
    mv $STRAGE/$HOST/current $STRAGE/$HOST/$LATEST
  fi

  $CMD -az --delete \
  --link-dest="../$LATEST/" \
  --rsync-path="sudo $CMD" \
  --exclude-from=$STRAGE/$HOST/excludes.txt \
  backup@$HOST:/ $STRAGE/$HOST/current/

done;

ローカルIPと同じ名称でディレクトリを作成すれば、バックアップ対象としてエントリされる仕組み。

以降は初期設定と、ターゲット毎の設定。

#-------------------------
# 初期設定
#-------------------------
scp backup.sh root@192.168.1.177:
ssh root@192.168.1.177
ssh-keygen -t rsa
useradd -G wheel backup
passwd backup

# rsync3 のインストール
cd /usr/local/src/
wget http://rsync.samba.org/ftp/rsync/rsync-3.0.7.tar.gz
tar xzfv rsync-3.0.7.tar.gz 
cd rsync-3.0.7
./configure
make
make install

#-------------------------
# ターゲット毎の設定
#-------------------------
ssh work@192.168.1.172
su -

# rsync3 のインストール
cd /usr/local/src/
wget http://rsync.samba.org/ftp/rsync/rsync-3.0.7.tar.gz
tar xzfv rsync-3.0.7.tar.gz 
cd rsync-3.0.7
./configure
make
make install

# バックアップユーザの追加と sudo の設定
useradd backup
visudo
backup ALL= NOPASSWD:/usr/local/bin/rsync

# 必要に応じて公開鍵認証を有効化する
vi /etc/ssh/sshd_config
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

# バックアップサーバから公開鍵認証でログインできるようにする。
su - backup
vi ~backup/.ssh/authorized_keys

rsync --link-dest --rsync-path など

覚書

HOST=192.168.1.172
CMD=/usr/local/bin/rsync
OLDEST=`date --date '7 days ago' +%Y%m%d`
LATEST=`date --date '1 days ago' +%Y%m%d`

rm -fr $HOST/$OLDEST
mv $HOST/current $HOST/$LATEST

$CMD -narzv --delete \
--link-dest="../$LATEST/" \
--rsync-path="sudo $CMD" \
--exclude-from=excludes.txt \
/ backup@$HOST:$HOST/current/

Twitter Search API の利用回数制限は秘密らしい

他のAPIの1時間に利用できる回数の制限は150回らしいのですが、検索に関しては非公開となっているようです。
ドキュメントの上のほうしか見てなくて、150回しか使えないと思ってたからなんか得した感じ。

Search API Rate Limiting

The Search API is rate limited by IP address. The number of search requests that originate from a given IP address are counted against the search rate limiter. The specific number of requests a client is able to make to the Search API for a given hour is not released. Note that the Search API is not limited by the same 150 requests per hour limit as the REST API. The number is quite a bit higher and we feel it is both liberal and sufficient for most applications. We do not give the exact number because we want to discourage unnecessary search usage.


150回以上使えるか確認用に作ったスクリプトはこれ

#!/usr/bin/perl

use strict;
use warnings;

use LWP::UserAgent;
use JSON;

$!=1;
for my $number (1..200) {
  my $query = "java";
  my $ua = LWP::UserAgent->new;
  my $res = $ua->get("http://search.twitter.com/search.json?q=$query");

  if($res->is_success){
    my $json = from_json($res->content, {utf8 => 1});
    if($json->{error}){
      printf "%4d NG: %s\n", $number, $json->{error};
    }else{
      printf "%4d OK: %s results\n", $number, scalar(@{$json->{results}});
    }
  }else {
    die $res->status_line;
  }
}

HTML中のイメージのwidthを調整するフィルタの作りかけ

widthが無い場合やスタイルで指定されている場合、外部cssの場合など
対応できないので今は使わないことにした。

なんかもっといい方法ないかなぁ

#!/usr/bin/perl

use strict;
use warnings;

use IO::File;
use HTML::Parser;
use Data::Dumper;

my $file = 'test.html';


my $fh = new IO::File;
$fh->open("< $file") or die "$!: $file";
my $str = join '', <$fh>;
$fh->close;

my $ret = img_resize($str);
print "$ret\n";

sub _img_resize {
    my ($self, $tag, $attr, $attrseq, $text) = @_;
    return unless $tag eq 'img' && $attr->{'width'};
    #print Dumper(\@_);
    $attr->{'width'} = int($attr->{'width'} * $self->{'ratio'});
    my $attr_text = join ' ', map { sprintf '%s="%s"', $_, $attr->{$_} } grep !/height/, @$attrseq;
    $self->{'ret'} .= "<$tag $attr_text>\n";
};
sub img_resize {
    my $str = shift;
    my $p = HTML::Parser->new;
    $p->{'ratio'} = shift || '0.5';
    $p->handler( start => \&_img_resize );
    $p->handler( declaration  => sub { return; $_[0]->{'ret'} .= "<!$_[1]>"     } );
    $p->handler( process      => sub { return; $_[0]->{'ret'} .= $_[2]          } );
    $p->handler( comment      => sub { return; $_[0]->{'ret'} .= "<!--$_[1]-->" } );
    $p->handler( end          => sub { return; $_[0]->{'ret'} .= $_[2]          } );
    $p->handler( text         => sub { return; $_[0]->{'ret'} .= $_[1]          } );
    $p->parse($str);
    return $p->{'ret'};
};

Twitter Widget advanced search 対応版 なんてのないかなぁ

途中まで作っちゃったけど、探してみてないことに気づいた。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>sample1</title>
<script type="text/javascript" src="jquery-1.4.2.js"></script>
<script type="text/javascript" src="jquery.timer.js"></script>
<script type="text/javascript">
kwd1 = encodeURI('ダウンタウン');
kwd2 = encodeURI('さんま');
$.getJSON('http://search.twitter.com/search.json?q=' + kwd1 + '+OR+' + kwd2 + '&rpp=100&callback=?', function(data) {
  $.each(data.results.reverse(), function(i, tweet){
    $.timer(5000 * (i + 1), function(timer){
      img = '<img src="' + tweet.profile_image_url + '" alt="' + tweet.from_user + '">';
      $('div').prepend('<p>'+ '[' + ']' + img + decodeURI(tweet.text) + '</p>');
      height = $('p:first').css('height');
      $('p:first').css('margin-top', '-' + height).animate({marginTop : 0}, 'slow', 'linear');
      timer.stop();
    });
  });  
});
</script>
<style type="text/css">
div {
  width: 500px;
  height: 400px;
  overflow: hidden;
}
</style>
  </head>
  <body>
    <div></div>
  </body>
</html>