Object Storage相手にrsyncでバックアップみたいなことできないかなと模索して、結構ドンピシャな動きが確認できたので、書いてみました。誰かの役に立てば。
したいこと
指定したディレクトリ内のファイルをオブジェクトストレージにバックアップがしたい!
OCI CLIのコマンドリファレンスを見るとばっちりなコマンドが見つかります。
oci os object sync
でも、やっぱ挙動は検証してみないとですよね?
まずはオプション確認
-bn, --bucket-name [text]
必須。バケット名。
--cache-control [text]
--content-disposition [text]
--content-encoding [text]
--content-language [text]
--content-type [text]
Object Storageの動作には影響しないとあるので、いったん無視。
--delete
コピー元に存在しないファイルを削除するか。
rsyncの--deleteと同じかな。検証対象。
--dest-dir [text]
オブジェクトストレージがコピー元になる場合に指定。つまり、ダウンロード。
--dry-run
実際にアクションせず、アップロード/ダウンロードおよび削除されるファイル一覧を出す。検証時には重要オプション。
--encryption-key-file [filename]
暗号化キー。無視。
--exclude [text]
コピー対象外にするものを書く。
rsyncの--excludeと同じ?検証対象。
--from-json [text]
--metadata [text]
無視。
--include [text]
コピー対象にするものを書く。
これも検証対象。
-ns, --namespace, --namespace-name [text]
名前空間。指定しなくても、oci os ns get
で取得した名前空間が利用される。
--no-follow-symlinks
シンボリックリンクを対象とするか。
オブジェクトストレージにはシンボリックリンクなんて概念はないので、、、どう動くかは検証。ま、だいたい想像は付くかな。
--no-multipart
--parallel-operations-count [integer range]
--part-size [integer range]
転送系のパラメータなので、いったん無視。
--prefix [text]
オブジェクトのプレフィックス。
アップロード時に自動的に付与されて、ダウンロード時には自動的に除外されるらしい。
何らかの理由でプレフィックス付けたい時用?検証対象。
--src-dir [text]
オブジェクトストレージがコピー先になる場合に指定。つまり、アップロード。
--storage-tier [text]
保存するストレージ層。挙動には影響ないかなあ。
確認したいオプションが大体わかったので、次に進みましょう。
それでは検証
使うのは、みんな大好きCloud Shell。
ほんとねえ、Cloud Shellでさくっと検証できるようになると、OCIめっちゃ楽ですよ。
検証1 excludeとinclude
オブジェクトストレージにはディレクトリという概念がありません。
OCIコンソールの表示上、ディレクトリ構成っぽく表示されますが、ありません。
rsync
の場合は、対象をファイル名やディレクトリ名で指定しますが、oci os object sync
の場合はどうなるか?
まずはディレクトリ構成。
$ pwd; find . | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/home/adzumi/sync
|--fuga
| |--hoge1.txt
| |--hoge2.txt
|--hoge1.txt
|--hoge2.txt
$
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --exclude hoge1.txt --dry-run
Uploading file: ./hoge2.txt
Uploading file: ./fuga/hoge1.txt
Uploading file: ./fuga/hoge2.txt
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --exclude '*hoge1.txt' --dry-run
Uploading file: ./hoge2.txt
Uploading file: ./fuga/hoge2.txt
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --exclude '*/hoge1.txt' --dry-run
Uploading file: ./hoge1.txt
Uploading file: ./hoge2.txt
Uploading file: ./fuga/hoge2.txt
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --exclude hoge1.txt --exclude '*/hoge1.txt' --dry-run
Uploading file: ./hoge2.txt
Uploading file: ./fuga/hoge2.txt
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --include 'fuga*' --exclude '*hoge1.txt' --dry-run
UsageError: The --include and --exclude parameters cannot both be provided.
$
なるほど。
「指定するのはオブジェクトストレージ上のオブジェクト名」ということですね。
--exclude
--include
は同一であれば複数指定はできるけど、両方指定するのはできないのはちょっと驚き。
検証2 no-follow-symlinks(とdelete)
まあ、これはだいたい想像が付きますが、念のため。
$ ls -l fuga
total 0
-rw-r--r--. 1 adzumi oci 0 Aug 7 19:35 hoge1.txt
lrwxrwxrwx. 1 adzumi oci 12 Aug 7 19:48 hoge2.txt -> ../hoge2.txt
$
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --dry-run
Uploading file: ./hoge1.txt
Uploading file: ./hoge2.txt
Uploading file: ./fuga/hoge1.txt
Uploading file: ./fuga/hoge2.txt
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --no-follow-symlinks --dry-run
Uploading file: ./hoge1.txt
Uploading file: ./hoge2.txt
Uploading file: ./fuga/hoge1.txt
$
想像通り、--no-follow-symlinks
付けるとコピーそのものがされません。
そもそも、所有者情報とかパーミッションとかはコピーできないので、OS領域をそのまんまバックアップとかは無理ですよね。いっぱい写真が入ってるフォルダとかのバックアップとかなら良さそうです。
おまけ。
$ oci os object sync -bn bucket-20250807-1930 --src-dir .
Uploaded hoge1.txt [####################################] 100%
(中略)
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --no-follow-symlinks --delete --dry-run
Skipping file: ./hoge2.txt
Skipping file: ./fuga/hoge1.txt
Skipping file: ./hoge1.txt
Deleting object: fuga/hoge2.txt
$
--no-follow-symlinks
と--delete
付けると、シンボリックリンクのものは削除対象になりますね。
検証3 delete
ローカルのhoge1.txt
とオブジェクトストレージ上のfuga/hoge2.txt
を削除した状態で、アップロードとダウンロードを試してみました。
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --delete --dry-run
Uploading file: ./fuga/hoge2.txt
Skipping file: ./hoge2.txt
Skipping file: ./fuga/hoge1.txt
Deleting object: hoge1.txt
$ oci os object sync -bn bucket-20250807-1930 --dest-dir . --delete --dry-run
Downloading object: fuga/hoge1.txt
Downloading object: hoge1.txt
Downloading object: hoge2.txt
Deleting : ./fuga/hoge2.txt
$
--delete
の動きは想定通りなんですけど、全部ダウンロード対象になったのば驚き。
オブジェクトストレージ上のオブジェクトのタイムスタンプは、アップロードした時間になるので、ダウンロード時は常に「オブジェクトストレージ側が新しい」ということですかね。
ダウンロード時は要注意だなあ。
検証4 ダウンロード(--dest-dir指定)時の挙動
ダウンロード時が要注意と分かったので、ローカルが新しくなるようにtouchしてみました。
$ touch hoge2.txt
$ oci os object sync -bn bucket-20250807-1930 --dest-dir . --delete --dry-run
Downloading object: fuga/hoge1.txt
Downloading object: hoge1.txt
Skipping object: hoge2.txt
Deleting : ./fuga/hoge2.txt
$
ですよねえ。
検証5 prefix指定
アップロードしてみます。
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --prefix piyo/
Uploaded piyo/hoge2.txt [####################################] 100%
(中略)
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --prefix piyo/ --dry-run
Skipping file: ./fuga/hoge2.txt
Skipping file: ./hoge2.txt
Skipping file: ./hoge1.txt
Skipping file: ./fuga/hoge1.txt
$ oci os object list -bn bucket-20250807-1930 | jq '.data[].name'
"piyo/fuga/hoge1.txt"
"piyo/fuga/hoge2.txt"
"piyo/hoge1.txt"
"piyo/hoge2.txt"
$
prefixが付いた状態で格納されますね。
では、ダウンロードもしてみましょう。
$ cd ../sync2
$ ls
$ oci os object sync -bn bucket-20250807-1930 --dest-dir . --prefix piyo/
Downloaded piyo/fuga/hoge1.txt [####################################] 100%
(中略)
$ pwd; find . | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/home/adzumi/sync2
|--fuga
| |--hoge1.txt
| |--hoge2.txt
|--hoge1.txt
|--hoge2.txt
$
prefixが消えてダウンロードされてますね。
…ここで、ちょっと実験。
$ rm -fr *
$ ls
$ oci os object sync -bn bucket-20250807-1930 --dest-dir . --prefix piyo
Downloaded piyo/fuga/hoge2.txt [####################################] 100%
(中略)
$ pwd; find . | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/home/adzumi/sync2
|--fuga
| |--hoge1.txt
| |--hoge2.txt
|--hoge1.txt
|--hoge2.txt
$
piyo/
をpiyo
にしてみました。
/
にファイルを書き込みに行ってエラーになるかなと思いましたが、そうはならないみたいですね。
では、piy
にしたらどうなるか。
$ rm -fr *
$ ls
$ oci os object sync -bn bucket-20250807-1930 --dest-dir . --prefix piy
Downloaded piyo/fuga/hoge2.txt [####################################] 100%
(中略)
$ pwd; find . | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/home/adzumi/sync2
|--o
| |--fuga
| | |--hoge1.txt
| | |--hoge2.txt
| |--hoge1.txt
| |--hoge2.txt
$
これは想像通り。
検証6 src-dirとprefix
まずは事前準備。
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --dry-run
Skipping file: ./hoge1.txt
Skipping file: ./fuga/hoge4.txt
Skipping file: ./hoge2.txt
Skipping file: ./fuga/hoge3.txt
$ pwd; find . | sort | sed '1d;s/^\.//;s/\/\([^/]*\)$/|--\1/;s/\/[^/|]*/| /g'
/home/adzumi/sync
|--fuga
| |--hoge3.txt
| |--hoge4.txt
|--hoge1.txt
|--hoge2.txt
$ oci os object list -bn bucket-20250807-1930 | jq '.data[].name'
"fuga/hoge3.txt"
"fuga/hoge4.txt"
"hoge1.txt"
"hoge2.txt"
$
この状態で、fugaの下だけアップロードします。
$ oci os object sync -bn bucket-20250807-1930 --src-dir fuga --prefix fuga/ --dry-run
Skipping file: fuga/hoge3.txt
Skipping file: fuga/hoge4.txt
$
このように、--src-dir
を指定すれば、特定のディレクトリ以下のみを対象にできますが、アップロード時のオブジェクト名にディレクトリ名が入らなくなるので、--prefix
で補完できます。
ただ、この方法だとディレクトリが一つしか指定できなくてやや不便。なので、--include
を使う方法もあります。--include
は複数指定できることを有効利用。
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --include 'fuga/*' --dry-run
Skipping file: ./fuga/hoge4.txt
Skipping file: ./fuga/hoge3.txt
$ oci os object sync -bn bucket-20250807-1930 --src-dir . --include 'fuga/*' --include 'hoge1.txt' --dry-run
Skipping file: ./fuga/hoge3.txt
Skipping file: ./fuga/hoge4.txt
Skipping file: ./hoge1.txt
$
たぶん、この辺を利用すれば、簡単に必要なファイルのみのアップロードが実現できると思います。
結論
oci os object sync は大きな驚きなく使えそう!