誰かがこのスクリプトの理由を説明できますか?
echo one &&
echo two &
echo three &&
echo four
私にください
[1] 3692
three
four
one
two
[1]+ Done echo one && echo two
当然、バックグラウンドプロセス以降のすべての内容が最初に出力され、その後、バックグラウンドプロセスの前のコード行が時系列で印刷されます。私は私が書こうとしたシナリオでそれを偶然見つけましたが、それがなぜそうなったのかわかりませんでした(ただし、後ろに少し独創性があると思いますが)。
私はかっこを使ってこれを防ぐことができることを発見しました:
echo one &&
(echo two &)
echo three &&
echo four
与えられた
one
two
three
four
そして
echo one &&
(sleep 2 && echo two &)
echo three &&
echo four
与えられた
one
three
four
two
2行目はバックグラウンドでスタンバイ状態なので、1行目はすでに実行中に出力されます。
しかし、なぜかっこがこのような効果をもたらすのでしょうか?
追加の質問:括弧がバックグラウンドPID出力を妨げるのはなぜですか?
答え1
echo one && echo two & echo three && echo four
覚えておいてください。これは次のように解析されます。
echo one && echo two &
echo three && echo four
私はこのecho
コマンドが成功したと仮定します(フルディスクのファイルにリダイレクトするなどの極端な場合にのみ失敗します)。したがって、このコードスニペットは2つのタスクを並列に実行します。 1 つは行の合計を印刷しone
、もう 1 つは行のtwo
合計を印刷します。合計と合計の分散は保証されず、システム、シェル、および呼び出しによって異なる場合があります。このような簡単な例を使用すると、負荷の低いシステムで再現可能な結果を見ることができますが、これは信頼できるものではありません。three
four
one
two
three
four
echo one && (echo two &) echo three && echo four
解析を変更しました。ここでは、コマンドのみがecho two
バックグラウンドで実行されます。これはone
最初に出力され、beforeと同様にthree
常にbeforeになりますが、four
場所はtwo
afterのどこにでも配置できますone
。
シェルは、デフォルトのシェルプロセスで開始された場合にのみバックグラウンドプロセスのメッセージを印刷し、サブシェルで起動された場合にはそのメッセージを印刷しません。括弧はサブシェルを生成するので、シェルは(echo two &)
メッセージを出力しません。これによりバックグラウンドプロセスが作成されますが、バックグラウンドは生成されません。働く。
echo one && (sleep 2 && echo two &) echo three && echo four
このコードでは、バックグラウンドジョブは出力する前に2秒間休止状態になりますtwo
。これにより、two
後に出力がある可能性が非常に高くなります(実際には保証されません)。three
four
答え2
パート1
echo one &&
echo two &
echo three &&
echo four
これは次のように書き直すことができます。
echo one && echo two &
echo three && echo four
three
最初にandを取得する理由は、単にandを印刷するよりも、サブシェルfour
でone
andを処理して実行するのに時間がかかるためです。two
three
four
このように見れば、より確実にわかります。
echo one && echo two &
sleep 1
echo three && echo four
この場合、あなたone
はとを取得しますtwo
。しばらくするとあなたはとthree
を得ますfour
。
もともとのシナリオでは、 と が and の出力one
と混在しないという保証はなく、または同じ単語が挿入される場合にも可能です。two
three
four
thonreee
twfouro
パート2
echo one &&
(echo two &)
echo three &&
echo four
これは次のように書き直すことができます。
echo one && (echo two &)
echo three && echo four
ここで何が起こるのかは、one
すぐに印刷してtwo
サブシェルでトリガーされることです。その後、次の行が(連続して)実行され、three
sumが生成されますfour
。特別な場合、サブシェルはtwo
出力する前に印刷できるほど小さく、高速です。three
しかし、これに対する保証はありません。
3番目の部分
ステートメントをサブシェルにグループ化します。 &記号は&
ステートメントに対して機能しますが、この場合は2つのコマンドを一緒にリンクするために使用したので、単一の&&
ステートメントとして扱う必要があります。
echo one; echo two
たぶん代わりに使うべきですかecho one && echo two
?彼らは非常に異なります。セミコロンは、;
2つのコマンドを区別して独立して順次実行されます。デュアルアンパサンドは&&
2つのコマンドを一緒に接続します。論理AND、最初が正常に完了するまで2番目が実行されないようにします。false; echo yes
、、、false && echo yes
およびを比較しますtrue && echo yes
。それから&&
(論理AND)と||
(論理的または)。
ボーナス
サブシェルにはジョブ制御がないため、ジョブ制御通知が失われます。