DEV Community

loading...
Cover image for Towards a better message of the day

Towards a better message of the day

Ben Sinclair
I've been a professional C, Perl, PHP and Python developer. I'm an ex-sysadmin. Back in the day, I had a geekcode which I'm not going to share with you. 418 I'm a teapot.
Updated on ・3 min read

What's a MOTD?

A Message Of The Day is something that's displayed to you when you connect to a service. It can be the welcome message for an FTP session, the rules for an IRC server, or it can be the first thing you see when you open a terminal.

There's a file which lives at /etc/motd and its contents are displayed immediately before executing a login shell. What does that mean? It means it appears before anything in your shell startup files, like .bash_profile or .zshrc.

What's the point of it?

It's there so the owners of a system can tell all its users something when they connect. Something like "Welcome to FooCorp, your commands are all logged." or "Advance notice: this system will be rebooted for maintenance tonight at 7PM."
Anyone with super user rights can edit it.

Handy, eh? Well not so much for most developers these days, because you lot will mostly be using your system as a single user, and have no need to present that kind of information to yourself.

If you're on a foreign system and don't want to see the same boring old MOTD they've had for donkey's years, you can get round it by creating a file in your home directory called .hushlogin.

This is one time I'd be okay with you using touch to create a file.

My MOTD replacement

I share my shell configuration and init scripts across the systems I use and connect to a lot of remotes. I have the hostname in my prompt because otherwise it's too easy to choose the wrong terminal window and clobber my work files.

funky_motd() {
  printer="cat"
  filter="cat"

  if command -v toilet >/dev/null; then
    printer="toilet -t -f future"
  elif command -v figlet >/dev/null; then
    printer="figlet"
  fi

  if command -v lolcat >/dev/null; then
    filter="lolcat -S $(hostname | shasum | tr -d '[a-f]' | cut -b-4)"
  fi

  printf "\n"
  eval "echo $* | $printer | $filter"
  printf "\n"
}
Enter fullscreen mode Exit fullscreen mode

Bonus level

Since I want to mainly use this as a welcome message when switching environments, I can add it to nvm or venv changes or whatever I want.

The main use though is for seeing in big letters what system I've connected to.

display_host_info() {
  # My work laptop has a dumb corporate name.
  if [[ "$(hostname)" =~ "\.local$" ]]; then
    funky_motd "Macbook"
  elif [ -n "$SSH_CLIENT" -o -n "$SSH_TTY" ]; then
    funky_motd "$(hostname)"
  elif [ -d /mnt/c/WINDOWS ]; then
    # WSL leaves you in the Windows directory by default rather than your home.
    cd

    funky_motd "arcade"
  fi
}
Enter fullscreen mode Exit fullscreen mode

This is kinda what it looks like in use:

Screenshot of a terminal with large colourful representations of host names

Specifically, I'm using toilet or figlet to display the "future" typeface, and filtering that through lolcat to create the colour effects.

If any of these programs aren't installed, it falls back to the next best thing it can do. Worst case, you get a regularly echoed hostname.

There's a little bit of magic with shasum to ensure that the random seed for lolcat's colour gradient stays consistent - so in the example above, I always see the same colours for Arcade whenever I log in, and the same for my Macbook1. This is a neat trick you can use to keep a different colour shell prompt or background or anything you like on a per-host basis. Anything to make it more difficult to type something into the wrong window!

Arcade2 is the name of my gaming PC, if you're curious.


  1. Ok, there's a fudge in there because my work Macbook has a hostname like "EDLA0692BSI.local" for Important Corporate Reasons and that's not what I want to see when I look at my terminal. 

  2. All my personal machines are all named after computers from TV and film. What do you mean you don't recognise this one? 

Discussion (3)

Collapse
taikedz profile image
Tai Kedzierski • Edited

I was trying to figure out why you were using eval, then realised, you are not making use of "array" structures. Using those, you can have:

funky_motd() {
  printer=(cat)
  filter=(cat)

  if command -v toilet >/dev/null; then
    printer=(toilet -t -f future)
  elif command -v figlet >/dev/null; then
    printer=(figlet)
  fi

  if command -v lolcat >/dev/null; then
    filter=(lolcat -S "$(hostname | shasum | tr -d '[a-f]' | cut -b-4)")
  fi

  printf "\n"
  echo "$*" | "${printer[@]}" | "${filter[@]}" # Using quotes and array dereference
  printf "\n"
}
Enter fullscreen mode Exit fullscreen mode

Using the quotes arround the array dereference allows it to split just as you had specified initially. For a more direct example:

my_var=(a "b c" d)
for x in "${my_var[@]}"; do echo "--> "$x"; done
Enter fullscreen mode Exit fullscreen mode

Prints

--> a
--> b c
--> d
Enter fullscreen mode Exit fullscreen mode

As for your output -- which program eventually produced it? I like it :D

Collapse
moopet profile image
Ben Sinclair Author

Wait what I wrote this forever ago and didn't even notice I was using eval. Now I'm not sure why I was doing that at all. Probably to get round issues with things like printing messages that start with a dash or something

I rarely if ever deal with arrays in shell scripts - but your changes look like the right thing to do! Thanks.

The final output in mine comes down to hostname | toilet -f future | lolcat . Future is such a nice, small font compared to the "tiny" fonts or figlet/toilet's usual enormous banners :)

Collapse
thibaultduponchelle profile image
Tib

Wow it's just awesome