ファイルの最後まで実行するように設計されたダッシュシェルスクリプトがあります。
#!/usr/bin/dash
# File b_shell
. a_nonexistent_file
echo "I want to print this line despite any previous error."
ただし、存在しないファイルのインポートに失敗すると、実行は停止します。
$ ./b_shell
./b_shell: 3: .: a_nonexistent_file: not found
インターネット上で簡単に見つけることができるなどset -e
の候補ソリューションを試してみましたが、役に立ちませんでした。|| true
追加情報:
- Bash、tcshなどの他のシェルは使用できません。俺を変えないでください。
- 以下のようにスクリプトを停止しない他の「見つかりません」エラーが見つかりました。
#!/usr/bin/dash
# File b_shell_ok
a_nonexistent_command
ls a_nonexistent_file
echo "This line is printed despite any previous error."
$ ./b_shell_ok
./b_shell_ok: 3: a_nonexistent_command: not found
ls: cannot access 'a_nonexistent_file': No such file or directory
This line is printed despite any previous error.
答え1
.
特別な組み込み関数だからです。これは POSIX 要件です。他のほとんどのPOSIXシェルもこれを行いますが、それが対応するposix / sh / kshモードにある場合にのみ(呼び出し時に含まれますbash
)。zsh
sh
特殊な組み込み関数の特殊性を排除するPOSIXメソッドは、その関数に接頭辞を付けることですcommand
。
$ dash -c 'command . /x; echo here'
dash: 1: .: cannot open /x: No such file
here
exit
これは、ソースファイルの呼び出し中またはコンテンツの解釈中に致命的なエラーが発生した場合にシェルが終了するのを防ぎません。ダッシュ(たとえば反対)の場合、bash -o posix
ソースファイルに埋め込まれた特殊関数が失敗してもシェルは終了しませんcommand
。
このオプションも有効な場合、errexit
ソースファイルを開くことができない場合、シェルは終了し続けますが、今回はゼロ以外のcommand
終了ステータスを返します。
$ dash -o errexit -c 'command . /x; echo "$? here"'
dash: 1: .: cannot open /x: No such file
解決策はエラーを処理することです。
$ dash -o errexit -c 'command . /x || echo "that is fine"; echo "$? here"'
dash: 1: .: cannot open /x: No such file
that is fine
0 here
または:
$ dash -o errexit -c 'command . /x && : non-fatal; echo "$? here"'
dash: 1: .: cannot open /x: No such file
2 here
(またはcommand .
//ステートメントの条件付き部分を呼び出します)。if
while
until
この場合(例とは異なり、dash
少なくとも現在のバージョン)、ソースファイルのコード評価効果はキャンセルされません。bash -o posix
errexit
$ dash -ec 'command . ./file || echo fine; echo here'
before
$ bash -o posix -ec 'command . ./file || echo fine; echo x'
before
after
x
errexit
最も単純なスクリプトを除いて、いくつかの理由の1つで避けるのが最善です。
zsh はcommand
POSIX よりも先行し、意味が異なります。command .
sh エミュレーション/POSIX モードでない場合は使用できません。
このエラーを回避するには、stderrの削除中に一部のfdでファイルを開き、事前にTOCTOUレースに付属のチェックを実行するのではなく、そのファイルをインポートできます/dev/fd/n
。
$ dash -c '{ command . /dev/fd/3; } 4>&2 2> /dev/null 3< file 2>&4 4>&-; echo here'
here
リダイレクトが失敗した場合、リダイレクトされたコマンド(ここではコマンドグループ) が実行されないため、シェルは特殊な組み込み機能を実行しようとしないため、シェルのシャットダウンによる副作用を回避できます. OSがLinuxまたはCygwinで、オープンがaと等しくないcommand
場合は、プレフィックスを追加し、ファイルがfd 3で開かれてからファイル権限が変更された場合でも、失敗する可能性があります。/dev/fd/x
dup(x)
答え2
それPOSIXの要件このような失敗はシェルを停止する必要があります。
読み取り可能なファイルがない場合、非対話型シェルは終了します。
したがって、唯一のオプションは、ファイルが存在し、必要に応じて読み取り可能であることを確認してコマンドを保護することです。
[ -f file ] && [ -r file ] && . ./file
if
ファイルが存在しない場合は、エラーまたは警告メッセージを印刷するためにそれを完全なステートメントに拡張することもできます。