捕获一行代码的错误流,并使用trap报告错误流,同时保持标准输出不变 很快再走一步完整可用版本

如何解决捕获一行代码的错误流,并使用trap报告错误流,同时保持标准输出不变 很快再走一步完整可用版本

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

该脚本调用一个R脚本,在该脚本中运行代码,这将根据发生的情况生成标准输出错误流。

我要实现的是照常在控制台上同时显示输出错误流,但是当脚本运行且失败时(例如RScript产生错误流),我想保存该错误消息R在sqlite数据库生成,但仍具有正常输出,并且退出时控制台上也会显示错误。我已经尝试了多种形式的Rscript函数输出重定向,但是我要么最终没有将任何东西保存到数据库中(除了行号),要么我可以保存错误消息,但是控制台上什么也不会放置... >

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

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)

我到处寻找一种方法来仅捕获错误流到变量并保持控制台上的输出不变(输出错误),但是我被困住了:)

Grtz, 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
,

很快

使用未命名的fifos (警告,因为OS会进行缓冲,所以这将起作用,因此仅当输出保持在64Kb以下时才可以使用!),这是一种微妙的方式:

exec {HOLDERR}<> <(:)
ls -ld /t{mp,nt} 2>&${HOLDERR}
read -t 0 -u $HOLDERR && read -ru $HOLDERR errmsg
exec {HOLDERR}<&-

这必须输出如下内容:

drwxrwxrwt 4 root root 4096 Jan 01 1970 /tmp

并使用以下内容填充$errmsgdeclare -p errmsg

declare -a errmsg=([0]="ls: cannot access '/tnt': No such file or directory")

再走一步

exec {HOLDERR}<> <(:)
ls -ld /t{mp,nt} 2>&${HOLDERR}
errmsg=()
while read -t 0 -u $HOLDERR;do
    read -ru $HOLDERR line
    errmsg+=("$line")
done
exec {HOLDERR}<&-
printf "%s\n" "${errmsg[@]}"

完整可用版本

使用trap SIGCHLD刷新fifo。

printmsg() {
    local out=()
    out=("${errmsg[@]}")
    errmsg=("${errmsg[@]:${#out[@]}}")
    [ "${#out[@]}" -gt 0 ] &&
    printf "Err: %s\n" "${out[@]}"
}
checkmsg() {
    local line
    while read -u $HOLDERR -t 0 ;do
    read -ru $HOLDERR line &&
        errmsg+=("$line")
    done
}
msg=()
trap checkmsg CHLD
exec {HOLDERR}<> <(:)

然后

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?