パターンはなぜ「コマンド|| 本当」有用ですか?


79

現在、Debianパッケージを調査しており、コードサンプルをいくつか読んでいます。また、たとえば、postinstスクリプトはすべての行でパターンです。

some command || true
another command || true

したがって、一部のコマンドが失敗すると、行はtrueを返しますが、これがプログラムの出力にどのように影響するかわかりません。


5
参考までに、||:これを記述するためのもう1つの慣用的な方法です(:ビルトインテーブル内の別のエントリを指しますが、Bourneに戻ってもビルトインであることtrue保証されています。つまり、POSIX shの場合trueも同様にビルトインであることが保証されているため、遠隔から現代にかけての効率よりも簡潔さ)。
チャールズダフィー

回答:


151

このパターンの理由は、Debianパッケージのメンテナースクリプトはで始まる傾向があるためset -e、コマンド(厳密に言えば、パイプライン、リスト、または複合コマンド)がゼロ以外のステータスで終了するとすぐにシェルが終了するためです。これにより、エラーが累積しないことが保証されます。何か問題が発生するとすぐに、スクリプトが中止されます。

スクリプト内のコマンドの失敗が許可されている場合、追加|| trueすると、結果の複合コマンドが常にステータス0で終了するため、スクリプトは中止されません。たとえば、ディレクトリの削除は致命的なエラーではありません(パッケージの削除を防止します)。だから私たちは使うだろう

rmdir ... || true

rmdirエラーを無視するように指示するオプションがないためです。


4
まあ、set -eまったく必要なしに|| true、コンテキストを提供することが重要だと思いました。POWERで奇妙なことに気づいたら、バグ(reportbug)を提出することを強くお勧めします!
スティーブンキット

16
@MichaelFeltは、実際にset -eは「Debian規約」だけでなく、常に使用すべき優れたプログラミングパターンです。見る。例:davidpashley.com/articles/writing-robust-shell-scripts
kay

2
ここでの質問-なぜ|| trueset -eを使用するのがコンテキストであり、最も一般的である可能性が高いか この答えにお辞儀をします!文字通り、終了ステータスが無関係であると見なされる場合はいつでも役立ちます(記事リンクが追加するように)、スクリプト制御の一部として終了ステータスを使用していません。ユーティリティ(set -e)が表示されますが、記事に記載されている限り、「作成するすべてのスクリプトにはset -eを先頭に含める必要があります」とは言えません。それはプログラミングのスタイルです。「ALWAYS | Every」には、独自のトラップセットが含まれていALWAYSます。
マイケルフェルト

1
@Kayそれは現在人気のある見方ですが、最終的にはスクリプトの移植性を制限する多くの仮定に夢中になります。set -e動作に歴史的な矛盾があります。ターゲットがでbashあり、に住んでいる他の比較的最近のシェルである場合、それは重要ではないかもしれません/bin/shが、古いシェル/システムをサポートしたい場合、状況はより微妙です。
mtraceur

2
@StephenKitt確かなこと。Sven Mascheckによるさまざまなシェルのset -e動作を文書化した非常に詳細なページがありますが、このページには、今日では関係のない多くの歴史的/古代のシェルも文書化されています。また、これらの2つのページには、最近のより狭いフォーカス(「set -e」を検索)があります:「lintsh」ページautoconfのポータブルシェルドキュメント->
Builtins

32

実行されるプログラムの出力には影響しませんが、すべてが正常であるかのように呼び出し側が続行することを許可します。つまり、将来のロジックに影響を与えます。

言い換え:前のコマンドのエラーステータスをマスクします。

michael@x071:[/usr/sbin]cat /tmp/false.sh
#!/bin/sh
false

michael@x071:[/usr/sbin]cat /tmp/true.sh 
#!/bin/sh
false || true

michael@x071:[/usr/sbin]sh /tmp/false.sh; echo $?
1
michael@x071:[/usr/sbin]sh /tmp/true.sh; echo $? 
0

6
それは事実ですが、なぜコマンドの終了ステータスをマスクすることが有用なのかは答えていません。
moopet

4
set -eは、ゼロ以外の戻り時にスクリプトが即座に終了することを意味します。あなたは、そのローカライズされた場所で、それが起こることを望まないかもしれません!
rackandboneman

私は単純な人です-そして、私にとってエラー状態を隠す唯一の理由は、それが「邪魔」だからです。set -eは、気にする前であればエラーを「邪魔に」します。スクリプトをデバッグし、エラーに応答するための追加のロジックを作成するのに役立つ良い方法だと思うので、この議論が好きです(例えば、|| print-"xxx exists non-zero here"。シェル関数「致命的」と私は「何か||致命的な「不幸な私」を持っています。スクリプトは失敗したステータスを報告するか、気にしないでください。-e plus || trueはマスキングエラーです。そうでない場合、エラーがありません
マイケルフェルト

私が自問しなければならないのは:|| true-コーディング松葉杖(今私が対処したくないエラーを回避/ペーストする怠lazな方法;デバッグツール(-eがありません|| true)またはコーディングの実践とは何かのドグマ。 -私はそれを機能と見なします-潜在的な利点があります。私はそれをすべてを治す魔法の杖とは見なしません。要するに-美しさが見る人の目にあるように- set -eそして|| true効用はその特性と目標プログラマー
マイケルフェルト

6
@MichaelFelt考慮:git remote remove foo || true git remote add foo http://blah-リモートが存在しない場合、エラーを無視したい。
user253751
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.