cbashmacosunixterminal

Terminal background color not always properly reset using "\033[0m"


Trying to understand terminal behavior when it comes to reset background color on a Unix-like OS (Mac, Linux).

Consider a bash script

#!/usr/bin/env bash

printf "\033[46m"
printf "On Cyan\n"
printf "\033[0m"
printf "Back to Normal\n"

When I initially run this script, everything is as expected. However, if I repeat it for several times, the printing result changes. Following "Back to Normal" is a line on cyan background color.

The screenshot (Terminal, Mac OS Mojave):

enter image description here

Questions:

  1. Why is this? Can anyone explain this behavior?
  2. If I have changed background color and have printed out a line (ending with newline), what can I do to properly reset the background and to avoid this unwanted trailing background color?

For your information, I have tested this behavior on Mac OS Mojave Terminal, and on Ubuntu 18.04 Terminal. And I have tested using an equivalent Python 3 script. Results are consistent. I also tried using fflush(stdout) in C/C++ but in vain.

P.S. This question stems from a C++ program to be run on Mac or Linux. I thought it is irrelevant to the language itself, so I simplified it down to a bash script. If possible, please suggest a solution that can be done in C/C++.


Solution

  • Here’s your improved and clarified text with fixed grammar and typos:


    Your issue is caused by terminal scrolling.

    When your "On Cyan" text, which has a cyan background, prints a newline that causes the terminal to scroll, the newly inserted blank line inherits the last known background color—cyan.

    Then, when you reset the color attributes, the "Back to Normal" text is printed with the default background. However, any part of the line that wasn't explicitly overwritten remains cyan.

    To avoid this, you should reset the attributes before reaching the end of the line, like this:

    #!/usr/bin/env sh
    
    printf "\033[46m"  # Set cyan background
    printf "On Cyan"
    printf "\033[0m"   # Reset attributes before newline
    printf "\nBack to Normal\n"
    

    Alternatively, you can clear the rest of the line after resetting the text attributes using tput el or printf "\033[K":

    #!/usr/bin/env sh
    
    printf "\033[46m"    # Set cyan background (same as `tput setab 6`)
    printf "On Cyan\n"
    printf "\033[0m\033[K"  # Reset attributes and clear to end of line (same as `tput -S <<<$'sgr0\nel'`)
    printf "Back to Normal\n"
    

    This ensures that no residual background color remains on the blank space of the scrolled line.