2022年1月11日火曜日

bash スクリプトの実行中上書き動作が ansible copy module で再現するのか試してみた

きっかけはこちら 「スーパーコンピュータシステムのファイル消失のお詫び
bash のスクリプト実行中にファイルを上書きすると、実行中の場所から上書き後の状態で実行される挙動(以下、本挙動)があり、それにより意図しない処理がされてしまったという感じ。
わかりやすい例はこの辺を参考にしてください。

Tips: 実行中のシェルスクリプトを書きかえるときには - Qiita
bash スクリプトの実行中上書き動作について

この記事は ansible で本挙動と同じことが起こり得るのかの検証記事です。



さて、結論から言うと・・・「再現しない」でした。安心してください。
仕事で ansible 使って .sh を配布してたのでちょっと心配だったんですよね。良かったです。



では、以下から検証内容を詳しく見ていきます。
(公開当初に検証用の repository が private になってました。すみませんでした)

bash のスクリプト実行中の上書き実験 by srz-zumix · Pull Request #3 · srz-zumix/ansible_dotfiles

こちらの PR で検証コードを書いて、GitHub Actions で実行してみました。
検証コードは↑で紹介した記事のサンプルスクリプト(echo foo/bar)を使っていて、copy module を使ったファイルコピーと shell module で cp コマンド使ってコピーした場合を検証しています。
このへん→https://github.com/srz-zumix/ansible_dotfiles/blob/main/roles/bash-cp-test/tasks/test-loop.yml#L19

実行中に上書きするために async を使用しています。
async タスクの完了待ちは async_status で状態を確認して待っています。
こういう書き方は普段しないので勉強になりました。

この ansible を playbook すると再現した場合は「bar」、再現しなかった場合は「foo」と表示されます。
結果はこちら


cp コマンドでは「bar」、copy module では「foo」でした。
cp コマンドの場合に再現しているので検証コードには問題がないと言えます。
よって copy module では本挙動は再現しないと言えます。
本挙動が発生するかしないかは inode が変わるか変わらないがポイントとなっており、コピー前後の inode をデバッグ出力もしています。上のスクリーンショットのログは cp コマンドの場合のログで、inode が変わってないことが見て取れます。(スクリーンショットにはありませんが、copy module では inode が変化してました)
実行結果は GitHub Actions のログでも確認できますので、詳細はそちらを参照してください。

ちなみに copy module は remote_src: true でリモートマシン内でのファイルコピーができますが、その場合も本挙動は「再現しない」です。
なぜなら copy module の実装で remote_src の true/false によらず atomic_move を使用して新しいファイルに更新しているからです。atomic_move は os.rename を使ったファイルリネームで実装されており、この atomic_move を使っていれば copy module 以外でも本挙動は発生しないと考えてよいでしょう。
(不安だったのでテスト追加した。https://github.com/srz-zumix/ansible_dotfiles/pull/4 cp コマンドの対としては remote_src のほうが適切だったと後で思った)

以上。

0 件のコメント:

コメントを投稿