【问题标题】:Redirect copy of stdin to file from within bash script itself将标准输入的副本从 bash 脚本本身重定向到文件
【发布时间】:2020-06-09 21:00:07
【问题描述】:

参考https://stackoverflow.com/a/11886837/1996022(也无耻地偷了标题),问题是如何捕获脚本的输出,我想知道如何另外捕获脚本输入。主要是因为脚本也有用户输入产生完整的日志。

我尝试过类似

exec 3< <(tee -ia foo.log <&3)
exec <&3 <(tee -ia foo.log <&3)

但似乎没有任何效果。我可能只是错过了一些东西。

【问题讨论】:

    标签: bash shell logging io-redirection


    【解决方案1】:

    也许使用script 命令会更容易?您可以让您的用户直接使用script 运行脚本,或者做一些类似这样的时髦操作:

    #!/bin/bash
    
    main() {
        read -r -p "Input string: "
        echo "User input: $REPLY"
    }
    
    if [ "$1" = "--log" ]; then
        # If the first argument is "--log", shift the arg
        # out and run main
        shift
        main "$@"
    else
        # If run without log, re-run this script within a
        # script command so all script I/O is logged
        script -q -c "$0 --log $*" test.log
    fi
    

    很遗憾,您不能将函数传递给script -c,这就是为什么在此方法中需要双重调用。

    如果有两个脚本是可以接受的,您还可以有一个面向用户的脚本,它只使用script 调用非面向用户的脚本:

    script_for_users.sh
    --------------------
    #!/bin/sh
    script -q -c "/path/to/real_script.sh" <log path>
    
    real_script.sh
    ---------------
    #!/bin/sh
    <Normal business logic>
    

    【讨论】:

    • 这是一个非常好的解决方案!我很震惊,我以前从未见过这个。
    • 顺便说一句,它应该是 script -q -c "$0 --log${@@Q}" test.log 以便正确转义。
    • ${@@Q} 使用 bash v4.2 对我来说语法错误...一般来说,因为我们在双引号字符串中扩展参数,所以使用 $* 来避免拆分字段。见github.com/koalaman/shellcheck/wiki/SC2145
    • 是的,它需要一个相对较新的 bash 版本。它适用于 bash 5.0.3。它应该是script -qec "$0 --log ${*@Q}" test.log; exit $?。最后,$* 如果您有包含空格的参数,则会中断。 "${*@Q}" 正确地逃脱了它们。
    【解决方案2】:

    更简单:

    #! /bin/bash
    tee ~/log | your_script
    

    奇妙的是your_script可以是函数、命令或{}命令块!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 2020-03-22
      • 1970-01-01
      相关资源
      最近更新 更多