【问题标题】:bash - redirect specific output from 2nd script back to stdin of 1st program?bash - 将第二个脚本的特定输出重定向回第一个程序的标准输入?
【发布时间】:2011-10-10 02:53:09
【问题描述】:

我有一个小程序,我们简单地称它为“程序”,它具有“正常”的行为。它从标准输入(通常由用户在键盘上输入)获取信息并通过标准输出/标准错误输出。我想自动化一个过程,因此将 stdout/stderr 重定向到“我的小 bash 脚本”(它也可能是 C/C++ 中的另一个程序)。它将它作为标准输入并对其进行过滤。这意味着忽略不重要的信息......并添加由 bash 脚本本身生成的更多信息。输出显示在屏幕上(由 echo 命令打印出来)。

到目前为止这是有效的:

program --verbose 2>&1 | ./mylittlebashscript.sh

方案:

 stdin     +---------------+              +---------------+
 --------->|               |--stdout--+-->|      my       |-->screen
           |    program    |          |   |    little     |
           |               |--stderr--|   |  bash script  |
           +---------------+              +---------------+

现在我想更进一步: 该程序需要来自用户的输入,我想通过我的小 bash 脚本自动提供这些输入。例如,它提示用户输入特定文件的路径。我的小 bash 脚本知道该路径,并且 bash 脚本知道程序何时等待输入(因为打印出来的最后一行包含“greped”的内容)。如何从我的 bash 脚本中返回 一些 信息?我不想通过管道返回所有的标准输出,因为只需要在屏幕上显示几个信息,程序不会喜欢这个输出。

新方案:

 (stdin?)  +---------------+              +---------------+   (stdout?)
 -------+->|               |--stdout--+-->|      my       |-->screen
        |  |    program    |          |   |    little     |
        |  |               |--stderr--+   |  bash script  |----+(maybe
        |  +---------------+              +---------------+    | stderr?)
        |                                                      |
        +------------------------------------------------------+

目前我对 Linux 还不是很熟悉。我想有可能使用 cat、fifos、tee 和管道/重定向。不幸的是,到目前为止我还没有实现它。

我真的很高兴有一个小例子! 非常感谢!

干杯 马蒂亚斯

PS:我认为这个线程是相关的:how to redirect stdout of 2nd process back to stdin of 1st process?

编辑: 好的,为了更进一步的解释,我从我的测试机器上拿了我的测试文件:

我将“程序”替换为另一个名为 input.sh 的批处理文件:

#!/bin/bash
echo "input.sh: give me input, waiting for input 1"
read x
echo $x
echo "input.sh: give me input, waiting for input 2"
read x
echo $x

我得到了第二个(“mylittlebashscript.sh”),现在称为 inter.sh 来处理:

#!/bin/bash
echo "inter.sh: start"
while read line ; do
  echo "inter.sh: line>$line"
  notfound=$(echo $line | grep "waiting")
  if [[ "$notfound" ]]; then
    echo "inter.sh: input sh seems to wait for input! putting something in the fifo"
    #echo "banana" > testfile
    #echo "I am the stderr" >&2
  fi

done
echo "inter.sh: end"
exit

【问题讨论】:

    标签: bash stdout pipe stdin stderr


    【解决方案1】:

    另一个类似expect 的软件工具是empty

    http://empty.sourceforge.net

    【讨论】:

    • 看起来很有趣。你用它吗?不幸的是,我找不到它的联机帮助页。我想知道 f、w 和 s 等命令行参数的用途。只输入“空”和“脚本”、“手动”什么的,很难在搜索引擎上找到好的结果。但是到目前为止,谢谢!
    • 好的,只要输入“empty”就可以打印出用法——这对我来说仍然很神秘。我试图为我的 input.sh bash 脚本编写自己的空脚本,但它失败了:empty: Data stream is empty. Keyphrase wasn't found. Exit on timeout.。我尝试过“等待”、“输入”和其他几件事。
    • 取得了一些进展。我不确定我是否忘记chmod +x emptyscript.sh.. 另一个问题是我似乎必须rm -f 文件fifo_in 和fifo_out。
    • 谢谢大家。我现在有一个带有empty 脚​​本的解决方案。虽然我不太确定到目前为止我是否得到了program 的所有输出......也许它需要更多地使用脚本。
    【解决方案2】:

    您是否尝试过,作为您链接的主题的答案:

    mkfifo fifo
    program --verbose < fifo 2>&1 | ./mylittlebashscript.sh | tee fifo
    

    ?

    也许,您应该让您的脚本在等待输入之前打印出一些文本,以避免陷入等待循环。..

    【讨论】:

    • 感谢您的提示。不幸的是我没有得到这个工作。我用我的两个测试文件编辑了我的帖子。我认为在您的示例中,我还将我回显的所有内容都返回到“程序”的标准输入(如果它正在工作)。但问题是......我想在屏幕上带来一些东西......还有一些东西回到“程序”的标准输入。也许我可以在标准输出中放一些东西,在标准错误中放一些东西?谢谢!
    • 我现在拥有的是:./input.sh &lt; fifo 2&amp;&gt;1 | ./inter.sh 2&gt;fifo 我想我越来越近了! :D
    • 好的,所以这对我也不起作用;仅在小的 .sh 示例中。似乎在程序打印出该行后立即读取fifo..并需要一些旧的(??)内容或空内容继续。或者在我的批处理文件中可能有一些称为程序写入标准错误?我也尝试过这样的事情:./input.sh &lt; fifo 2&amp;&gt;1 | ./inter.sh 2&gt;/dev/nullecho "foobar" &gt;&amp;fifo 在我的 shell 脚本中。这也不起作用..之后cat fifo 给了我正确的输出。顺便说一句,是否有手动刷新缓冲区的选项?不会想到这不是微不足道的......
    【解决方案3】:

    您可能还想为此类任务考虑客户端/服务器模型。

    见:BASH: Best architecture for reading from two input streams

    一般来说,如果input.sh 的标准输入不是终端(而是从fifo 重定向),您必须从控制终端设备/dev/tty 显式读取以启用/获取用户输入。

    read x < /dev/tty  # in input.sh
    
    ./input.sh < fifo 2>&1 | ./inter.sh 2>fifo
    

    【讨论】:

    • 好的,感谢您的提示。是否也有可能“程序”不是从标准输入而是直接从 /dev/tty 读取的?
    【解决方案4】:

    这听起来像是expect 的工作!使用expect 脚本,您可以从expect 脚本启动程序,该脚本充当包装器,侦听stdout 中的某些模式并将内容输入stdin 作为响应。例如,可以回答您的 input.sh 脚本的摘录:

    #!/usr/bin/expect -f
    
    spawn input.sh
    expect ".+input 1"
    send "something cool\r"
    expect ".+input 2"
    send "also cool\r"
    expect eof
    

    【讨论】:

    • 谢谢!这似乎是一个不错的解决方案。是否仍然可以过滤程序的输出?我猜您可以将另一个管道添加到另一个执行此操作的 bash 脚本中。问题是我使用的是 linux live CD (systemrescuecd.org),我真的不想添加安装程序。但我也在创建一个个性化磁盘,所以这可能是一个选项。至少它看起来是一个很棒的工具。
    • 我觉得我不够先进。我下载了 tcl 和 expect 的源代码,将它们解压缩到 /usr/local/src 并运行 .configure、make 和 make install。没有错误,但我没有让它运行。也许有一个非常简单的解决方案,无需额外软件的帮助(我现在更喜欢)。
    【解决方案5】:

    这是一个小的 empty sn-p 在 Bash 中编写一个简单的 telnet 会话。

    # http://empty.sourceforge.net
    cd empty-0.6.18b && man ./empty.1
    empty -h 
    empty -f -L >(tee empty.log) telnet
    empty -l
    
    empty -s <<EOF
    display
    status
    help
    quit
    EOF
    
    empty -k
    cat empty.log
    

    【讨论】:

      【解决方案6】:

      如果您的自动用户输入要求不太复杂,也可以使用以下方法。

      #!/bin/bash
      # input.sh
      echo "input.sh being busy ..."
      sleep 10
      echo "input.sh: give me input, waiting for input 1"
      read x #</dev/tty
      echo $x
      echo "input.sh: give me input, waiting for input 2"
      read x #</dev/tty
      echo $x
      echo "input.sh continuing ..."
      
      
      (
      echo a
      sleep 1
      echo b
      sleep 1
      exec 1>/dev/tty  # redirect anything that would go to stdout/pipe to the screen
      ls
      #./mylittlebashscript.sh
      #./inter.sh
      ) | ./input.sh   # do not read from /dev/tty in input.sh
      

      【讨论】:

        猜你喜欢
        • 2011-07-04
        • 1970-01-01
        • 2016-07-05
        • 1970-01-01
        • 1970-01-01
        • 2017-07-24
        • 1970-01-01
        • 1970-01-01
        • 2018-12-13
        相关资源
        最近更新 更多