我正在使用一组脚本,其函数被视为只读。这些函数不仅仅是命令列表,例如,可以有循环和更改目录,甚至调用其他函数:
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
,但这似乎没有传播到函数中。我认为逐行复制行不通,因为cd
和loops
不能真正隔离,因为它们是控制语句而不是子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[@]}