捕获函数中的所有命令

捕获函数中的所有命令

我正在使用一组脚本,其函数被视为只读。这些函数不仅仅是命令列表,例如,可以有循环和更改目录,甚至调用其他函数:

func() {
    cd folder/
    run command1
    mkdir folder2/ ; cd folder2/
    run command2
}

暂时假装我可以更改脚本,以便向您展示我想要的内容,如下所示:

func() {
    cd folder/
    string[0]="command1" ; run command1 |& tee out0.log ; result[0]="$?" ; finished_command_number 0
    mkdir folder2/ ; cd folder2/
    string[1]="command2" ; run command2 |& tee out1.log ; result[1]="$?" ; finished_command_number 1
}

因此,对于可以通过管道传输但不能用于cd或循环的命令,我想存储一个字符串,存储标准输出(stderr),存储退出代码,然后运行另一个命令。但是,我无法添加这一点,它必须在我的脚本中完成,该脚本使用 func() 调用脚本。

为了单独获得后命令调用功能,我尝试复制该函数并使用 a 从我的脚本运行它trap foo debug,但这似乎没有传播到函数中。我认为逐行复制行不通,因为cdloops不能真正隔离,因为它们是控制语句而不是子shell命令。

如果字符串只是命令本身的函数,那仍然很有用。

答案1

#!/bin/bash
# test.sh
post() {
        echo "post [$BASH_COMMAND] [$?]"
        echo "== $RANDOM =="
}
set -o functrace
trap post debug
func() {
        . check.sh
        tryme |& tee out.txt
}
func

输出可以通过随机标记的行进行过滤。我应该进一步测试它,看看它在多个进程中的工作情况如何,但它似乎在短期命令中工作得很好。请注意,退出代码滞后于一个命令,因为显然首先调用了 debug。

#!/bin/bash
# check.sh
tryme() {
        echo "one"
        echo "two"
        mkdir -p hello
        cd hello/
        echo "three"
        false
        echo "four"
}

===

$ bash test.sh 
post [func] [0]
== 22542 ==
post [func] [0]
== 10758 ==
post [. check.sh] [0]
== 9115 ==
post [tryme 2>&1] [0]
== 11979 ==
post [tee out.txt] [0]
== 17814 ==
post [tryme 2>&1] [0]
== 22838 ==
post [echo "one"] [0]
== 5251 ==
one
post [echo "two"] [0]
== 18036 ==
two
post [mkdir -p hello] [0]
== 4247 ==
post [cd hello/] [0]
== 21611 ==
post [echo "three"] [0]
== 24685 ==
three
post [false] [0]
== 8557 ==
post [echo "four"] [1]
== 7565 ==
four

答案2

如果我正确地阅读你的问题,那么你正在寻找一种方法:

  • 独立于函数调用的输出捕获 stdout 和 stderr
  • 保留当前工作目录,防止在函数执行过程中对其进行任何更改

这可以相当简单地完成:

#!/bin/bash
stdout=/path/to/output.std
stderr=/path/to/output.err

somefunc() {
    : Do things
}

( somefunc arg1 arg2 ) >> $stdout 2>> $stderr

在子 shell 中运行该函数将允许它执行所需的任何操作,包括更改工作目录以及正常输出到 stdout 和 stderr。当子 shell 退出时,脚本的工作目录不变,所有 stdout 和 stderr 输出都会被捕获并重定向到日志文件中。

添加一个(全局或其他)数组来捕获命令的退出代码很简单:

declare -a exitcodes
( exit 0 )
exitcodes+=( $? )
( exit 2 )
exitcodes+=( $? )
( exit 0 )
exitcodes+=( $? )

echo ${exitcodes[@]}

相关内容