• トップ
  • 技術ブログ
  • Bash の AND 演算子、 OR 演算子での条件判定の実行順序で勘違いしていたこと

TECHBLOGスキルブログ

Bash の AND 演算子、 OR 演算子での条件判定の実行順序で勘違いしていたこと

2015.06.29

こんにちは、野口です。
Bash でちょっとはまったことがありましたので、メモを兼ねて共有です。

2015-06-08_22h33_50

Linux サーバに SSH の公開鍵を登録するときに、 .ssh ディレクトリがそもそも掘られていなかったり、
authorized_keys あたりのパーミッション調整等、数コマンドですが、いろいろチェックしてやることがあります。
毎度毎度同じことをやっているなと思い、ワンライナーでできないか考えて以下のようなシェルスクリプトを書きました。

([ ! -e ~/.ssh ] && mkdir ~/.ssh && chmod 700 ~/.ssh ) || cat <<EOF >>~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
ssh-rsa blahblahblah rsa-key-20150608-comment
EOF

これはうまくいくときもありますが、うまくいかないときもあります。
正しくはこうです。

([ ! -e ~/.ssh ] && mkdir ~/.ssh && chmod 700 ~/.ssh ) ; cat <<EOF >>~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
ssh-rsa blahblahblah rsa-key-20150608-comment
EOF

何が違うかお分かりでしょうか?
後者の例では || 演算子を使うのではなく、 ; で次のコマンドに制御が移るようにしています。
前者の例では ( ) 内の実行結果が真の場合は後ろのコマンドは評価されません。
つまり、 .ssh ディレクトリがなかったら作成されますが、 cat コマンドでファイルを生成している部分は実行されず、後ろの chmod コマンド実行に引き継がれてファイルが存在しない旨のエラーとなります。

によれば以下のように説明されています。

OR リストは
[ command1 || command2 ]
という形式であり、 command1 が 0 以外の終了ステータスを返した場合に限り command2 が実行されます。

前者の例では前の実行結果の真偽にかかわらず後ろのコマンドも実行されると予期していたのですが、
前のコマンドの実行結果が真偽にかかわらず後ろのコマンドを実行したい場合は複数のコマンドをつなげる ; を使えばいいのです。

一般的なプログラミング言語でも同じことが言えます。
OR 演算子で繋げられた条件文は前文の式の評価結果が真なら後ろの条件式の評価は省略されます。
後ろの条件式の評価のコストが無駄だからです。
シェルスクリプトを覚えていくと意外といい頭の体操になるなと感じた一例でした。


              

OTHER CONTENTSその他のコンテンツ

UNITRUST会社を知る

  • 私たちについて

  • 企業情報

SERVICE事業内容

  • システム開発

CONTACT
お問い合わせ

あなたの「想い」に挑戦します。

どうぞお気軽にお問い合わせください。

受付時間:平日9:00〜18:00 日・祝日・弊社指定休業日は除く

お問い合わせ