Updated CheatSheet

September 5, 2012

I have updated the cheatsheet at http://steve-parker.org/sh/cheatsheet.pdf – it’s still a single-page PDF, or a PNG at http://steve-parker.org/sh/cheatsheet.png, but it squeezes a bit more content in than the previous one had, and is slightly more Linux/Bash biased.

What shell am I running?

March 18, 2012

Whether you’ve got an interactive shell session, or are writing a shell script, it is very difficult to be certain. It’s better to check for the capabilities that you require.

If you find yourself in a shell session, but don’t know what type of shell it is, there are a few ways to find out whether it’s Bourne shell, Bash, ksh, csh, zsh, tcsh, or whatever.

The simple answer is that you type in the command

echo $SHELL

which should tell you the path to your current shell; if it’s /bin/ksh or /usr/bin/ksh then it’s the KornShell; if it’s /bin/csh then it’s the C shell, and so on.

However, it’s not always that simple; Bash will set $SHELL only if it was not already set, so if you were running csh and use that to call bash, then Bash’s $SHELL will still say csh, not bash. However, Bash will set the $BASH_VERSION variable, but that’s not really a guarantee that you have that version; it only tells you that there exists a variable which specifies that version. You may not even be running bash at all.

Similarly, some shells (particularly /bin/sh) are symbolic links to others – whether to bash (GNU/Linux and newer Solaris), dash (some Linux distros more recently), or ksh (AIX).

So $SHELL is a useful start, but not at all definitive. You can search for your UserID in the /etc/passwd file:

$ grep steve /etc/passwd
steve:x:1000:1000:Steve Parker,,,:/home/steve:/bin/bash

But there may be many entries containing the text “steve”, and you could be using NIS, LDAP, AD or some other authentication mechanism. $UID should be a read-only variable containing your UserID, and you can search your system-specific passwd via the getent command:

$ getent passwd $UID
steve:x:1000:1000:Steve Parker,,,:/home/steve:/bin/bash

However, as my UID is 1000, this would match any line containing “1000” such as an account called “HAL1000”. So this should be one way to get your shell:

$ getent passwd $UID | cut -d: -f3,7|grep "^${UID}:"

Still, you could have run another shell after picking up your default shell. You can always check $0 – that should tell you how your current shell was called. You don’t know what the $PATH variable was when that was called – if $0 says “/usr/bin/zsh” then that’s what was called (of course, it is possible that/usr/bin/zsh could have changed since your shell was invoked!). If it just says “sh” then it’s whatever “sh” was found first in the $PATH of the calling shell. And of course, you can’t find out for sure what state that shell was in at that time.

On a Linux system, “cat /proc/$$/cmdline” should also give a good clue; “ls -l /proc/$$/exe” is better (but not definitive; it may be marked “(deleted)” if it’s been deleted, so you should check if it’s been subsequently replaced by some other shell.

So – it depends why you need to know. If you need to know for sure, on an unknown system, exactly what shell you are in, then I’m sorry, it’s not possible to be absolutely certain. To be reasonably confident, check $SHELL or $0. If you need to be more certain than that, then check for the features you require.

If you’re writing a shell script which requires arrays, then define and access an array, check that the results are as expected, and if not, bail out with a message along the lines of “an array-capable shell is expected – we suggest bash or ksh”.

rm -rf /

February 1, 2012

It is commonly said that Solaris 10 will not allow you to issue a rm -rf / command. Few get to try it, but it was being discussed in the office today, so I thought I’d try it on a virtual machine.

The classic rm -rf / gets the message “rm of / is not allowed” and a return code of 2. Some variations get the same, whilst others (such as cd /; rm -rf .) get no message, a return code of zero, but nothing happens. Here is a transcript:

$ ssh sunflare
Last login: Tue Jan 31 21:38:05 2012 from goldie
Oracle Corporation SunOS 5.10 Generic Patch January 2005
steve@sunflare:~$ su -
Oracle Corporation SunOS 5.10 Generic Patch January 2005
# bash
root@sunflare:/# df -h .

Filesystem             size   used  avail capacity  Mounted on
/dev/md/dsk/d10        9.6G   3.6G   5.9G    38%    /
root@sunflare:/# rm -rf /
rm of / is not allowed
root@sunflare:/# echo $?
root@sunflare:/# cd /usr
root@sunflare:/usr# rm -rf ../
rm of / is not allowed
root@sunflare:/usr# cd /tmp
root@sunflare:/tmp# rm -rf ../
rm of / is not allowed
root@sunflare:/tmp# cd /usr/sfw/bin
root@sunflare:/usr/sfw/bin# rm -rf ../../..
root@sunflare:/usr/sfw/bin# cd /
root@sunflare:/# rm -rf .
root@sunflare:/# echo $?
root@sunflare:/# pwd
root@sunflare:/# df -h .

/dev/md/dsk/d10        9.6G   3.6G   5.9G    38%    /
root@sunflare:/# cd /dev
root@sunflare:/dev# rm -rf ../tmp/../
rm of / is not allowed
root@sunflare:/dev# rm -rf ../tmp/..
root@sunflare:/dev# exit
steve@sunflare:~$ logout
Connection to sunflare closed.

Shell Scripting book – out now

September 24, 2011

In case you hadn’t heard via other channels, my 564-page book, Shell Scripting: Expert Recipes for Linux, Bash and more is on sale now.

Paper books:
Amazon USA
Amazon UK
Also available at Barnes & Noble, WH Smiths, Waterstones, Supermarkets (online, if not in-store), and as the saying goes, every good bookshop (and some others too).

Kindle: Kindle

iPad / etc: iTunes

Nook: Nook

There’s also a Facebook page at facebook.com/shellscript.

Arcade Games written in a Shell Script

July 13, 2011

Yes, it is perfectly possible. Do watch this YouTube Video

Space Game

Space Game

Space Invaders – written entirely in the Bash shell, in a 248-line shell script.

The shell is often seen as old hat, hard to use, green screens and no interaction. In my new book, Shell Scripting (http://facebook.com/shellscript), I attempt to throw a new perspective on this; the shell can be used in lots of creative and imaginative ways.

The book also covers creating CSV files to easily plot complex data in spreadsheets, creating HTML as well as parsing HTML documents; I plan to post more updates before its launch on 12th August 2011.

Shell Scripting by Steve Parker. ISBN 1118024486


You can get the code for the game here. The description and explanation is in the book, of course. But at least the code itself is available online for inspection.

Shell Scripting page on Facebook

July 11, 2011

Shell Scripting

Shell Scripting

My Shell Scripting book, due out on August 12th by Wrox, now has a page on Facebook: http://www.facebook.com/pages/Shell-Scripting/175263275869249. Feel free to “Like” it, and get the latest updates on the project.

I have the final pages to proofread this week, ready to go to the printers. It’s looking like 576 pages, a little bit over the target of 504 pages, but close enough.

I will update the Table of Contents at http://sgpit.com/book/ once the page count is finalised.

Fork Bomb!

June 3, 2011

A few days ago I had to deal with my first ever real-life fork-bombed server.

By logging in to the console, I was somehow able to get a shell (one process). Having got that shell, even though I was root, it was difficult to be able to spawn other processes. It turned out that this was because we had restricted the CPU count on the kernel command line (maxcpus=2) so that a dual processor, 16-core machine had only one eighth of its processing power available. The dynamic change to the nproc value does not take this into account, so this unprivileged user was able to fork-bomb the entire machine.

The first thing you might want to do in this situation is to run ps -eaf. That’s another process, and even as root, you don’t get to do it. Being Linux, you can see how many processes exist on the system by listing /proc:
cd /proc
echo *

Neither of these commands spawn a new shell, they are both shell builtin commands, so they will work. In this case, with over 69,000 processes, I killed the output before I got too bored. Since there are usually around 200 processes running, that was enough to tell me that something was wrong.

After many attempts, a ps command did work, and confirmed that a certain shell script was being run a lot of times. I couldn’t cat that file, and didn’t even have its full name (ps truncates output to match the terminal’s width). I had the PID, so /proc/$PID/fd gave the filename.

It’s not possible to cat the script to see what it’s doing, so more builtin commands are required.
$ while read f
> do
> echo $f
> done < /path/to/script.sh

This uses all builtin commands, and tells you what the script is. From there, you may have some insight into what it is doing, and how to stop it.


Get every new post delivered to your Inbox.