From: emo@... Date: 2020-05-31T20:22:05+09:00 Subject: [ruby-list:50887] Net::SSH を使ったパイプ処理 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
' > 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
' > from /usr/share/gems/gems/net-ssh-2.9.1/lib/net/ssh.rb:210:in `start' > from ./test_backup.rb:15:in `
' 差分の情報が極小さい場合は、正常に実行できているようなのですが、 差分データが大きい場合は、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 江本