我正在改编Marcus Müller 对我上周提出的问题的回答 - 一个将其标准输出重定向到 tmux 会话以渲染 ANSI 转义序列的脚本,然后捕获窗格渲染作为脚本的真实输出。我知道它根本没有用,因为您可以将其直接打印到标准输出并获得相同的结果,但这只是一个演示,可以将代码带到一个更大的项目,更复杂的解释,我需要这个功能:
#!/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?我可以使用单行程序以某种方式继续打印所有内容并在完成后自动关闭会话吗?
我尝试使用 tmux 管道窗格、缓冲区、发送键和 run-shell,但无法成功。特别是当会话采用标准输入时,就像您在控制台上编写命令一样,而不是像正在运行的命令/脚本的脚本的标准输入一样
我觉得它必须以某种方式简化。
询问分配给新会话的唯一窗口的唯一窗格的
tmux
内容。tty
然后打印到它。tmux display-message -p
一般来说,从中获取信息非常有用。tmux new-session
在你的情况下,你可以直接从;获取有关 tty 的信息。并且您不需要该tty
变量。您无需执行任何预备步骤即可设置重定向,如下所示:Note
tail -f /dev/null
只是一个保持 tmux 窗格“活动”的命令。该脚本不会尝试向该命令发送任何内容,而是打印到正确的 tty。这个答案没有解决标题(“将脚本的标准输出重定向为 tmux 会话中运行的另一个脚本/命令的标准输入”),但它为您提供了您想要的功能。我不清楚你到底在问什么。您是否接受使用 tmux 处理转义序列的概念,但只想消除 FIFO?
尝试在 tmux 中生成您想要的输出:
并忽略 FIFO 的内容。
PS 您应该引用 shell 变量,例如
$fifo
和$tmpdir
。您实际上不需要引用由非空白字符组成的常量字符串,例如"aux"
.我认为你不能做类似的事情,因为
tmux
会关闭它收到的所有高于 2 的 fd(以及分离时的 0、1、2)。请参阅(或等效)输出或源中的调用
close_range(3, 4294967295, 0)
中的等效项。strace
closefrom(STDERR_FILENO + 1)
因此,您需要以其他方式传递数据,或者通过像您一样的命名管道或环境变量(但不能包含 NUL 字符)或嵌入由
tmux
套接字、临时文件、共享内存运行的 shell 代码中,其中没有一个真的会更简单或更可靠。但您的方法存在许多问题:
tmux
选择会话名称并通过选项检索-P
它new-session
。capture-pane
,不能保证它cat
会完成甚至开始。当您检索窗格的内容时,您正在执行循环+终止,而不是告诉 tmux 会话退出。$fifo
您将在新会话中运行的 shell 代码中嵌入内容。最好作为环境变量传递。mktemp
或 的退出状态mkfifo
。~/.tmux.conf
,这可能会干扰处理TERM=tmux
到环境tput
(或 zsh 的内置echoti
等效项),因为这是一个tmux
最终解释的终端仿真器,而不是您运行脚本的主机终端,因此您需要向它发送转义序列,而不是主机终端无法理解。-S0 -E1
,您仅捕获窗格的前 2 行可见行所以,也许是这样的:
那么例如:
(注意所有 0x0a (LF) 字节,因为我的终端窗口有 60 行高)。
(免责声明:我自己不是 tmux 用户,所以很可能有更聪明或更正确的方法来做到这一点)
1 尽管就该功能而言
home
,它在实践中不太可能产生影响,因为您不太可能使用转义序列与自己home
的仿真不同的终端 ( )。tmux
\e[H