Wednesday, June 30, 2010

making the most of bash

To the modern, Windows-accustomed, ungeeky person, those who who work in shells are often thought to hang out with folks like Neo and Morpheus. The truth is: we don't hang out with them, we just `talk` across terminals or occasionally say hi on multiplayer notepad (a.k.a IRC). And it's during these encounters that we sometimes share little nuances that make working in console just a little easier. I'm going to let you in on a few that could encourage you to don dark glasses and start muttering phrases such as 'Know Thyself';

This assumes you understand stuff like cd, cat, redirection, piping, ls and so on
  • screen - create a virtual console that you can detach from. Use ctrl + a, ctrl + d to detach. 'screen -x' will reattach (and allow multiple attachments). Try 'screen -d -m sleep 10' to run the command (sleep 10) in a screen in detached mode. 'screen -x' will attach.
  • wall / talk / mesg / write - wall broadcasts messages to all consoles, for system notices. mesg controls access to your terminal. talk & write is for sending messages to other users.
  • du -sh - Count the size of a directory. the -h outputs in human readable format and -s just shows the total, not all files.
  • df -h - shows disk usage
  • watch - allows you to repeatedly execute a command. e.g. to watch network connections (10s refresh): watch -n 10 netstat -nt
  • which - gives full path to a command in $PATH.
  • CTRL + R and ! - these are bash history functions. '!somestr' will execute that most recent command that matches 'somestr'. e.g. if the most recent command starting with 'ech' was 'echo hello', then '!ech' would re-execute it. CTRL + R allows bash history searching
  • `command output substitution` - backquotes (the one under the tilde~) substitute the output of a command. e.g: echo "Hi, the date is `date`" would stick the date in there. 'vi `which myscript`' would edit '/full/path/to/myscript' if it is in your PATH.
  • jobs, fg, bg, & and CTRL + Z - job control. You can run a process in the background by adding a & to the end of it (e.g. 'sleep 60 &'). in order to bring it to the foreground, you can get the job id using `jobs` and then 'fg '. It is now in the foreground. a CTRL + Z signal will send it back to the background, in stopped mode. 'bg ' will make it run in the background again. note that these jobs are attached to your current terminal session, so a job running in the backgroun will end if you exit.
  • looping and conditions - this can really make life easy for a sys admin, here's some examples:
if [ -f /tmp/somefile ]; then echo "/tmp/somefile exists"; fi
[ -f /tmp/somefile ] && echo '/tmp/somefile exists"
for item in /tmp/*; do echo "Found the following in /tmp: $item"; done
while [ 1 ]; do echo "Infinite loop"; sleep 10; done

Here's a more complex one, using a few:
for db in `mysql -e 'show databases' -B | sed -e "1d"`; do
   for table in `mysql $db -e "show tables" -B | sed -e "1d"`; do
      if mysql $db -B -e "show create table $table" | egrep -qi 'ENGINE=innodb'; then
         echo "$table in $db is InnoDB engine"
         echo "$table in $db is not InnoDB"

  • bash expansion (nice for writing scripts) - bash has some nice features like conditionals and search and replace, that can use less piping to awk / sed (lower on resources). Some examples:
MYVAR=${SOMEVAR:-"default"} - this will set $MYVAR to the value of $SOMEVAR if $SOMEVAR is set, otherwise $MYVAR will be set to "default"
MYVAR=${SOMEVAR//search/replace} - MYVAR will be set to $SOMEVAR with all occurences of 'search' set to 'replace'.

  • in-file search and replace - this can be done with perl or sed, and can match on regex. for example, if you want to change all occurences of INSERTs to REPLACEs within a sql file: perl -i.bak -pe 's/INSERT INTO/REPLACE INTO/g' /path/to/some.sql
the -i.bak backs up the original file.

There's plenty more, so comments / suggestions are welcome (and I'll add some more in here as I remember).

    No comments:

    Post a Comment