web-dev-qa-db-ja.com

プロンプトをハイジャックせずにバックグラウンドプロセスから進行状況をエコーする

単純なスクリプトhelloについて考えてみましょう。

#!/bin/bash

echo 'hello world!'

これをバックグラウンドで実行しようとすると、bashから次のようになります。

$ hello &
[1] 12345
$ hello world!
█ <--- Prompt is stuck here until I hit enter!
[1]+ Done
$ █ <--- Prompt back to normal

私がむしろ見たいもの:

$ hello &
[1] 12345
[1]+ hello world!
[1]+ Done
$ █ <--- Prompt normal the whole time

どうすれば動作を変更できますか?

10
Dave Johnson

タイミングの問題です。bashはバックグラウンドでhelloコマンドを起動し、新しいコマンドを入力するためのプロンプトを表示し、バックグラウンドコマンドが出力を出力します。次のコマンドライン(を押すだけの場合は空のコマンドライン)に入るとき Enter)、bashは、バックグラウンドジョブが終了したという通知を表示し、次に次のプロンプトを表示します。

sleep 3で始まるスクリプトを試して、スクリプトをバックグラウンドで起動した直後に入力を開始して、フォローできるペースで何が起こっているかを確認することをお勧めします。

notifyオプションに set -b を設定すると、バックグラウンドジョブが終了したときにbashにすぐに通知させることができます。次に、次のように表示されます。

$ set -b
$ hello &
[1] 12345
$ hello world!
[1]+ Done

この場合、Bashはプロンプトを再描画しません。バックグラウンドジョブがhello world!を出力する前に表示されたプロンプトラインのコマンドラインをまだ編集しています。を押すと、現在の線を再描画できます Esc1Ctrl+L。コマンドredraw-current-lineをより便利なキーにバインドすることをお勧めします。たとえば、 Ctrl+L 現在の線を再描画し、 Ctrl+Alt+L 画面をクリアし、~/.inputrcに次の行を追加します。

"\C-l": redraw-current-line
"\e\C-l": clear-screen

Bashにプロンプ​​ト行を自動的に再描画させる方法がわかりません。 Zshはデフォルトでそれを行います。