#要件
zfs send | recvで差分転送をするには、下記のような手順を踏む必要があります。
- 初回
- 送信側でtempスナップショットを作成
- tempスナップショットを送信
- 送信側および受信側でtempスナップショットをリネーム
- 2回目以降
- 送信側でtempスナップショットを作成
- tempスナップショットと前回のスナップショットの差分を送信
- 前回のスナップショットを削除
- 送信側および受信側でtempスナップショットをリネーム
#関数仕様
取り違えやすいため関数を作成しました。
send_recv_new <from_fsname> <from_ssh_host> <from_ssh_cipher_spec> <to_fsname> <to_ssh_host> <to_ssh_cipher_spec> <snapshot_name> <temp_snapshot_name>
send_recv <from_fsname> <from_ssh_host> <from_ssh_cipher_spec> <to_fsname> <to_ssh_host> <to_ssh_cipher_spec> <snapshot_name> <temp_snapshot_name>
SSHのホストに空文字列を渡せば、SSH接続せずローカルで処理します。また暗号化アルゴリズムに空文字列を渡せば、デフォルトの暗号化アルゴリズムを使います。具体的には次のように使ってください。
send_recv_new 'tank1/test' '' '' 'tank2/test' 'user@192.168.1.2' 'chacha20-poly1305@openssh.com' 'tank1_to_tank2' 'temp'
send_recv 'tank1/test' '' '' 'tank2/test' 'user@192.168.1.2' 'chacha20-poly1305@openssh.com' 'tank1_to_tank2' 'temp'
#コード
#!/bin/bash
ssh_wrapper () {
local host=$1
local cipher_spec=$2
local command=$3
if [ -n "$host" -a "''" != "$host" ]; then
local command2='ssh'
if [ -n "$cipher_spec" -a "''" != "$cipher_spec" ]; then
command2=${command2}' -c '${cipher_spec}
fi
command2=${command2}' '${host}' '$(printf %q "$command")
echo "$command2"
else
echo "$command"
fi
}
send_recv_new () { #初回
local from=$(printf %q "$1")
local from_host=$(printf %q "$2")
local from_cipher_spec=$(printf %q "$3")
local to=$(printf %q "$4")
local to_host=$(printf %q "$5")
local to_cipher_spec=$(printf %q "$6")
local snapshot=$(printf %q "$7")
local temp=$(printf %q "$8")
local c
c=$(ssh_wrapper $from_host $from_cipher_spec "zfs snapshot ${from}@${temp}") && eval $c &&
c=$( ssh_wrapper $from_host $from_cipher_spec "zfs send ${from}@${temp}") &&
c=$c' | '$(ssh_wrapper $to_host $to_cipher_spec "zfs recv ${to}") && eval $c &&
c=$(ssh_wrapper $from_host $from_cipher_spec "zfs rename ${from}@${temp} @${snapshot}") && eval $c &&
c=$(ssh_wrapper $to_host $to_cipher_spec "zfs rename ${to}@${temp} @${snapshot}") && eval $c
}
inner_send_recv () { #内部処理
local from=$1
local from_host=$2
local from_cipher_spec=$3
local to=$4
local to_host=$5
local to_cipher_spec=$6
local snapshot=$7
local temp=$8
local c
c=$( ssh_wrapper $from_host $from_cipher_spec "zfs send -i @${snapshot} ${from}@${temp}") &&
c=$c' | '$(ssh_wrapper $to_host $to_cipher_spec "zfs recv -F ${to}") && eval $c &&
c=$(ssh_wrapper $from_host $from_cipher_spec "zfs destroy ${from}@${snapshot}") && eval $c &&
c=$(ssh_wrapper $from_host $from_cipher_spec "zfs rename ${from}@${temp} @${snapshot}") && eval $c &&
c=$(ssh_wrapper $to_host $to_cipher_spec "zfs destroy ${to}@${snapshot}") && eval $c &&
c=$(ssh_wrapper $to_host $to_cipher_spec "zfs rename ${to}@${temp} @${snapshot}") && eval $c
}
send_recv () { #2回目以降
local from=$(printf %q "$1")
local from_host=$(printf %q "$2")
local from_cipher_spec=$(printf %q "$3")
local to=$(printf %q "$4")
local to_host=$(printf %q "$5")
local to_cipher_spec=$(printf %q "$6")
local snapshot=$(printf %q "$7")
local temp=$(printf %q "$8")
local c
c=$(ssh_wrapper $from_host $from_cipher_spec "zfs snapshot ${from}@${temp}") && eval $c &&
inner_send_recv $from $from_host $from_cipher_spec $to $to_host $to_cipher_spec $snapshot $temp
}