LoginSignup
1
1

More than 5 years have passed since last update.

zfs send | recvの差分転送を楽にする(SSH対応版)

Last updated at Posted at 2016-05-09

要件

zfs send | recvで差分転送をするには、下記のような手順を踏む必要があります。

  • 初回
    1. 送信側でtempスナップショットを作成
    2. tempスナップショットを送信
    3. 送信側および受信側でtempスナップショットをリネーム
  • 2回目以降
    1. 送信側でtempスナップショットを作成
    2. tempスナップショットと前回のスナップショットの差分を送信
    3. 前回のスナップショットを削除
    4. 送信側および受信側で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
}
1
1
0

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
1
1