Bash 捕获一行代码的错误流,并使用trap报告它,同时保持标准输出不变

Bash 捕获一行代码的错误流,并使用trap报告它,同时保持标准输出不变,bash,stderr,bash-trap,output-redirect,Bash,Stderr,Bash Trap,Output Redirect,我在下面的2个shell脚本中尝试了以下(简化)代码 该脚本调用运行代码的R脚本,该脚本将根据发生的情况生成标准输出和错误流 我试图实现的是像往常一样在控制台上显示输出和错误流,但是当脚本运行并且失败时(例如,RScript生成错误流)我想保存R在sqlite数据库中生成的错误消息,但当它退出时,仍然会在控制台上显示正常的输出和错误。我已经尝试过多种形式的重定向Rscript函数的输出,但我要么最终不将任何内容保存到数据库(除了行号),要么可以保存错误消息,但控制台上不会显示任何内容 这不会将错

我在下面的2个shell脚本中尝试了以下(简化)代码

该脚本调用运行代码的R脚本,该脚本将根据发生的情况生成标准输出和错误流

我试图实现的是像往常一样在控制台上显示输出和错误流,但是当脚本运行并且失败时(例如,RScript生成错误流)我想保存R在sqlite数据库中生成的错误消息,但当它退出时,仍然会在控制台上显示正常的输出和错误。我已经尝试过多种形式的重定向Rscript函数的输出,但我要么最终不将任何内容保存到数据库(除了行号),要么可以保存错误消息,但控制台上不会显示任何内容

这不会将错误消息保存到DB(行号将为),但所有内容都将在控制台上

updateDBwhenError() {
    sqlite3 "myDB.db" "INSERT INTO logs VALUES('$1')"   
}

err_report() {
    #Tryign to capture both line error and message
    updateDBwhenError "Error Line $1 $2"
    exit
}
trap 'err_report ${LINENO}' ERR

Rscript testScript.R

这将把错误消息保存到数据库中,但控制台上不再有任何内容

updateDBwhenError() {
    sqlite3 "myDB.db" "INSERT INTO logs VALUES('$1')"   
}

err_report() {
    #Tryign to capture both line error and message
    updateDBwhenError "Error Line $1 $rErr"
    exit
}
trap 'err_report ${LINENO}' ERR

rErr=$(Rscript testScript.R 2>&1)

我到处寻找一种方法,只捕获变量的错误流,并在控制台上保持输出不变(包括输出和错误),但我被卡住了:)

格尔茨, PJ

试试这个

exec 5>&1
exec 6>&1
rErr=$(Rscript testScript.R 2>&1 1>&6 | tee /dev/fd/5)
测试脚本

$ cat test
#!/bin/bash
ls
ls sdfgds
使用此脚本进行测试

$ exec 5>&1
$ exec 6>&1
$ err=$(./test 2>&1 1>&6 | tee /dev/fd/5)
file  new_file  test  xml
ls: cannot access 'sdfgds': No such file or directory

$ echo "$err"
ls: cannot access 'sdfgds': No such file or directory
不久 使用未命名的FIFO(警告,这将起作用,因为操作系统进行缓冲,所以只有当输出保持在64Kb以下!),有一种微妙的方式:

并使用类似于:
declare-p errmsg

declare -a errmsg=([0]="ls: cannot access '/tnt': No such file or directory")
更进一步 然后

必须输出如下内容:

drwxrwxrwt 4 root root 4096 Jan 01 1970 /tmp
drwxrwxrwt 4 root root 4096 Jan 01 1970 /tmp
其次是:

printmsg
将显示

Err: ls: cannot access '/tnt': No such file or directory

exec{HOLDERR}@KamilCuk你说得对!答案已编辑!但当然,这可能会阻塞,但不适用于raisonable
STDERR
output(小于64k;)。您好。谢谢你的回复!我会研究这一点,但我承认这远远超出了我目前的理解,所以我必须努力研究它,看看我是否能够实现和工作:)我以为我只是错过了一些简单的东西,但似乎如果我真的想实现这一点,我将需要更多复杂的代码。。。我会一直向您发帖的。您希望继续像下面这样测试控制台的输出
exec 5>&1;err=$(ls sadfasf 2>&1>&5)
控制台上无任何内容,仅在varHi中。我同意@Ivan的观点,这一个不起作用。请记住,我只想从var中的RScript捕获错误流,但是在控制台上有错误和输出,您是对的
tee
是复制流所必需的。更新了我的答案这没有回答问题。@Barmar你能不能重新打开这个问题,因为有针对性的答案没有回答它
ls -ld /t{mp,nt} 2>&${HOLDERR}
drwxrwxrwt 4 root root 4096 Jan 01 1970 /tmp
printmsg
Err: ls: cannot access '/tnt': No such file or directory