条件付き実行は、Bashの子プロセスの終了状態に応じてスクリプトフローを制御するために使用されます。ただし、場合によっては、子プロセス(アプリケーション)が対話型の目的でバックグラウンドで実行されるため、終了せずに閉じるまで終了状態はありません。
PDFビューアの実行など、いくつかの例を考えてみましょう。ドープ。 example.pdfファイルが存在する最初のケースを考えてみましょう。
$ mupdf example.pdf &
[1] 16220
動作するので、条件付き実行を試してみましょう。
$ mupdf example.pdf & && echo TRUE
bash: syntax error near unexpected token '&&'
まあ。さて、エラーを避けるために別の(人工的な)アプローチを試してみましょう。
$ if mupdf example.pdf &; then echo TRUE; fi
bash: syntax error near unexpected token ';'
どうですか?
$ if (mupdf example.pdf &); then echo TRUE; fi
TRUE
これは有望に見えますが、存在しないファイルを使用して2番目のケースを試してみましょう。
$ mupdf nofile.pdf &
[1] 16282
$ error: cannot open nofile.pdf
error: cannot load document 'nofile.pdf'
mupdf: error: cannot open document
$ if (mupdf nofile.pdf &); then echo TRUE; fi
TRUE
$ error: cannot open nofile.pdf
error: cannot load document 'nofile.pdf'
mupdf: error: cannot open document
その構造も機能しません。したがって、終了状態がないため、一般的な条件付き実行アプローチは機能しません。しかし、成功した場合と失敗した場合は、最初にpidが生成されることがわかりました(ドープ2番目のケースでは開けません。結局、起動は失敗します。
だから私は別のアプローチを試して、背景PIDで何が起こるのかを待って、次のスクリプトを書いています。
#!/usr/bin/env bash
# usage: ./show <file>.pdf
mupdf "$1" &>/dev/null &
sleep 2
if kill -0 $! &>/dev/null
then
echo TRUE
else
echo FALSE
fi
# end file
そして最初のケースをテストしてみてください。
$ ./show example.pdf # case 1
[1] 16602
TRUE
それは問題ではありません。 2番目のケースは次のとおりです。
$ ./show nofile.pdf # case 2
[2] 16699
[2]+ Exit 1 mupdf nofile.pdf &> /dev/null
FALSE
まあ、それも動作します。ただし、これはプロセスを確認する非常に複雑な方法であるように見え、開始に時間がかかると(2秒以上)失敗する可能性があります。それで、私の質問はこの問題を解決するより良い(よりクリーンな)方法がありますか?
答え1
このトピックに似たトピックをたくさん見つけました。以下を試してください。xdoツールそしてコントロールパネル永続ウィンドウアプリケーションまたはその他の永続サブプロセスの開始をテストするために使用されます。しかし、これを使用することは不必要な複雑に見えます。以下のソリューションを使用すると、永続的なサブプロセスを条件付きで実行できます。 0.5秒の睡眠時間を活用します。関心のあるサブプロセスを正常に開始するのに時間がかかる場合は、この期間も増やす必要があります。
バッシュソースファイル放射
#/usr/bin/env bash
# launch : will allow launching a windowed application or persistent
# sub-process in the background so that conditional execution can be
# applied to determine whether or not it has launched successfully -
# dependencies: GNU coreutils (sleep), util-Linux (kill)
# usage: ./launch process arg_1 .. arg_n && echo TRUE || echo FALSE
$@ &>/dev/null & sleep 0.5 && kill -0 $! 2>/dev/null
# end file
する:
$ ./launch mupdf example.pdf && echo TRUE || echo FALSE
TRUE
$ ./launch mupdf nofile.pdf && echo TRUE || echo FALSE
FALSE
この情報については、次の提案を含めることが役に立つと思いました。マックサイフオープニング記事へのコメントです。
上記の構成が現在の作業を達成していることを考慮すると、マックサイフこれを指摘すると、シグナルを呼び出しスクリプトに伝播せずに無視して削除するため、他の問題が発生する可能性があります。これは非常に重要な観察です。
シグナルはプロセス間通信の重要な要素であり、イベント駆動型スクリプトの可能性につながる可能性があります。したがって、より強力で効率的なスクリプトのためにマックサイフ信号が伝播するように信号をキャプチャするには、次の方法をお勧めします。
{ mupdf some.pdf || kill -"$(($?&127))" "$$"; } &
1 から 128 個の可能な信号 (POSIX) を操作できる$?&127
Debian システムには 64 個があり、代わりに信号マスクを$?&63
使用できます。
したがって、結論として、プロセス間通信に興味がない非常に単純なスクリプトの場合にお勧めします。放射役に立つかもしれませんが、より多くの場合、特にプロセス間通信が重要な場合は、提案されているように信号をキャプチャ(および伝播)します。マックサイフ。
答え2
一行で:
mupdf example.pdf & echo mupdf is now in the background; wait $! && echo FINISHED successfully