[ruby-list:50887] Net::SSH を使ったパイプ処理
From:
emo@...
Date:
2020-05-31 11:22:05 UTC
List:
ruby-list #50887
BASH のスクリプトで書いているディスクの
バックアップの処理を Ruby に書き換えようとして苦戦しています。
BASH で以下の様な処理をしている箇所があります。
> btrfs send -p $PREVIOUS $CURRENT | ssh $REMOTEHOST "btrfs receive
$TARGETDIR"
このコマンドを説明すると、二つのディレクトリ(Btrfs のスナップショット)
$PREVIOUS と $CURRENT の差分を標準出力を
ssh で $REMOTEHOST に送ります。
リモートホスト側では、差分情報を標準入力から読み込み、
これをディレクトリ $TARGETDIR に反映します。
この時の差分情報のデータは ~数十 GB 程度です。
これを Ruby で Net::SSH を使って以下のように書き換えました。
(ホスト名等は *** に替えています)
> #!/usr/bin/ruby
> # -*- coding: utf-8 -*-
>
> require 'open3'
> require 'net/ssh'
> BUF_SIZE=100*1024
>
> CURRENT="*****"
> PREVIOUS="******"
> REMOTE_HOST='******'
> TARGET_DIR='*****'
>
> sender_in, sender_out, sender_thread = Open3.popen2("btrfs send -p
#{PREVIOUS} #{CURRENT}")
>
> Net::SSH.start(REMOTE_HOST, 'root', :keys => '/root/.ssh/id_rsa' )
do |ssh|
> cmd="btrfs receive #{TARGET_DIR}"
> ssh.open_channel do |channel|
> channel.exec(cmd) do |ch, success|
> raise 'file to execute remote command' unless success
> channel.on_data do |ch, data|
> puts data
> end
>
> while (data=sender_out.read(BUF_SIZE)) do
> channel.send_data(data)
> channel.process()
> end
> end
> end
> ssh.loop
> end
これを実行すると以下の例外で失敗してしまします。
> /usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/buffer.rb:143:in
`append': failed to allocate memory (NoMemoryError)
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/channel.rb:251:in
`send_data'
> from ./test_backup.rb:25:in `block (3 levels) in <main>'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/channel.rb:608:in
`call'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/channel.rb:608:in
`do_success'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/session.rb:591:in
`channel_success'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/session.rb:465:in
`dispatch_incoming_packets'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/session.rb:221:in
`preprocess'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/session.rb:205:in
`process'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/session.rb:169:in
`block in loop'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/session.rb:169:in
`loop'
> from
/usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh/connection/session.rb:169:in
`loop'
> from ./test_backup.rb:30:in `block in <main>'
> from /usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh.rb:210:in
`start'
> from ./test_backup.rb:15:in `<main>'
差分の情報が極小さい場合は、正常に実行できているようなのですが、
差分データが大きい場合は、send_data ではデータが実際には送られず、
バッファーに溜まって行き、本体のメモリが足らなくなって
失敗しているようです。
どのようにプログラムを書き換えれば良いでしょうか?
実行環境:
OS : CentOS Linux release 7.7.1908 (Core)
Ruby : 2.0.0p648 (2015-12-16) [x86_64-linux]
Net::SSH 2.8.1
江本