背景
Bashでリリースツールを実装した際に少し詰まった部分について記述する。
とくにrsync
は単純なようで動かしてみると全然思った挙動をしてくれなかった。
単体テストは念入りに行うこと。
rsync
移送対象をファイルから読み込む際はexclude-from
オプションを使用する。include-from
やfiles-from
を利用するより直感的に操作できる。
ファイルの書式は次の通り。
+ */
+ path/to/file1.extension
+ path/to/file2.extension
+ path/to/file3.extension
- *
+
は移送対象、-
は除外対象になる。+
で指定するパスはrsync
コマンドを実行するディレクトリからの相対パスになるので注意する。+ */
がないとコマンド実行ディレクトリからサブディレクトリ以下に配置されたファイルが認識されない。
これは本来、ディレクトリごとに+
で指定する必要があるため。
rsync --exclude-from=/path/to/transfer.list /path/to/source /path/to/target
配列
資源のパスと所有者のような対応関係を記述する際は連想配列を使用する。
declare -A RESOURCE_PATH=(
["source1"]="/path/to/source1"
["source2"]="/path/to/source2"
["source3"]="/path/to/source3"
)
declare -A RESOURCE_OWNER=(
["source1"]="owner1:group1"
["source2"]="owner2:group2"
["source3"]="owner3:group3"
)
for resource in ${!RESOURCE_PATH[@]};
do
# 処理内容
<command> ${RESOURCE_PATH[${resource}]}
<command> ${RESOURCE_OWNER[${resource}]}
done
ただし、これは連想配列であって配列のような順序関係はない。
宣言通り、source1 -> source2 -> source3
の順に処理するにはさらに配列を使用する。
declare -A RESOURCE_PATH=(
# 省略
)
declare -A RESOURCE_OWNER=(
# 省略
)
declare -a RESOURCE=(
"source1"
"source2"
"source3"
)
for resource in ${RESOURCE[@]};
do
# 処理内容
<command> ${RESOURCE_PATH[${resource}]}
<command> ${RESOURCE_OWNER[${resource}]}
done
trap
シェルが異常終了する場合などの終了処理を組み込む際はtrap
を使用する。trap
はシェルが受け取るシグナルをトリガーとするのでkill
コマンドで強制終了される際にも有効。
trap "
rm -rf ${temp_directory}
rm -f ${temp_file}
exit ${return_code}
" 0 1 2 3 9 15 # trapを発火させるシグナル
後記
実際には上に書いたことより、シェルのオプションに何を用意するか、ヘルプをどう記述するかを考えたり、
また、リリースツールを第三者に動かしてもらっての手順書のレビュー指摘箇所修正などに時間を取られた。
GUIがない分、Bashに明るくない人間が読むと挙動や操作方法が理解できないものになりやすい。
実行ログは多すぎるくらい出してちょうどいい。各種コマンドのverbose
オプションを積極的に利用すること。