Is it possible to make stdout and stderr output be of different colors in XTerm or Konsole?

前端 未结 7 621
抹茶落季
抹茶落季 2021-01-30 17:16

Is it even achievable?

I would like the output from a command’s stderr to be rendered in a different color than stdout (for example, in red).

I ne

相关标签:
7条回答
  • 2021-01-30 17:32

    I can't see that there is any way for the terminal emulator to do this.

    The interface between the terminal emulator and the shell/app is via a pseudo-tty, where the terminal emulator is on the master side and the shell/app on the other. The shell/app have both stdout and stderr connected to the same pty, so when the terminal emulator reads from the pty for the shell/app output it can no longer tell which was written to stdout and which to stderr.

    You will have to use one of the solutions that intercepts the data between the application and the slave-pty and inserts escape codes to control the terminal output colo(u)r.

    0 讨论(0)
  • 2021-01-30 17:42

    Here is a little Awk script that will print everything you pass it in red.

    #!/usr/bin/awk -f
    { printf("%c[%dm%s%c[0m\n", 0x1B, 31, $0, 0x1B); fflush() }
    

    It simply prints each line it receives on stdin within the necessary escape codes to display it in red. It is followed by an escape code to reset the terminal.

    (If you need a different color, change the second argument in the above printf call from 31 to the number corresponding to the desired color.)

    Save it to colr.awk, do a chmod a+x, and use it like so:

    $ my_program | ./colr.awk
    

    It has the drawback that lines may not be displayed in order, because stderr goes directly to the console, while stdout is piped through an additional process.

    0 讨论(0)
  • 2021-01-30 17:42

    A simple solution to color stdout in red is to pipe it through grep:

    program | grep .
    

    This should not require installing anything, as grep should be already installed everywhere.

    Taken from Dennis’s comment on superuser.com.

    0 讨论(0)
  • 2021-01-30 17:46

    You can also check out stderred: https://github.com/sickill/stderred

    0 讨论(0)
  • 2021-01-30 17:48

    I think you should use the standard escape sequences on stderr. Have a look at this.

    0 讨论(0)
  • 2021-01-30 17:50

    Here's a solution that combines some of the good ideas already presented.

    Create a function in a bash script:

    color() ( set -o pipefail; "$@" 2>&1>&3 | sed $'s,.*,\e[31m&\e[m,' >&2 ) 3>&1
    

    Use it like this:

    $ color command -program -args
    

    It will show the command's stderr in red.

    Keep reading for an explanation of how it works. There are some interesting features demonstrated by this command.

    • color()... — Creates a bash function called color.
    • set -o pipefail — This is a shell option that preserves the error return code of a command whose output is piped into another command. This is done in a subshell, which is created by the parentheses, so as not to change the pipefail option in the outer shell.
    • "$@" — Executes the arguments to the function as a new command. "$@" is equivalent to "$1" "$2" ...
    • 2>&1 — Redirects the stderr of the command to stdout so that it becomes sed's stdin.
    • >&3 — Shorthand for 1>&3, this redirects stdout to a new temporary file descriptor 3. 3 gets routed back into stdout later.
    • sed ... — Because of the redirects above, sed's stdin is the stderr of the executed command. Its function is to surround each line with color codes.
    • $'...' A bash construct that causes it to understand backslash-escaped characters
    • .* — Matches the entire line.
    • \e[31m — The ANSI escape sequence that causes the following characters to be red
    • & — The sed replace character that expands to the entire matched string (the entire line in this case).
    • \e[m — The ANSI escape sequence that resets the color.
    • >&2 — Shorthand for 1>&2, this redirects sed's stdout to stderr.
    • 3>&1 — Redirects the temporary file descriptor 3 back into stdout.

    Here's an extension of the same concept that also makes STDOUT green:

    function stdred() (
        set -o pipefail;
        (
            "$@" 2>&1>&3 |
            sed $'s,.*,\e[31m&\e[m,' >&2
        ) 3>&1 |
        sed $'s,.*,\e[32m&\e[m,'
    )
    
    0 讨论(0)
提交回复
热议问题