0

I want to execute some scripts in install.sh, looks like:

#!/bin/bash

./script1.sh
./script2.sh
./script3.sh
...

It executes a bunch of scripts, so I want to distinguish stdout and stderr by color (green for stdout, red for stderr), and also where the outputs come from.

The output format I want is:

script1.sh: Hello                 # in green color (stdout)
script2.sh: Cannot read a file.   # in red color (stderr)

My goal is to print outputs in scripts in format of:

{script_name}: {green_if_stdout, red_if_stderr}

I don't want to edit every single command in all scripts.

Is there any way to override (or customize) all stdout and stderr outputs in the script?

#!/bin/bash

override_stdout_and_stderr

echo "Start"    # It also prints as green color

./script1.sh
./script2.sh
./script3.sh
...

restore_if_needed
osflw
  • 79
  • 1
  • 8

1 Answers1

0

You asked how to color all of stdout and stderr and prefix all lines with the script name.

In the answer below used redirection to send stdout to one process and stderr to another process. Credit to how to redirect stderr.

Using awk to prefix the incoming output with the needed color, red or green, then printing each line of input, and clearing the color setting upon finishing the print.

#!/bin/bash

function colorize()
{
  "$@" 2> >( awk '{ printf "'$1':""\033[0;31m" $0 "\033[0m\n"}' ) \
       1> >( awk '{ printf "'$1':""\033[0;32m" $0 "\033[0m\n"}' )
}

colorize ./script1.sh
#!/bin/sh
# script1.sh
echo "Hello GREEN"
>&2 echo "Hello RED"

Expect output similar to this command.

printf 'script1.sh:\033[0;32mHello GREEN\033[0m\nscript1.sh:\033[0;31mHello RED\033[0m\n'

Using read instead of awk:

#!/bin/bash

function greenchar()
{
  while read ln ; do
    printf "$1:\033[0;32m${ln}\033[0;0m\n" >&1
  done
}

function redchar()
{
  while read ln ; do
    printf "$1:\033[0;31m${ln}\033[0;0m\n" >&2
  done
}

function colorize()
{
  $* 2> >( redchar $1 ) 1> >( greenchar $1 )
}

colorize ./script2.sh
#!/bin/bash

# script2.sh

echo "Hello GREEN"
>&2 echo "Hello RED"

>&1 echo "YES OR NO?"
select yn in "Yes" "No"; do
  case $yn in
    Yes) echo "YOU PICKED YES" ; break;;
    No) echo "YOU PICKED NO" ; break;;
  esac
done

Example output, the output is similar to output of these commands.

RED="\033[0;31m"
GRN="\033[0;32m"
NC="\033[0;0m"
printf "./script1.sh:${GRN}Hello GREEN${NC}\n"
printf "./script1.sh:${GRN}YES OR NO?${NC}\n"
printf "./script1.sh:${RED}Hello RED${NC}\n"
printf "./script1.sh:${RED}1) Yes${NC}\n"
printf "./script1.sh:${RED}2) No${NC}\n"
printf "${NC}1${NC}\n"
printf "./script1.sh:${GRN}YOU PICKED YES${NC}\n"
atl
  • 575
  • 3
  • 6
  • Thanks for the handy command. I also want to add {script_name} in front of the output regardless of stdout or stderr. I edited the question and sorry for confusing question. – osflw Sep 26 '22 at 02:39
  • Yes you did! apologies was so excited about the coloring I forgot to check. – atl Sep 26 '22 at 02:46
  • I have a trouble with your idea. If the script prompts for my input such as y/n, it does not show output (either stdout or stderr) but just waits for my input. Can I solve this problem? – osflw Sep 27 '22 at 14:23
  • Having a look into it now, the issue I see is that awk is processing lines based on newlines and you are asking for character at a time processing. I have some ideas to try out. – atl Sep 28 '22 at 02:43
  • I didn't find a solution for the input issue using bash scripting – atl Sep 28 '22 at 03:52