LoginSignup
2
2

More than 5 years have passed since last update.

perl の Net::SFTP::Foreign でファイルを同期する

Last updated at Posted at 2014-04-15

サーバー間でファイルを双方向に同期する必要が生じたので、perl でスクリプトを書いてみました。

SFTP とは

セキュアなファイル転送プロトコルとしては SFTP と FTPS があって紛らわしいのですが、FTP を SSL/TLS を通して安全に使えるようにしたものが FTPS で、SFTP は FTP とは無関係に、SSH プロトコルの一部(?)としてファイル転送を行えるようにしたもののようです。

また、SFTP はスクリプト言語から制御できるので、単純なコピーではなく、双方向の同期にはぴったりだと思われます。

Net::SFTP::Foreign

perl から SFTP を使うには Net::SFTP::Foreign というモジュールを使えばいいようです。Debian には libnet-sftp-foreign-perl というパッケージがありました。

$ sudo apt-get install libnet-sftp-foreign-perl

接続

とりあえずこんな感じで接続します。かんたん。

use Net::SFTP::Foreign;

my $HOST = 'user@example.com';
my $PASS = '********';
my $MORE = [ -o => 'StrictHostKeyChecking no' ];

my $sftp = Net::SFTP::Foreign->new($HOST, password => $PASS, more => $MORE);

more にいろいろオプションを指定できるようなので、未知の鍵に関していちいち確認されないように StrictHostKeyChecking no を指定してみました。

ファイル一覧

接続先のファイル一覧は $sftp->ls($dir, ...) で取得できます。ファイル名が . で始まらない通常ファイルのみをソートして取得してみます。

my $files = $sftp->ls($dir, ordered => 1, no_wanted => qr/^\./,
                            wanted => sub { S_ISREG($_[1]->{a}->perm) });

結果は配列のリファレンスで、その中身は

foreach my $file (@$files) {
    my $filename = $file->{filename};
    my $mtime = $file->{a}->mtime;
}

のようにアクセスできます。$file->{a} は stat の結果と似ています。

ファイルの送受信

ファイルの送信は以下のようにします。

$sftp->put("$local_dir/$filename", "$remote_dir/$filename");

また、ファイルの受信は以下のようにします。

$sftp->get("$remote_dir/$filename", "$local_dir/$filename");

それから、接続先のファイルの削除は以下のようにします。

$sftp->remove("$remote_dir/$filename");

あとは、接続先とローカルのファイルの一覧を比較して、新しい方を送受信すればいいだけですね。削除に関しては、新しい方のファイルサイズが 0 なら削除ということにしてみました。

できあがり

ってなわけで、できあがり。コードは gist にあります。
https://gist.github.com/hoshi-takanori/9948910

2
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2