Changelog 547 - Efficient Linux at the CLI

Changelog 547 - Efficient Linux at the CLI

Published on in know-notes & the-changelog.

Changelog 547 - Efficient Linux at the CLI

I was first schooled at the bash terminal in 2001. I was home from college and I had a summer gig at NMS Communications in Framingham, MA. Back in those days we barely had datacenters, I think we still called them computer labs: a room in the office with 10-50 racked computers, about 5-10 monitors that could be switched between the different servers, and you needed a parka because the max temperature seemed around 45℉.

We were using a few different flavors of Linux there. I remember RHEL and something like CentOS (though CentOS didn't exist yet). I floundered around at the terminal, barely finding my way from point A to B. But I had a wonderful manager, whose name I can't remember unfortunately, who was a wizard at the terminal. It was mindblowing to watch him work. He taught me many tricks I still use today, for example these aliases:

alias u='cd ..'
alias uu='cd ../..'
alias uuu='cd ../../..'
alias dv='dirs -v | column -t'

Then in 2008, my first gig back in Boston after 8 years away, I worked at Nuance Communications (no relation to NMS Communications) on a backend Speech Recognition system written entirely in [gasp] perl, bash, and Makefiles. This is where I really honed my bash skills.

The Episode

I loved this episode. The only topic that I didn't recognize was CDPATH. That is pretty useful!

On Process Substition

Another common use of process substition is while loop input. For example, a while can take a file as input this way:

while read dir ; do
  echo ${dir}
done < /tmp/some-text-file.txt

You can use process substition to chain more complicated commands together, e.g. loop through all child directories of the current directory, sorted, and exclude the '.' directory reference:

while read dir ; do
  echo ${dir}
done < <(find . -maxdepth 1 -type d | sort | grep -v -e '^\.$')

NOTA BENE: Some may be wondering why not just pipe the output of the command directly into the while. You can do that in many cases, though I try to limit pipes interacting with loops because you can run into some nefarious bugs that way, e.g. when one iteration of a loop fails in its piped subshell but the rest of the script keeps on chugging.

On Job Control

You actually can use the Job Control built-ins to keep something running on a remote box a la Screen/tmux with a combination of ^Z (Control-Z), bg, jobs, and disown:

./long-running-script.sh
^Z               # Control-Z
jobs -l          # get job id AND pid
bg               # start job in background
disown -h <pid>  # disown it from the current user and prevent SIGHUP from killing it (-h)

Here's a video of it in action:

bash-job-control-disown