Tag: bash

Timeout a process in Bash > v4

Posted by – 19/04/2012

Just for reference, this is really useful:

( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec some_command )

Update Apr 20, 2012 @ 16:54: As pointed in a comment by Timo Juhani Lindfors, if “some_command” exits early and the interval is long, another process can reuse its process number and get killed once the sleep runs out. Does anybody know a better way of doing that without using timeout from coreutils (better yet: using just bash)?

find | while read var; do something “$var”; done

Posted by – 25/06/2009

Essa vai para a galera que scripta muito bash. É a milésima vez que tenho de repetir esse comando para alguém (na milésima-primeira eu desisto e ponho no blog para referência ;-)).

O pessoal fica estressado com nomes de arquivos com espaços, ou tentando usar xargs com mais de um comando. No loop while você pode colocar o conjunto de comandos que quiser para executar sobre a variável em questão:

bash$ find ~/photos | while read foto; do mogrify -resize 800x "$foto"; done

Simples e eficiente.

Best Bash tip ever!

Posted by – 31/12/2008

While googling for something completely different (which I cannot remember right now), I passed by what is probably the best Bash tip I ever read:

bash$ head -10 /etc/apache2/sites-available/default
(...)
bash$ ^10^20^
(...)

What happens in the second command is that the previous one is repeated, replacing “10” by “20”! How great is that?!

Bash prompts: the essential

Posted by – 05/11/2008

Bash is probably the most common command-line shell in the GNU/Linux world. Although a lot of people use alternate shells (such as Zsh), Bash is still shipped with most mainstream distros as the default. Once you have a lot of different remote machines, all running Bash as the shell, it becomes increasingly difficult to pay attention to the prompt, and typing reboot in a machine different from the one you wanted becomes more likely. I deal with that problem by changing Bash prompts…

First of all, the basics: Bash prompts are just environment variables with special characters you can set and export. Bash has four of these variables: PS1 to PS4, but usually only the first two matters (actually, just PS1 – for a reference on the others, check the manpage). The most common PS1 string is:

spectra@home:~$ echo $PS1
\u@\h:\w\$
spectra@home:~$

This has 4 special characters, escaped with a backslash: \u informing us the username; \h informing us the hostname; \w, informing us the working directory; and \$, which gives us the $ in the end of the prompt (more on this later).

So, essentially, one can change that string to anything else…

spectra@home:~$ PS1="my_shell_prompt\$ "
my_shell_prompt$

Pretty easy. You can check a complete reference of the special characters at the section PROMPTING of bash manpage, but the most useful IMHO are the following:

  • \d the date
  • \t the time (24-hour format)
  • \W the basename of the current working directory
  • \! the history number of this command
  • \# the command number of this command
  • \$ shows # if the UID is 0 (is we are root), or $ for all the rest

Also, as part of the prompt string, one can use ANSI Colors enclosed as non-printing characters (that is between \[ and \]). ANSI sequences always begin with an “ESC[” and end with an “m”. (Yes… Really arbitrary… but that’s the way it is…). ESC can be represented as \e… Here is a list of the most common colors in ANSI sequences:

  • Black: 0;30
  • Red: 0;31
  • Green: 0;32
  • Brown: 0;33
  • Blue: 0;34
  • Purple: 0;35
  • Cyan: 0;36
  • Light Gray: 0;37

Now, notice that there are two numbers separated by a semi-colon… the first is always 0 (zero) in the colors I pointed above, but it actually refers to an ANSI attribute called Select Graphic Rendition… You can use 0 (zero) to normal colors, 1 for bold, 2 to faint, etc. So \e[0;30m refers to BLACK, \e[1;30m refers to DARK GREY. The Wikipedia has a good article on these escape sequences.

Once you’re satisfied with something printed in a color, to go back to the default (to reset), you issue the \e[0m escape sequence.

So, back to my problem… Each different machine gets a different color for the hostname. On “hospital” machine, for instance, my PS1 looks like:

spectra@hospital:~$ PS1="\[\e[1;33m\]\u\[\e[0m\]@\[\e[0;35m\]\h\[\e[0m\]:\[\e[0;32m\]\w\[\e[0m\]\$ "
spectra@hospital:~$

With \e[0;35m (Purple) for the hostname. On “home” machine, it may be \e[0;34m (Blue)… On “server”, it may be \e[0;36m (Cyan), and so on… After a while, you get used to the color and end up linking the color to the machine… so that typing “reboot” on a machine with the wrong color gets harder than before.

To make the changes permanent, put export PS1 in one of the config script of bash (.bashrc, .bash_profile, etc). On some systems, /etc/environment holds lots of environment variables definitions.

I just scratched the surface… That’s just what works for me… The Bash-Prompt-HOWTO has some interesting examples, and I actually have a friend who uses more esoterical stuff, such as fancybash or bashish, but I’ll leave this up to you…