Bash

Create a scalable environment with Bash

\This is the philosophy of Unix: write programs that do one thing and do it well. Write programs to work together. Write programs to handle streams of text, because that's a universal interface.

Douglas McIlroy

Bash (and its derivatives) have been present in the history of computing for more than 30 years and although it has never been a language considered a pivot for innovation, it has helped many developers to make their work less monotonous.

It is both a command line interpreter( Unixshell ) and a scripting language for (in principle) unix-based environments. Like most Unix shells, it supports wildcard matching in filenames, pipes, command substitution, variables, and control structures for condition and iteration testing. Keywords, syntax, dynamically scoped variables and other basic language features are copied from sh. Other functions, e.g., history, are copied from csh and ksh. Bash is a POSIX-compliant shell, but with several extensions.

The name of the shell is an acronym for Bourne Again Shell, a play on the name of the Bourne shell it replaces and the notion of "being born again".

This is a small introduction to a project I have been working on privately for some time, in order to organize functions, aliases and environment variables in a way that makes sense and can be scalable.

Motivation

I have been using the bash terminal for several years now to shorten the amount of work that is regularly done with a graphical user interface, but as the projects I work on grow in complexity, the amount of commands I must use to compile, package, and upload code to test devices (I work with networks) increases as well. I believe that, as I described in a previous article, it takes a lot of creative energy to work in software development and every time we waste about 10sec trying to type or remember some complex command in the terminal, we lose some of that energy that helps us to make decisions that are relevant.

Time management is crucial to being a successful developer, not only to deliver work on time, but to ensure quality and optimization when solving a problem.

The math doesn't fail in that sense, if I lose about 8-10 seconds every time I have to test a change, assuming I take about 10-15min to write part of the code per year I would be losing between 20-29 hours per year just doing mechanical work and in projects like the one I work on these numbers can double or triple.

\

Yes, it seems obsessive-compulsive to count this time, but the time lost in mechanical work is not what is relevant, it is the time lost in really creative work.

The idea

It was very simple, to be able to have a project that met the following characteristics:

  • Be scalable, allowing the separation of interests (it is not the same to have functions for networking than aliases for git).
  • Be easily exportable to other platforms (operating systems, servers, raspberry pis, etc.), so its processing has to end in a single exportable file (envrc).
  • Its adaptability should be simple, so that when you need to add a new command or configuration, its place makes sense from the beginning.

Organization of the archives

The choice of the organization of the files was not so difficult when I had a clear idea, the result was the following:

/
  config        # Carpeta para agregar todas las configuraciones que van en el ~/.config
    jrnl        # Ejemplo: Mi configuración por defecto para jrnl.sh
  env           # Carpeta en la que se almacenan de forma separada los scripts
    git.sh 
    global.sh
    media.sh
    network.sh
    personal.sh
  rc            # Configuraciones específicas para los archivos rc (de bc, la calculadora, por ejemplo)
    .vim
    .bc
    .vimrc
  Makefile      # Archivo que ayuda a construir el .envrc en instalar el entorno usando la herramienta make
  deploy        # Script que ayuda a subir el entorno de desarrollo a un host externo (rpi, servidor, etc.)

Scripts

Scripts are internally organized into: environment variables, aliases and functions. For example:

#!/bin/bash

###################################################################################
# #
# PERSONAL ENV #
# #
###############################################################################################

HUGO_SUPPORTED_LANGUAGES=(\"en\" \"es\")
EMOTIONS_TEMPLATE=/home/jpgarcia/journals/templates/emotion.txt

#########################################################################################
# #
# PERSONAL ALIASES #
# #
###############################################################################################

alias hpost=\”hcontent posts\”
alias hproject=\”hcontent projects\”
alias emotion=\”jrnl emotions < $EMOTIONS_TEMPLATE && jrnl emotions -1 –edit\”

#########################################################################################
# #
# PERSONAL FUNCTIONS #
# #
###############################################################################################

function hcontent() {
if [ ! -d content/$1 ]; then
echo \”You must be on a HUGO project directory. Or create a base directory for content/$1.\”
else
if [ -z \”$2\” ]
then
echo \”You have to provide a valid $1 slug (e.g: first-post)\”
else
for VARIABLE in $HUGO_SUPPORTED_LANGUAGES
do
hugo new $1/$2/index.$VARIABLE.md
done
fi

fi
}

function jrnl() {
if [ $MACHINE = \”Mac\” ]; then
/usr/local/bin/jrnl $@
elif [ $MACHINE = \”Linux\” ]; then
~/.local/bin/jrnl $@
else
echo \”jrnl.sh not found for $MACHINE\”
fi

if [ -d ~/journals ]; then
cd ~/journals
if ! git diff-index -quiet HEAD -; then
git add -all
git commit -m "Log $(date)\"; then git add -all
git push origin master
fi
cd -
fi
}

The special touch

What makes this an interesting project is that no matter how many files, functions and environment variables are added, with the use of the Makefile, all these files are converted into one with a 'merge' function:

merge_env:
  if [ ! -f envrc ]; then 
    echo \"Generating envrc file\"; 
    if [ -f /tmp/envrc ]; then 
      sudo rm /tmp/envrc; 
    fi; 
    touch /tmp/envrc; 
    cat env/*.sh > /tmp/envrc; 
  fi

The envrc file is temporarily generated and then copied to the preferred directory (in my case /etc).

Conclusion

With bash you can control virtually any part of the operating system that is running. It is the gateway to the operating system, so having a personal and adaptable development environment will always keep your work as non-creative as possible.

The complete project is published in github and you can find it in the following link.

\"\"

Juan Pablo

Technical Lead

Scroll to Top