適応中です。マーカス・ミュラーの答え 先週質問しました。標準出力をtmuxセッションにリダイレクトしてANSIエスケープシーケンスをレンダリングし、ウィンドウレンダリングをスクリプトの実際の出力にキャプチャするスクリプト。 stdoutで直接印刷して同じ結果を得ることができるので、まったく役に立たないことを知っています。ただし、これはより複雑な解釈を通じてコードをより大きなプロジェクトにインポートするためのデモであり、次の機能が必要です。
#!/bin/zsh
tmpdir="$(mktemp -d)"
fifo="${tmpdir}/fifo"
mkfifo "$fifo"
tmux new-session -d -s aux "while true; do cat ${fifo}; done"
exec 3>&1 1>"$fifo"
echo foo
echo bar
tput home
echo -n b
exec 1>&3 3>&-
tmux capture-pane -t "aux" -p -S0 -E1
tmux kill-session -t aux
rm -rf $tmpdir
出力は次のようになります(そしてそれが必要です)。
boo
bar
コードの簡素化に興味があります。メンテナンスが必要なFIFOの代わりに使用できるstdinリダイレクトに関連するトリックはありますか? 1行の方法ですべてのコンテンツを印刷し続け、完了したらセッションを自動的に閉じることができますか?
tmuxパイプウィンドウ、バッファ、トランスポートキー、実行シェルを試しましたが、うまくいきませんでした。特に、コマンド/スクリプトを実行するスクリプトのstdinではなく、コンソールにコマンドを作成するのと同じように、セッションがstdinを使用する場合
なんとか単純化しなければならないような感じがします。
答え1
メンテナンスが必要なFIFOの代わりに使用できるstdinリダイレクトに関連するトリックはありますか?
新しいセッションに割り当てられたユニークウィンドウのユニークウィンドウの内容を尋ねますtmux
。tty
その後、印刷します。
#!/bin/zsh
tmux new-session -d -s aux 'tail -f /dev/null' || exit 1
tty="$(tmux display-message -p -t aux -F '#{pane_tty}')"
{
echo foo
echo bar
TERM=tmux tput home
echo -n b
} > "$tty"
tmux capture-pane -t aux -p -S0 -E1
tmux kill-session -t aux
tmux display-message -p
一般的に言えば、それから情報を得ることは非常に便利です。あなたの場合はttyに関する情報を直接得ることができ、tmux new-session
その変数は必要ありませんtty
。リダイレクトを設定するために、次の準備手順を実行する必要はありません。
{...} >"$(tmux new-session -d -s aux -P -F '#{pane_tty}' 'tail -f /dev/null')" || exit
注はtail -f /dev/null
tmuxウィンドウを「アクティブ」に保つためのコマンドです。スクリプトはコマンドに何も送信しようとしませんが、正しいttyに印刷します。この回答は、タイトル(「tmuxセッション内で実行される他のスクリプト/コマンドの標準入力へのスクリプトの標準出力リダイレクト」)には対応していませんが、必要な機能を提供します。
答え2
正確に何を求めるのかよくわかりません。エスケープシーケンスを処理するためにtmuxを使用するという概念を受け入れますが、ただFIFOを削除したいですか?
必要な結果のみを作成してくださいtmuxから:
tmux new-session -d -s aux "echo foo; echo bar; tput home; echo -n b"
tmux capture-pane -t aux -p -S0 -E1
tmux kill-session -t aux
FIFOの内容を無視します。
$fifo
PSなどのシェル変数を引用する必要があります$tmpdir
。空白以外の文字で構成される定数文字列を実際に引用する必要はありません"aux"
。
答え3
そんなことができないと思います。tmux
これは、2(そして分離されたときに0、1、2)以上で受信されたすべてのfdが閉じられるためです。
close_range(3, 4294967295, 0)
出力で同等の項目を確認するか、ソースから呼び出してください。strace
closefrom(STDERR_FILENO + 1)
したがって、名前付きパイプまたは環境変数(NUL文字を含まない)を介して、またはソケット、一時ファイル、共有メモリによって実行されるシェルコードに含まれる他の方法でデータを渡す必要があります。tmux
どちらも真実ではありません。より簡単またはより安定しています。
しかし、あなたのアプローチには多くの問題があります。
- 固定セッション名を使用しています。これは、スクリプトへの2つの呼び出しが同時に実行されないことを保証できない場合、スクリプトを確実に使用できないことを意味します。セッション名を選択して
tmux
オプションで-P
検索できますnew-session
。 - 同期は行いません。実行すると完了または開始される
capture-pane
保証はありませんcat
。ウィンドウの内容を検索すると、tmuxセッションを終了するように指示するのではなく、ループ+シャットダウンを実行します。 $fifo
新しいセッションで実行されるシェルコードにコンテンツを含めます。環境変数として渡されるのが最善です。mktemp
の終了ステータスを確認していませんmkfifo
。- tmuxはユーザーのデータを読み取ります
~/.tmux.conf
。これは処理を妨げる可能性があります。 - これはスクリプトを実行するホスト端末ではなく最終的に解釈される端末エミュレータであるため、
TERM=tmux
環境tput
(またはzshの組み込み同等項目)に渡す必要があるため、エスケープシーケンスを送信する必要があります。echoti
tmux
それむしろホスト端末が理解している。 - を使用すると、
-S0 -E1
ウィンドウの最初の2つの表示行のみがキャプチャされます。 - ホスト端末ウィンドウと同じサイズのウィンドウを作成するようにtmuxに指示できます。
- 出力が1つの画面に収まらない場合は、スクロールバックバッファの内容を取得することもできます。
おそらく次のようになります。
#! /bin/zsh -
tmpdir=$(mktemp -d) || exit
trap 'rm -rf -- $tmpdir' EXIT INT TERM HUP QUIT
in=$tmpdir/in out=$tmpdir/out
mkfifo -- $in $out || exit
session=$(
IN=$in OUT=$out tmux -f /dev/null new-session -PEd -x ${COLUMNS:-80} -y ${LINES:-24} '
cat -- "$IN"
echo done > "$OUT"
read may_I_exit < "$IN"
'
) || exit
cat "$@" > $in || exit
read can_I_retrieve_the_output < $out || exit
tmux capture-pane -t $session -pS-
echo you may exit > $in
たとえば、次のようになります。
$ (TERM=tmux; print -rln foo bar$terminfo[home]b) | ./capture | hexdump -C
00000000 62 6f 6f 0a 62 61 72 0a 0a 0a 0a 0a 0a 0a 0a 0a |boo.bar.........|
00000010 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a 0a |................|
*
00000040 0a 0a |..|
00000042
(マイターミナルウィンドウの高さは60行なので、すべて0x0a(LF)バイトに注意してください。)
(婦人声明:私はtmuxユーザーではないので、これを行うよりスマートで正確な方法があります。)
1この機能に関する限り、自己エミュレーション()と他のエスケープシーケンスを持つ端末をhome
使用する可能性がないため、実際に影響を与える可能性はほとんどありません。home
tmux
\e[H