AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 772947
Accepted
Whimusical
Whimusical
Asked: 2024-03-23 08:19:58 +0800 CST2024-03-23 08:19:58 +0800 CST 2024-03-23 08:19:58 +0800 CST

将脚本的标准输出重定向为 tmux 会话中运行的另一个脚本/命令的标准输入

  • 772

我正在改编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,但无法成功。特别是当会话采用标准输入时,就像您在控制台上编写命令一样,而不是像正在运行的命令/脚本的脚本的标准输入一样

我觉得它必须以某种方式简化。

zsh
  • 3 3 个回答
  • 73 Views

3 个回答

  • Voted
  1. Best Answer
    Kamil Maciorowski
    2024-03-25T02:55:23+08:002024-03-25T02:55:23+08:00

    是否可以使用任何与标准输入重定向相关的技巧,而不是需要维护的 fifo?

    询问分配给新会话的唯一窗口的唯一窗格的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一般来说,从中获取信息非常有用。tmux new-session在你的情况下,你可以直接从;获取有关 tty 的信息。并且您不需要该tty变量。您无需执行任何预备步骤即可设置重定向,如下所示:

    {...} >"$(tmux new-session -d -s aux -P -F '#{pane_tty}' 'tail -f /dev/null')" || exit
    

    Notetail -f /dev/null只是一个保持 tmux 窗格“活动”的命令。该脚本不会尝试向该命令发送任何内容,而是打印到正确的 tty。这个答案没有解决标题(“将脚本的标准输出重定向为 tmux 会话中运行的另一个脚本/命令的标准输入”),但它为您提供了您想要的功能。

    • 2
  2. G-Man Says 'Reinstate Monica'
    2024-03-23T09:32:09+08:002024-03-23T09:32:09+08:00

    我不清楚你到底在问什么。您是否接受使用 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 的内容。

    PS 您应该引用 shell 变量,例如$fifo和 $tmpdir。您实际上不需要引用由非空白字符组成的常量字符串,例如"aux".

    • 1
  3. Stéphane Chazelas
    2024-03-23T20:01:34+08:002024-03-23T20:01:34+08:00

    我认为你不能做类似的事情,因为tmux会关闭它收到的所有高于 2 的 fd(以及分离时的 0、1、2)。

    请参阅(或等效)输出或源中的调用close_range(3, 4294967295, 0)中的等效项。straceclosefrom(STDERR_FILENO + 1)

    因此,您需要以其他方式传递数据,或者通过像您一样的命名管道或环境变量(但不能包含 NUL 字符)或嵌入由tmux套接字、临时文件、共享内存运行的 shell 代码中,其中没有一个真的会更简单或更可靠。

    但您的方法存在许多问题:

    • 您使用的是固定会话名称,这意味着脚本无法可靠地使用,除非您可以保证不会同时运行该脚本的两个调用。您可以tmux选择会话名称并通过选项检索-P它new-session。
    • 你不做任何同步:当你运行时capture-pane,不能保证它cat会完成甚至开始。当您检索窗格的内容时,您正在执行循环+终止,而不是告诉 tmux 会话退出。
    • $fifo您将在新会话中运行的 shell 代码中嵌入内容。最好作为环境变量传递。
    • 您没有检查mktemp或 的退出状态mkfifo。
    • tmux 将读取用户的数据~/.tmux.conf,这可能会干扰处理
    • 您需要传递TERM=tmux到环境tput(或 zsh 的内置echoti等效项),因为这是一个tmux最终解释的终端仿真器,而不是您运行脚本的主机终端,因此您需要向它发送转义序列,而不是主机终端无法理解。
    • 使用-S0 -E1,您仅捕获窗格的前 2 行可见行
    • 您可以告诉 tmux 创建一个与主机终端窗口大小相同的窗格
    • 您可能还想获取回滚缓冲区的内容,以防输出不适合一个屏幕。

    所以,也许是这样的:

    #! /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
    

    (注意所有 0x0a (LF) 字节,因为我的终端窗口有 60 行高)。

    (免责声明:我自己不是 tmux 用户,所以很可能有更聪明或更正确的方法来做到这一点)


    1 尽管就该功能而言home,它在实践中不太可能产生影响,因为您不太可能使用转义序列与自己home的仿真不同的终端 ( )。tmux\e[H

    • 1

相关问题

  • 列出没有其他后缀文件的文件

  • 什么情况下路径中最先找到的可执行文件不会被使用

  • 符号链接所有点文件和目录

  • 如何在`zsh`中增加一个动态命名的变量

  • 为什么我不能在 zsh 中定义一个名为 path 的只读变量?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve