端末の特定の場所にあるバックグラウンドプロセスのstdoutを表示する


8

新しい端末が開かれるか、新しいログインが行われるたびに実行するコマンドがあります。

このプログラムは、コマンドプロンプトの前に配置される出力(色付き)を生成します。実行に数秒かかる可能性があり、それまでは(バックグラウンドで実行されない限り)端末を使用できません。

zshには既存のテキストを壊さずにターミナルを再描画する高度な方法があるので、ターミナルを使用する前にコマンドが完了するのを待つ必要がないように、このコマンドを実行する方法を知りたいのですが終了すると、最初からバックグラウンド化されていないかのように出力を印刷します。

実際には、私ができることを望みます:

Command output:
... (running on background)
me@computer: somecommand
me@computer: someothercommand

コマンドが完了すると、次のようになります。

Command output:
 * Output foo
 * Multiple lines bar
 * and some yada
me@computer: somecommand
me@computer: someothercommand

プロセスをバックグラウンドで開始しようとしましたが、出力がきれいに表示されません。私は次のようなものを得ます:

Command output:
[2] 32207
me@computer: somecommand
me@computer: someother * Output foo
 * Multiple lines bar
 * and some yada
[2]  + done       command
me@computer: someothercommand

それで、これは可能ですか?zshを使用しない場合、それを実行できる解決策はありますか?

ポインタや情報は大歓迎です。


プログラムがターミナルで直接実行されている場合は、カーソル位置とzshが1つしかなく、プログラムがそれと競合するため、それは不可能です。あなたは何かをすることができますzpty:コマンドをzshによって作成された端末で実行させ、その出力をzshの制御下の実際の端末に中継します。
Gilles「SO-邪悪なことをやめ

@ギレスの使用法について詳しく教えてくださいzpty。カーソルをめぐって何らかの競合がなければ、2つのプログラムが同じ端末に書き込むことはできないことを知っています。私の質問は、zshが一部の構成で既にプロンプ​​トを書き換えているという事実から来ています。明らかに、このプログラムは、コマンドが終了すると特定の場所に「出力」される一時的なメモリ内バッファに書き込む必要があります。後者はすべてzshの制御下にあります。
unode

@ギレス:多分これは本当の答えの価値がありますか?
ステファン・ヒメネス

@StéphaneGimenezもちろんです。調査なしではどうすればいいのかわかりませんし、今この調査をする時間もありません。
Gilles「SO-悪をやめ

screen画面を分割し、上部で長いランナーを実行し、下部で通常のコマンドラインを実行する起動スクリプトを使用して、これを行うことをお勧めします。
vasquez

回答:


5

現在のプロンプト行のすぐ上で出力を受け入れる場合は、これが簡単な解決策です。

TRAPUSR1 () { zle -I; unfunction TRAPUSR1 }  # invalidate prompt on signal USR1

bufferout () {
    local buffer
    while read -r line; do                   # buffer lines from stdin
        buffer="$buffer$line\n"
    done
    print -rn -- $terminfo[dl1]              # delete current line
    print -rn -- $terminfo[cr]               # move cursor to BOL
    printf "$buffer"                         # print buffer
    kill -USR1 $$                            # send USR1 when we're done
}

unsetopt monitor                             # don't monitor this job
./testout |& bufferout & disown              # bg and disown to suppress notification
setopt monitor                               # restore job monitoring

ジョブが完了すると、現在のプロンプトと入力バッファーが削除され、コマンドのstdoutstderrがすべて印刷されます。

このモジュールでそれよりもはるかに豪華になることができますzsh/curses、努力に値するほど十分に大きな利点が得られるとは思えません。


これは機能します。しかし、バックグラウンドに送信されたときにシェルがプロセスpidを出力し、完了時に「done」メッセージが表示されないようにするのはどれほど難しいでしょうか。(つまり、その機能を一時的に無効にします)。また、出力を端末に置く前に、既存のプロンプト行をクリアするのはどれほど難しいでしょうか?
unode

私は、最初のプロンプトの削除と衝突する他のプロンプト書き換え設定があると思います。コマンドが終了しても鉱山は消えません。バックグラウンドに送信されたときにもプロセスのPIDを取得していますが、「done」行がなくなっています。いずれにしても、私が考えていたものにかなり近いので、私はあなたの答えを受け入れます。ありがとう。
unode

xtermを使用していて、VCSモジュールを有効にして、プロンプトに対するその他のカスタマイズを行っています。私は試したことはありませんが、それに関連していると確信しています。しばらく前に、これと同様のviモード通知機能(stackoverflow.com/a/3791786/125801)を使用してみましたが、アクティブなときにカスタムプロンプトの動作の一部が失われました。それは大した問題ではありませんが、現時点では解決策に満足しています。これらの日の1つでプロンプトをクリーンアップして、PIDがまだ表示されるかどうかを確認します。
unode

zshの-4.3.10は、ほとんどすべてのカスタマイズを無効にした後、私は今、もはやプロンプトを取得していない(すなわち、それが適切に削除されます)が、私はまだのように、バックグラウンドでのプロセスのPIDを取得する[1] 27911 27912単一のラインにし、上の最初の行にターミナル。
unode

もう一度賛成してもいいですか?:)それは今完璧です!本当にありがとう。
unode
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.