Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm altering scripts at work that monitor log files to single out certain items and colorize them. The final output is a list of 6-digit numbers in several columns. I've been able to add a ~ to the start of the number, and it doesn't break anything in the final output, but it's rather ugly and hard to read. However, when I try to colorize the number, either in preceding bash scripts or the final processing of the data in a perl script, the color text gets clobbered.

For example, the original number, which I will put into $num:

123456

I input this in perl (or, much the same thing in bash):

"\e[1;34m" . $num . "\e[0m"

And here's what I get:

[1;34m123456[0m 

I've also tried this, an escaped version, but get the same thing:

"\x1B[1;34m" . $num . "\x1B[0m"

If this makes a difference, here's the real stack of scripts (it's a mess):

  • Perl called inside shell script, which then pipes to grep/cut/etc.
  • shell script with more cut/etc., then pipes to .pl
  • shell script watches that output

Maybe watch doesn't like color then?

I don't know perl too well, so I guess it wouldn't hurt to show what I'm seeing around the print lines:

my $format = ("%-8s") x scalar(@{$a[0]});

printf("$format\n", @$_)
share|improve this question
add comment

3 Answers

up vote 5 down vote accepted

I encountered the 'color-stealing' issues with watch, it's because watch uses a simple /bin/sh output style, which clobbers any color, aliases, shortcuts... the whole shebang!

So I cobbled this together, placed in my .bashrc, allows me to use all my own aliases, shortcuts and whatnot:

Usage:
    watcher 20 'somecommand | apipe | grep'

The number is the delay between updates, in seconds, the command can include anything you can quote.

###### 'watch' workalike, lets me use my aliases and such
function watcher() { WATCHERTIME=$1 ; WATCHERFILE=/tmp/watcher$$ ; shift ; while true ; do WATCHERHEIGHT=$(($LINES - 5)) ; ( eval $* ) | tail -n ${WATCHERHEIGHT} > ${WATCHERFILE} 2>/dev/null; clear ; /bin/echo -n "Every ${WATCHERTIME} seconds - " ; date ; /bin/echo ; cat ${WATCHERFILE} ; \rm -f ${WATCHERFILE} ; /bin/echo ; /bin/echo "==" ; sleep ${WATCHERTIME} ; done ; }

To break it down:

function watcher()
{ 
  WATCHERTIME=$1
  WATCHERFILE=/tmp/watcher$$
  shift
  while true; do
    WATCHERHEIGHT=$(($LINES - 5))
    ( eval $* ) | tail -n ${WATCHERHEIGHT} > ${WATCHERFILE} 2>/dev/null
    clear
    /bin/echo -n "Every ${WATCHERTIME} seconds - "
    date
    /bin/echo
    cat ${WATCHERFILE}
    \rm -f ${WATCHERFILE}
    /bin/echo
    /bin/echo "=="
    sleep ${WATCHERTIME}
  done
}

It determines the current screen height in lines, subtracts out enough for its own output, then repeatedly executes the command given, then clears the screen, displays the output and waits for the next loop. It displays a short '==' at the bottom to signify that's where the output ended. Sometime's it's helpful to know this.

I did it this way so there was smallest possible delay when displaying. if you don't capture output and then display, you get a long pause, then the output... icky.

Since it doesn't clobber colors, you get everything you're used to getting. Enjoy!

share|improve this answer
    
I played around with this and made it work just how I wanted. I ended up changing tail to head and changed this line as follows: WATCHERHEIGHT=$(($(tput lines) - 3)) This will auto-scale the lines to what the current terminal shows. Still, you brought me most of the way there. Thanks a ton! –  Ken Oh Jul 18 '12 at 23:58
    
glad it works for you, the tail/head always depends on what you're viewing, and the $LINES should do the same as the tput lines... but as long as it works. You're welcome! –  lornix Jul 19 '12 at 0:49
add comment

The problem is that watch uses Curses and the curses string output functions work on a virtual framebuffer with separate planes for characters and their attributes/colours. Strings are sent to the framebuffer as-is, with no terminal directive interpretation. To safeguard against clobbering of the terminal state, Curses ignores ESC (among other things), so watch won't do colour by default.

You can fix that by following the sage advice of either jw013 or lornix: either use watch --color or wrap your script in something like a while true; do clear; $SCRIPT; sleep 2; done loop.

share|improve this answer
add comment

You probably need the --color option to watch.

share|improve this answer
1  
D'oh...it looks like --color isn't in RHEL 4's watch. –  Ken Oh Jun 29 '12 at 23:37
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.