How To: Show Colour Numbers in Unix Terminal

256-terminal-colors-unix-linux.png
I’m decorating my tmux setup and needed to confirm colour numbers for some elements of the interface. Turns out, it’s simple enough to show all the possible colours with a 1-liner in your favourite Unix shell – bash shell in my case.

Using ESC sequences For Using Colours

I’ll explain how this works in full detail sometime in a separate post, but for now will just give you an example and show how it works:

hello-color-bash-output.png

So, in this example, this is how we achieve colorized text output:

  1. echo command uses -e option to support ESC sequences
  2. \e[38;5;75m is the ESC sequence specifying color number 75.
  3. \e[38;5; is just a special way of telling terminal that we want to use 256-color style

List 256 Terminal Colours with Bash

Here’s how we get the colours now: we create a loop from 1 until 255 (0 will be black) and then use the ESC syntax changing colour to $COLOR variable value. We then output the $COLOR value which will be a number:

for COLOR in {1..255}; do echo -en "\e[38;5;${COLOR}m${COLOR} "; done; echo;

Here’s how running this will look in a propertly configured 256-color terminal:

bash-show-256-colors.png

Bash Script to Show 256 Terminal Colours

Here’s the same 1-liner converted into proper script for better portability and readability:

#!/bin/bash

for COLOR in {1..255}; do
echo -en "\e[38;5;${COLOR}m"
echo -n "${COLOR} "
done

echo

If you save this as bash-256-colours.sh and chmod a+rx bash-256-colours.sh, you can now run it every time you want to refresh your memory or pick different colours for some use.

See Also




Unix Tutorial Digest – February 4th, 2019




bash 5.0

Screen Shot 2019-01-11 at 23.47.02.png
bash-5.0 on MacOS

Earlier this week we got a major upgrade to one of the most popular Unix shells in the world: BASH 5.0 (Bourne Again Sgell) was released on January 7, 2019.

Previous major release was bash 4.4, delivered in September 2016.

Unbelievable as it may sound, BASH was released in 1989, which makes it 30 years old!

Changes and Improvements in bash 5.0

Bugfixes

As expected over the period of 2+ years, lots of bug fixes were identified and resolved.

Readline 8.0

Readline is the library used by many projects, including bash, for advanced editing of the command lines. All these cool hotkeys for moving around the command line in bash (jumping words, editing/replacing characters) are provided by readline.

bash 5.0 shipped with readline 8.0 upgrade.

BASH_ARVG0 variable

You can now use this variable to confirm the name of the shell itself or the name of the script currently running:

greys@maverick:~ $ echo $BASH_ARGV0
/usr/local/Cellar/bash/5.0.0/bin/bash

EPOCHSECONDS variable

Very handy for timestamps, this variable returns the number of seconds since start of the Unix epoch.

EPOCHREALTIME

Another cool variable, EPOCHREALTIME reports Unix timestamps even more precisely: micro-second granularity is provided in addition to the Unix timestamp:

greys@maverick:~ $ echo $EPOCHREALTIME
1547250886.146766

For example, this simple one-liner can prove than sleeping for 1sec isn’t micro-second precise on my MacBook Pro. Notice how the micro-second part is slightly off every time:

greys@maverick:~ $ while true; do echo $EPOCHSECONDS; echo $EPOCHREALTIME; sleep 1; done
1547250913
1547250913.079728
1547250914
1547250914.097573
1547250915
1547250915.107237
1547250916
1547250916.118661
1547250917
1547250917.130726
^C

See also




Review Latest Logs with tail and awk

Part of managing any Unix system is keeping an eye on the vital log files.

Today I was discussing one of such scenarios with a friend and we arrived at a pretty cool example involving awk command and eventually a bash command substitution.

Let’s say we have a directory with a bunch of log files, all constantly updated at different times and intervals. Here’s how I may get the last 10 lines of the output from the most recent log file:

root@vps1:/var/log# cd /var/log
root@vps1:/var/log# ls -altr *log
-rw-r--r-- 1 root root 32224 Jul 10 22:49 faillog
-rw-r----- 1 syslog adm 0 Jul 25 06:25 kern.log
-rw-r--r-- 1 root root 0 Aug 1 06:25 alternatives.log
-rw-r--r-- 1 root root 2234 Aug 8 06:34 dpkg.log
-rw-rw-r-- 1 root utmp 294044 Aug 15 22:32 lastlog
-rw-r----- 1 syslog adm 12248 Aug 15 22:35 syslog
-rw-r----- 1 syslog adm 5160757 Aug 15 22:40 auth.log

Ok, now we just need to get that filename from the last line (auth.log).

Most obvious way would be to use tail command to extract the last line, and awk to show the 9th parameter in that line – which would be the filename:

root@vps1:/var/log# ls -altr *log | tail -1 | awk '{print $9}'
auth.log

Pretty cool, but can be optimised using awk’s END clause:

root@vps1:/var/log# ls -altr *log | awk 'END {print $9}'
auth.log

Alright. Now we wanted to show the 10 lines of output, which we can use tail -10 for.

A really basic approach is to assing the result of the line we’re using to a variable in Bash, and then access that variable, like this:

root@vps1:/var/log# FILE=`ls -altr *log | tail -1 | awk '{print $9}'`
root@vps1:/var/log# tail -10 ${FILE}
Aug 15 22:40:37 vps1 sshd[26578]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=159.65.145.196
Aug 15 22:40:39 vps1 sshd[26578]: Failed password for invalid user Fred from 159.65.145.196 port 47934 ssh2
Aug 15 22:40:39 vps1 sshd[26578]: Received disconnect from 159.65.145.196 port 47934:11: Normal Shutdown, Thank you for playing [preauth]
Aug 15 22:40:39 vps1 sshd[26578]: Disconnected from 159.65.145.196 port 47934 [preauth]
Aug 15 22:41:15 vps1 sshd[26580]: Connection closed by 51.15.4.190 port 44958 [preauth]
Aug 15 22:42:02 vps1 sshd[26585]: Connection closed by 13.232.227.143 port 40054 [preauth]
Aug 15 22:43:23 vps1 sshd[26587]: Connection closed by 51.15.4.190 port 52454 [preauth]
Aug 15 22:44:08 vps1 sshd[26589]: Connection closed by 13.232.227.143 port 47542 [preauth]
Aug 15 22:45:01 vps1 CRON[26604]: pam_unix(cron:session): session opened for user root by (uid=0)
Aug 15 22:45:01 vps1 CRON[26604]: pam_unix(cron:session): session closed for user root

But an ever shorter (better?) way to do this would be to use the command substitution in bash: the output of a command becomes the command itself (or string value in our case).

Check it out:

root@vps1:/var/log# tail -10 $(ls -altr *log | tail -1 | awk '{print $9}')
Aug 15 22:42:02 vps1 sshd[26585]: Connection closed by 13.232.227.143 port 40054 [preauth]
Aug 15 22:43:23 vps1 sshd[26587]: Connection closed by 51.15.4.190 port 52454 [preauth]
Aug 15 22:44:08 vps1 sshd[26589]: Connection closed by 13.232.227.143 port 47542 [preauth]
Aug 15 22:45:01 vps1 CRON[26604]: pam_unix(cron:session): session opened for user root by (uid=0)
Aug 15 22:45:01 vps1 CRON[26604]: pam_unix(cron:session): session closed for user root
Aug 15 22:45:26 vps1 sshd[26610]: Connection closed by 51.15.4.190 port 59872 [preauth]
Aug 15 22:46:15 vps1 sshd[26612]: Connection closed by 13.232.227.143 port 55030 [preauth]
Aug 15 22:46:23 vps1 sshd[26608]: Connection closed by 18.217.190.140 port 40804 [preauth]
Aug 15 22:47:28 vps1 sshd[26614]: Connection closed by 51.15.4.190 port 39044 [preauth]
Aug 15 22:48:20 vps1 sshd[26616]: Connection closed by 13.232.227.143 port 34286 [preauth]

So in this example $(ls -altr *log | tail -1 | awk ‘{print $9}’) is a substituion – bash executes the command in the parenthesis and then passes the resulting value to further processing (becoming a parameter for the tail -10 command).

In our command above, we’re essentially executing the following command right now:

root@vps1:/var/log# tail -10 auth.log

only auth.log is always the filename of the log file that was updated the latest, so it could become syslog or dpkg.log if they’re updated before next auth.log update.

See Also




Bash Scripts – Examples

I find it most useful when I approach any learning with a clear goal (or at least a specific enough task) to accomplish.

Here’s a list of simple Bash scripts that I think could be a useful learning exercise:

  • what’s your name? – asks for your name and then shows a greeting
  • hello, world! (that also shows hostname and list server IP addresses)
  • write a system info script – that shows you a hostname, disks usage, network interfaces and maybe system load
  • directory info – script that counts disks space taken up by a directory and shows number of files and number of directories in it
  • users info – show number of users on the system, their full names and home directories (all taken from /etc/passwd file)
  • list virtual hosts on your webserver – I actually have this as a login greeting on my webservers – small script that highlights which websites (domains) your server has in web server (Apache or Nginx) configuration.

Do you have any more examples of what you’d like to do in a Linux shell? If not, I’ll just start with the examples above. The plan is to replace each example name in the list above with a link to the Unix Tutorial post.