January 22, 2008

CLI Magic: Use ANSI escape sequences to display a clock in your terminal

Author: Sergio Gonzalez Duran

When I'm in a Linux terminal, I often find myself typing date just to see the time. To make life a bit easier, I wrote a script to always display a clock in the top right corner of the screen.

The script saves the current cursor position with an ANSI escape sequence instruction. Then, using the tput command, the cursor is sent to row 0 (the top of the screen) and the last column minus 19 characters (19 is the length of HH:MM:SS YYYY-MM-DD). The formatted date command is displayed in green inverted color. The cursor is then sent back to its original position with another ANSI sequence that restores the original saved position.

If you're in an X Window System terminal, you can resize the window, and the clock will adjust its position because it is displayed at the last column minus 19 characters. The ANSI escape sequences don't work in all terminal emulators, but they do fine in xterm. Here's the script:

# clock.sh

# the script is executed inside a while without conditions
while :
# time and date are formatted to show HH:MM:SS YYYY-MM-DD
cmd=`date +"%H:%M:%S %F"`

# cursor's current position is saved through an escape sequence
echo -n -e "\033[s"

# Uncomment the next two lines to clean up the whole first line, although it causes a lot of blinking
#tput cup 0 0 # positions on row 0 col 0 (left top corner)
#tput el # cleans from position to end of line

# to place the clock on the appropriate column, subtract the length of 'HH:MM:SS YYYY-MM-DD', which is 19,
# from the total number of columns
C=$((`tput cols` - 19))
tput cup 0 $C # positions cursor at row 0 col $C

# clock will be shown green inverted
# setaf 2 = green, smso = inverted
COLOR=`tput setaf 2; tput smso`

# back to normal screen colors
NORMAL=`tput sgr0`

# print the time-date output on the above position
echo -n $COLOR$cmd$NORMAL

# restore the cursor to whatever was its previous position
echo -n -e "\033[u"

# script is executed every second
sleep 1

Save the script as clock.sh, chmod to 755, and run it with ./clock.sh&. The time and date should now appear at the top right of your screen.

When you run clock.sh, the terminal will return the job number and process identifier (PID) of the clock.sh process. You can end the execution of the script by using the kill command and specifying the job number.

With this script, you can display not only a clock, but other useful information as well. For example, suppose you want to monitor your CPU's load average from the uptime command:

09:19:56 up 1 day, 1:54, 4 users, load average: 0.29, 0.39, 0.42

The last three values are the average load for the last one, five, and 15 minutes. You can extract these values with a gawk command:

uptime | gawk '{print $(NF - 2), $(NF - 1), $NF}'
0.72, 0.54, 0.47

NF is the total number of fields in the output, and $NF is the value of the last field. In clock.sh, change this line:

cmd=`date +"%H:%M:%S %F"`

to this:

cmd=`uptime | gawk '{print $(NF - 2), $(NF - 1), $NF}'`

or this, to leave the time and date:

cmd=`date +"%H:%M:%S %F" ; uptime | gawk '{print $(NF - 2), $(NF - 1), $NF}'`

Since the length of the string is no longer 19, let the wc command help you determine the display offset. Change this line:

C=$((`tput cols` - 19))

to this:

C=$((`tput cols` - (`echo $cmd | wc -c` - 1) ))

The length of the output is calculated with wc -c (the -c option tells wc to count the number of characters in the string being piped to it). -1 subtracts the \r at the end of the $cmd output.

You could also display the total size or available space of a growing partition with df, the number of users online with uptime or w, or the number of processes with ps. Samba, Apache, and many other servers have status commands where you can extract pieces of information to show this way. Use your imagination to create your own modified version of clock.sh.


  • Tools & Utilities
Click Here!