【问题标题】:Redirect to a script that uses /dev/tty重定向到使用 /dev/tty 的脚本
【发布时间】:2020-05-30 06:52:56
【问题描述】:

我正在编写一个可能需要人工输入的 git 钩子。根据this answer,必须在该脚本中使用exec < /dev/tty。这完成了工作,但现在不可能将标准输出重定向到该钩子(用于测试目的)。我想这个问题可以归结为一个问题:如何向/dev/tty 发送消息以使另一个进程可以读取它?不确定这是否可能。

这是最小的可重现示例:

# file: target.sh

exec < /dev/tty # we want to use /dev/tty
read -p  "Type a message: " message
echo "The message ${message}"

我尝试了几种这样的解决方案:

echo -e "foo\n"| tee /dev/tty | source target.sh

它实际上在read 提示符之后在控制台中打印消息,但message 变量仍未设置。有什么办法可以解决吗?

【问题讨论】:

    标签: bash stdout tty


    【解决方案1】:

    你可以使用expect来达到效果:

    #!/bin/bash
    
    expect << EOF
    spawn bash target.sh
    expect {
        "Type a message: " {send "foo\r"; interact}
    }
    EOF
    

    【讨论】:

    • 哇,谢谢,这就是我正在寻找的解决方案。它实际上与我即将编写的测试用例配合得很好
    【解决方案2】:

    您可以将输入文件设为可选参数:

    #!/bin/bash
    
    input_file=${1:-/dev/tty}
    read -p  "Type a message: " message < "${input_file}"
    echo "The message ${message}"
    
    # other stuff ...
    

    现在像这样测试命令:

    your_script
    your_script <(echo foo)
    some_cmd | your_script
    some_cmd | your_script <(echo foo)
    

    PS:我使用的语法&lt;(echo foo) 是所谓的process substitution

    【讨论】:

    • 感谢您的及时回复,我喜欢您的方法,但我无法将其标记为已接受。我打算在 git 钩子中使用它,将没有传递输入文件参数的选项。我很好奇是否有办法解决这个/dev/tty 问题。无论如何,您的解决方案看起来是编写自定义脚本的好习惯,谢谢
    • 输入文件参数默认为/dev/tty,这就是重点。在 git-hook 中,您只是不传递文件名(检查示例)。如果您愿意,请使用 expect ,但这在 imo 中要复杂得多,而且它要求用户已经安装了 expect
    • 对不起,这是我的错,我不够清楚。我假设端到端测试。例如echo -e "some information\n" | git commit -m "message" 之类的东西(这不是一个工作示例,只是为了说明我的观点)。在这种情况下,git 隐藏了参数,我不确定是否可以覆盖。是的,用户可能没有安装expect,但他们不应该安装。在 CI 环境中拥有它就足够了。但是您实际上给了我另一个提示:D,我可以将钩子作为常规脚本单独测试,无需任何 git 调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    相关资源
    最近更新 更多