|Home » Learning Curve
Cookie Tin Tips II
This series is directed to potential switchers. It's about Unix. Remember when reading that Unix is considered more than an operating system: it's a way of thinking.
A First Look
Unix is at once - and from the very beginning - a multiuser and 'time sharing' system. The PhDs in the corridor of the CSRC at Bell Labs could trust one another, but still and all you need security, and security was built into Unix from the very outset.
You have to log in to Unix to get access to it; having access to the physical box means you can also start the system in what is known as 'single user mode' which in effect gives you 'superuser' or 'root' access.
The highest honcho on any Unix box is the superuser most commonly known as root. A number of limitations on this account are to be implemented by Sun Microsystems but traditionally root can get at almost anything on the machine which other users cannot.
Some user groups are set up to be able to escalate their privileges (under certain circumstances) to root level. It is root who decides who will be able to do what; a further authentication - most often in the form of password - is also needed.
When you log in to Unix you arrive at your home directory. The old passwd file spells it all out quite clearly.
% cat /etc/passwd
www:*:70:70:World Wide Web Server:/Library/WebServer:/noshell
sshd:*:75:75:sshd Privilege separation:/var/empty:/noshell
This is a series of records with colon delimited fields. The first field is the name of the account. The second is the encrypted password (using a salted version of DES). The third is the account number or UID. The fourth is the group number or GID. The fifth is a description of the account; the sixth is the directory the user is dropped in after login; the seventh is the user's 'shell'.
Note that this file is normally not used anymore - in the interests of further security. The '*' in the password fields is an impossibility: it means the account is effectively disabled as no password can with DES result in a single asterisk.
Note that with the root account both the user ID and the group ID are zero. Any Unix account with user ID and group ID zero is by definition a root account. The name need not be the same - the IDs determine the security level.
In the above record the root account is also disabled ('*'); the account is given the description 'System Administrator'; the home directory and starting shell are set to '/var/root' and 'tcsh' respectively.
A strict Unix terminal login never tells you what went wrong with a login. You must first type your username and then enter your password a new prompt - but even if your username doesn't exist the login process won't let on. Only if one or the other proves incorrect will the login process say simply:
And bring back the original login prompt again.
Your shell (tcsh for root above) is your command interpreter. There are light years of difference between Unix shells and the kinds you run into on tinkertoy operating systems like MS-DOS or Windows. These shells are brutal to say the least.
They allow use of variables, enumeration of directory contents, control flow - almost everything possible under the sun. And there are at least five such shells in popular use today.
|sh|| ||The original 'Bourne shell' written by Steve Bourne of Bell Labs.|
|csh||The 'C shell' variant written at Berkeley.|
|ksh||The 'Korn shell'.|
|tsch||A popular variant of sh used on OS X.|
|bash||The 'Bourne again shell' [sic] popular on Linux.|
It's easy to switch shells if you're authenticated: simply type in the name of the new one. Exiting a secondary shell is almost as easy: simply type in 'exit' and you're back where you started.
Unix even has 'restricted shells' for use in high security installations. Users who are given these shells cannot roam anywhere they like in the system file hierarchy and will find themselves limited in other ways too.
One File System
Unix has only one file system. There are no drive letters. No matter how many volumes on your system there is only one hierarchy - they're all mounted together.
Early Unix had at least two disks on a typical system: one for the OS itself and another with the users' home areas. This latter drive would 'mount' under the path /usr.
Looking at the second drive by itself it would appear everyone's home directory was in the root directory ('/') but when it was mounted at boot time it would be attached (mounted) at /usr and this is where users would find their files.
And so it works today - except that OS X user accounts are found at '/Users' instead and most Apple computers start with a single physical drive.
Not that there are not further file systems in effect mounted into that one single file system you see; but that's another story best left for later.
Even your removable drives - CDs, DVDs, iPods, and so forth - mount into your one single file system. On OS X they appear at the path '/Volumes'.
Your standard Unix 'binaries' (program files or 'tools') are located today in four different locations.
|/bin|| ||The original location for programs.|
|/usr/bin||Used when /bin got as big as anyone wanted. User binaries.|
|/usr/sbin||Same thing applied to /sbin.|
A 'path' is automatically applied to your login; you can see this path at any time by issuing the following command.
A good path (all are in this respect good today) will never include your current working directory. Most often your path will simply be the four paths listed above.
If you're looking for the location of a program you often run, use the whereis command to find it. whereis looks for it the same way your shell would but merely prints out the path when it's found (and if it prints out nothing it wasn't found).
Unix also takes its shells very seriously: anytime you invoke a shell you get a new set of variables to follow you around. In fact most of Unix is built around the concept of a shell, using something called the 'fork'.
To start a new process, the system first makes an exact duplicate of the calling process. Then the duplicate's 'forked' off to be the target process instead; your calling process will then wait for the 'child' process to exit. And when it does your first process continues.
There's actually a great story around this told by Dennis Ritchie. In the first days of Unix it was not possible to create new directories without rebooting the computer to see the results. Obviously this was less than usable so Ken set about trying to beef things up.
They were stymied for months. Every time they tried to create a new directory things went fine; but when they tried to move into that new directory they always ended up where they started from.
They picked the code apart byte for byte and found nothing. Until one day when they remembered they were using shells extensively. This is what was happening.
- Create new directory which can today be seen without rebooting.
- Attempt to move into that directory by using the 'cd' program.
- Get a prompt back again after above.
- Check with 'pwd' (print working directory) and find nothing's changed.
But when invoking 'cd' they in effect did a 'fork' which spawned a new shell; inside this shell they were indeed at the new path; but then that shell exited and they were back where they started from.
Obviously they found a way around this but the fact remains Unix is oriented around 'concentric' shells and shell variables.
To make sure each successive shell gets the same values, they use a directive called 'EXPORT'. EXPORT lists all variables (path and so forth) that should apply to successive shells and when you create a new one those variables follow along.
Classic Unix by definition does not allow inter-process communication - and Ken was adamant about this. Unix processes can only know when another process exits. No more. And while this may not always hold 100% today it's still a cornerstone of Unix philosophy.
- Clean interfaces.
- Don't reinvent the wheel.
- Make each program do one thing and do it well.
- Keep your hands off the drivers.