如何使用 [error] 头重定向标准错误?

huangapple go评论76阅读模式
英文:

How can I redirect standard error with [error] head?

问题

我知道如何将标准错误输出到shell中的日志文件。

BACKUP_DIR="/home/backup/"
BACKUP_LOG="/home/backup.log"
echo "backup start" >> $BACKUP_LOG 2>&1
mkdir $BACKUP_DIR >> $BACKUP_LOG 2>&1

mkdir命令失败时,我会收到消息:no such file or directory

是否有办法将错误消息更改为类似 [error] no such file or directory 的形式?

我想在错误消息前面添加文本 [error]

英文:

I understand how to output standard error to a log file in shell.

BACKUP_DIR="/home/backup/"
BACKUP_LOG="/home/backup.log"
echo "backup start" >>$BACKUP_LOG 2>&1
mkdir $BACKUP_DIR >>$BACKUP_LOG 2>&1

When mkdir command fails, i get the message: no such file or directory

Is there a way to change the error message to something like: [error] no such file or directory?

I want to prepend the text[error] to the front of the error message.

答案1

得分: 2

以下是翻译好的内容:

这里有一些尝试的内容:

    mkdir $BACKUP_DIR 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG)

改编自:https://serverfault.com/a/502019/506625。

使用以下命令进行测试:

    BACKUP_DIR="a/b/c"
    BACKUP_LOG="junk.log"

    mkdir $BACKUP_DIR 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG)

并且 junk.log 显示:

    [error] mkdir: 无法创建目录 'a/b/c':没有那个文件或目录

-----

也适用于命令组合(也许我没有理解注释):

    TESTFILE1="test1.txt" ; TESTFILE2="test2.txt" ;
    echo "Test1" >$TESTFILE1

    # 确保第二个文件不存在并删除测试日志
    rm -f $TESTFILE2 ; rm -f $BACKUP_LOG

    # 命令组合;第一个命令正常;第二个命令出错
    { cat $TESTFILE1 ; cat $TESTFILE2 ; } 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG);

和输出:

$ { cat $TESTFILE1 ; cat $TESTFILE2 ; } 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG);
Test1

$ cat junk.log
[error] cat: test2.txt: 没有那个文件或目录
英文:

Here's something to try:

mkdir $BACKUP_DIR 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG)

Adapted from: https://serverfault.com/a/502019/506625.

Tested using

BACKUP_DIR="a/b/c"
BACKUP_LOG="junk.log"

mkdir $BACKUP_DIR 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG)

and junk.log shows

[error] mkdir: cannot create directory ‘a/b/c’: No such file or directory

Also works with command grouping (I'm probably not understanding comment though):

TESTFILE1="test1.txt" ; TESTFILE2="test2.txt" ;
echo "Test1" >$TESTFILE1

# make sure 2nd file doesn't exist and remove test log
rm -f $TESTFILE2 ; rm -f $BACKUP_LOG

# Command grouping ; 1st command OK ; 2nd command error
{ cat $TESTFILE1 ; cat $TESTFILE2 ; } 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG);

and output

$ { cat $TESTFILE1 ; cat $TESTFILE2 ; } 2> >(sed $'s,.*,[error] &,'>>$BACKUP_LOG);
Test1

$ cat junk.log
[error] cat: test2.txt: No such file or directory

答案2

得分: 0

文件重定向在Shell中的语法非常灵活,但也许有点晦涩。要在标准输出和标准错误流中添加头部,可以执行以下操作:

{ { cmd | sed -e 's/^[stdout] /' >&3; } 2>&1 | sed -e 's/^[stderr] /' >&2; } 3>&1

这将在每行标准输出前添加 "[stdout] ",并在每行标准错误前添加 "[stderr] "。要重定向到文件,需要确保按照正确的顺序进行重定向。例如:

{ { cmd | sed -e 's/^[stdout] /' >&3; } 2>&1 | sed -e 's/^[stderr] /' >&2; } >"$BACKUP_OUT" 2>"$BACKUP_ERR" 3>&1

执行多个命令的最简单方式可能是将它们定义在名为 cmd 的函数中,然后继续使用上述相同的语法。当然,您还可以添加换行符和空格以使其更可读,或使用一些函数进行重构。例如:

#!/bin/sh

BACKUP_DIR="$HOME/backup/"
BACKUP_OUT="$BACKUP_DIR/out"
BACKUP_ERR="$BACKUP_DIR/err"

cmd() {
        echo do one thing well
        echo do this poorly >&5
        echo three
}

{ {
        cmd \
        | sed -e 's/^[stdout] /' >&3; } 2>&1 |
        sed -e 's/^[stderr] /' >&2; } >"$BACKUP_OUT" 2>"$BACKUP_ERR" 3>&1

这种新潮的进程替代语法确实更清晰,但在许多Shell中无法工作(例如,它是一种 "bashism")。

英文:

File redirection syntax in the shell is flexible, but perhaps a bit obscure. To add headers to both stdout and stderr streams, you can do things like:

{ { cmd | sed -e 's/^/[stdout] /' >&3; } 2>&1 | sed -e 's/^/[stderr] /' >&2; } 3>&1

That will add "[stdout] " to the beginning of each line of stdout, and "[stderr] " to the beginning of each line of stderr. To redirect to files, you need to make sure you do the redirections in the correct order. For example:

{ { cmd | sed -e 's/^/[stdout] /' >&3; } 2>&1 | sed -e 's/^/[stderr] /' >&2; } >"$BACKUP_OUT" 2>"$BACKUP_ERR" 3>&1

The easiest way to do multiple commands is probably to simply define them in a function named cmd and continue using exactly the same syntax as above. Of course, you can also add newlines and whitespace to make this more readable, or refactor with some functions. eg:

#!/bin/sh

BACKUP_DIR="$HOME/backup/"
BACKUP_OUT="$BACKUP_DIR/out"
BACKUP_ERR="$BACKUP_DIR/err"

cmd() {
        echo do one thing well
        echo do this poorly >&5
        echo three
}

{ {
        cmd \
        | sed -e 's/^/[stdout] /' >&3; } 2>&1 |
        sed -e 's/^/[stderr] /' >&2; } >"$BACKUP_OUT" 2>"$BACKUP_ERR" 3>&1

The new-fangled process substitution is certainly cleaner syntax, but will not work in many shells (eg, it is a "bashism").

huangapple
  • 本文由 发表于 2023年3月7日 09:58:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75657410.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定