The command-line

When interacting with a unix command-line, the user actually interacts through a shell. A shell is a program that provides a user interface, and is primarily responsible for giving the user a way to start other programs.

Unix-users usually have their choice of shells; on our SPMs, we have one shell installed, which is called `Bash'. On the SPM, Bash will present a "#" prompt to you.:

Command-line options

Command options cause commands to behave differently. A unix command (such as the ls command, which lists files), with options, may look something like:

ls -rw 40 --color=always
In unix, command options are typically given preceded by a "-", as in:
ls -l

You can, of course, specifiy multiple options, when using most commands, such as:

ls -l -r

For the sake of brevity, when specifying multiple options, you can usually squish them all together, preceding the entire set with only one "-", like:

ls -lr

There are also what are referred to as `long' options, which are often multicharacter words (rather than `short' options, like ls's "-l" and "-r", which consist of one character). Long options are usually preceded by "--", like:

ls --color

Some options take arguments; with short options, you just write the argument after the option, like:

ls -w 40

Arguments are given to long options like:

ls --color=never

Common command options

-v, --verbose
causes command to print out extra information about what it's doing
-f, --force
command will not prompt you, but will assume that you are sure
-R, --recursive
when operating on a directory, command will recurse through all subdirectories and their files
--version
command will print version information
-h, --help
command will print out help: how it is invoked, what options it accepts, etc.
--
signifies that there are no options after this point (even if there are things that look like options, that are interpreted as regular command arguments; this is useful in commands like "rm -- -f", which means `remove the file named "-f"', where "rm -f" would mean `remove, without prompting, nothing'.

Basic commands

Listing files

The ls command lists files, and accepts many options to control the way in which it lists files. ls's useful options include:

-1
display entire list in a single column
-a
list all files, including hidden files (dot files)
-A
like -a, but doesn't list "." and ".."
-c
sort by change time
-C
list files in columns
-d
list directory entries instead of their contents
-F
append a type-indicator charcter to the end of files' names; this character is "/" for directories, "@" for symlinks, "*" for executable files, and "|" for pipes.
-p
like -F, but doesn't display "*" for executables
-x
list files in lines instead of in columns

Reading files

Two commands are useful for reading the text of files: cat and more.

cat's name comes from "concatenate". When invoked with a list of files as arguments, such as:

cat foofile barfile zippyfile

cat prints the concatenated text of these files.

Also usefule is the more command, which displays lengthy text one screen at a time. more accepts file-names as command arguments. If invoked with no arguments, more reads text from standard input, which makes it useful for piping the output of long-winded commands through, ie:

ls -l /bin | more

Moving and renaming

To move a file, and to rename it, are usually really the same thing. To accomplish either task, use the mv command, as in:

mv foo bar

The above command moves the file, "foo", to "bar". If `bar' does not already exist, then `foo' is simply renamed. If "bar" exists, and is a directory, then `foo' is moved into `bar', thus becoming `bar/foo'. If `bar' is a regular file, it will be removed, and then `foo' will be renamed.

Copying files

To copy files, one uses the cp command. For example:

cp foo bar

The cp command accepts the following command-line options:

-d, --no-dereference
preserve links--copy symlinks instead of what they point to
-l, --link
hardlink files, instead of copying
-p, --preserve
try to give new files the same permissions (and owners) as the original

Linking

Sometimes more useful than copying a file, the ln command creates a link to the file. ln can make two types of links: hard links, and symbolic links. The default behaviour is for ln to make hard links.

When one makes a hard link, one creates another name for a file, and the two (or more) resultant `files' are indistinguishable--they share the same inode, and any changes to the inode are reflected in all of its links. Hard linking is a way to make a single file exist in several places (or with several names) simultaneously.

When one makes a symbolic link (or symlink), one creates a special entry in a directory that points somewhere else. When a program attempts to open a symlink, it will end up opening the file (or directory) that the symlink points to. Note that symlinks need not be valid, meaning that they can point to files that don't exist--such a symlink is rightfully referred to as broken.

ln accecpts the following options:

-s
make a symbolic link, rather than a hard link
-n
no dereference symlinks--treat like normal file. Useful in combination with -f, when wanting to replace an existing symlink to a directory.

Deleting

The unix command to delete things is rm, as in:

rm somefile
rm -Rf somedirectory

Setting permissions

A unix file has permissions relevant to the user who owns the file, the group that owns the file, and `everyone else' who is not the indicated user and who is not in the indicated group. At the same time, a file has permissions indicating readability, writability, and executability. This gives us a table of attributes, like this:

user group others
read user-can-read groupies-can-read others-can-read
write user-can-write groupies-can-write others-can-write
execute user-can-execute groupies-can-execute others-can-execute

Those coming from a DOS-based world may be surprised by the presence of the executability setting, and often ask where all of the ".exe files" are. The truth of the matter is that file-extensions are best used to indicate the type of data in a file, and, given the number of file-formats that one may or may not want to treat as `programs' (infinite?), and that we may not want everyone to be able to run some programs, using a file's name to determine whether it is executable is a rather silly practice. On directories, the `executable' attribute is treated as meaning `accessable'.

In addition to these 9 permissions, there are 3 other permissions:

These 3 permissions are only meaningful on executables and directories. On an executable `program' file, the set-user-ID (SUID) attribute causes the program to run with the permissions of that user. The SGID property causes a program to run with the permissions of the indicated group. Being sticky causes a program to be cached in memory, even after it finishes executing; this sometimes done for frequently-used programs to prevent them from needing to be reread from disk each time they're invoked.

On directories, SGID means that all files created in the directory will have the same group as the directory, rather than of creator of the file. Making a directory sticky prevents users from deleting the files of other users in that directory, even if the user has write access to the directory. SUID is not meaningful on directories.

Using ls -l to display information about files (or ls -ld for directories), you get information like this:

-rw-r----- fred users 1453 Apr 12 16:06 myfile
-rwsr-x--T fred users 3512 Apr 13 12:01 myprogram
-rwxr-xr-t fred monks 4423 Apr 13 12:15 ourprogram
drwxrws--- fred monks 2048 May 12 15:31 ourdirectory

The 10-character strings in the left-most columns display both the files' permissions and their types. From left to right, the characters in the string indicate:

  1. type
  2. user readable
  3. user writable
  4. user executable and/or SUID
  5. group readable
  6. group writable
  7. group executable and/or SGID
  8. readable-by-others
  9. writable-by-others
  10. executable-by-others and/or sticky

The type, as explained below, are "d" for "directory", "l" for "symlink", "c" for "character device", "b" for "block device", or "-" for "regular file".

The permission-indicators are an alphabetic character indicating Boolean truth or `yes', or the character "-" indicating `no'; the indicators for readability and writability are self-explanatory.

If a file is SUID or SGID, there will be an "S" (uppercase) in the appropriate space. If the file is also executable, then the "s" is lowercase. If a file is executable, but not SUID (or SGID), then an "x" is used as an indicator.

If a file it sticky, a "T" is used as an indicator in the appropriate place. If the file is also executable by `others', then a lowercase "t" is used. If a file is executable and not sticky an "x" is used.

The chmod command can be used to change the permissions on files. chmod takes file-names as arguments, along with a numeric representation of a full set of permissions (ie: 0755) or one or more symbolic permission-modifier strings.

Symbolically, you can tell chmod to add or remove specific permissions on files, with commands like:

chmod a+x myfile
chmod a-w myfile
chmod ug+sxr o-rwx myfile
chmod g=rx myfile

"u", "g", "o", and "a" (on the left side of the symbol) mean "user", "group", "other", and "all", respectively. "r", "w", "x", "X", "s", and "t" mean "read", "write", "execute", "execute (if file is a directory or is already executable by someone)", "set ID (which ID depends on who it's being applied for)", and "sticky", respectively. "+" means "set these bits to true", "-" means "set these bits to false", "=" means "set these bits to true and set all others to false".

Since there are 4 sets of permissions (`special', user, group, and world), each being composed of 3 Boolean (true/false) values, it's ideally compact to represent the whole permission-set with 4 groups of 3 bits, or a 4-digit octal number. For each of the user, group, and world permissions, the bits of the number are as follows: 4 is readability, 2 is writability, 1 is executability. For the `special' digit, the bits are: 4 for SUID, 2 for SGID, 1 for sticky. So, for example: 0755 is not SUID, SGID, or sticky; it is readable, writable, and executable by its owner; it is readable and executable (but not writable) by its group and everyone else.

Administrative and advanced commands

Mounting file-systems

In unix, all physical storage-devices have their file-systems mapped into a single hierarchy of directories. Adding file-systems to this tree is accomplished via use of the mount command, ie:

mount -t minix /dev/hda1 /usr

The above command `mounts' the device, /dev/hda1, as a minix file-system, attaching it at the directory, /usr.

If you use the mount command with no arguments, a list of all currently-mounted file-systems is printed, which looks something like this:

/dev/ramdisk on / type minix (rw)
/dev/hda1 on /usr type minix (ro)
proc on /proc type proc (rw)
none on /dev/pts type devpts (rw)

This output lists 4 pieces of information about every mounted file-system, in order:

  1. which device the file-system resides on
  2. which directory the file-system is attached to
  3. the type of the file-system
  4. the options set for the file-system

In the above example, the root directory's (/) file-system is located on the device /dev/ramdisk (a ramdisk), it is a minix file-system, and it is mounted in readwrite mode. /usr is based on hda1, is a minix file-system, and is in read-only mode.

To undo a mount action, use the umount command.

Creating device-files and pipes

To create pipes, use the mkfifo command. To create device-files, use mknod, for example:

mkfifo mypipe
mknod mydevice c 1 1
mknod myblock b 3 0

mknod takes 3 arguments:

  1. the name of the file to create
  2. the type of the file ("b" for a block device, or "c" for a character device)
  3. the major number
  4. the minor number

The first mknod example, above, creates a character device file named "mydevice", with major number 1 and minor 1--this is equivalent to /dev/mem. The next example creates a block device file named "myblock", with major 3 and minor 0--this is equivalent to /dev/hda.

Note: you can also use mknod to create pipes, by specifying "p" instead of "c" or "b" as the device-type parameter.

Getting/setting the date

The command to get the date is date. To set the time, use date -s. To set the full date, use a command of the form date MMDDhhmm[[CC]YY][.ss], where MM is the month, DD is the day, hh is the hour, mm is the minute, CC is the century, YY is the year, and ss is the second--each letter should be replaced by a digit; brackets indicate that something is optional. Examples:

date -s 13:40
date 0414
date 04141340
date 041413402000

Setting passwords

The passwd command will ask you to enter a new password, and then to enter it again for verification, and then it will set the password.

Viewing messages from the kernel

The dmesg command prints messages from the kernel. As this list tends to be quite lengthy, you'd probably want to pipe it through more, like:

dmesg | more

Viewing processes

The ps command prints a list of the currently-running processes, their process IDs, and their states. A process' state is indicated by a single letter, define as follows:

D
uninterruptible sleep (usually IO)
R
runnable (on run queue)
S
sleeping
T
traced or stopped
Z
a defunct ("zombie") process

Killing processes

This is actually `how to send signals to processes'. After a process is started, if you can't interact directly with the program, you can still control it by sending it signals. There are many different signals that unix processes can recieve and respond to; the most commonly used include:

SIGTERM (signal 15: terminate) is sent to a process to request that it end. A process will usually respond to this by doing whatever cleanup it should do before exiting, and then exiting.

SIGKILL (signal 9: kill) is sent to processes to demand that it exit. Other signals can be `caught' by a process, and the process can then choose how to respond to them, if at all; SIGKILL is the one signal that cannot be caught, and a process must exit immediately upon receiving this signal.

SIGHUP (signal 1: hangup) usually cases a running program to reload any configuration files, and basically restart itself.

To send a signal to a process, one uses the kill command, such as:

kill -TERM 1619
kill -KILL 1542
kill -9 1452

Checking disk-usage

The two commands, df and du display statistics about the space used in file-systems. df accepts names of directories or device-files as arguments, and prints out:

  1. the device (on which the directory resides)
  2. the total amount of space on the device
  3. the amount of used space on the device
  4. the amount of available space on the device
  5. the directory (at which point the device is mounted)

du takes names of files or directories as arguments, and displays how much space those objects use. By default, when used to display the size of a directory, du will recurse through that directory and display the size of every file and directory within it. The -s option causes du to display only one (total) size per item specified on the command-line.

Unixisms

Unix devices, and other special files

In unix, many things are incarnated as files; there are 6 types of files:

Plain files and directories

Plain files like files that every other operating system has--they contain text. This may be configuration-data, program-text, a human-readable text.... Directories, also, are just like they are in most other operating systems. Symbolic links are addressed above.

Device files

special files, or device-files, are not simple collections of text. What makes these files `special' is that they are (usually) representative of a piece of hardware in the computer, such as a hard drive, a partition on a hard drive, the computer's RAM, the computer's serial ports..., etc.

special/device files are usually located in the /dev directory, and usually have standard names associated with their function; the actual function/meaning of a device-file is, however, independant of its location and name--it is dictated by two numeric attributes of the file:

  1. major number
  2. minor number

Device-files are also sorted into 2 types:

Block devices are devices that have an associated buffer/cache, such as hard drives. Character devices are then devices which have no cache, such as serial ports and RAM.

Here is a list of serveral important device-files in our SPMs, their major and minor numbers, and their meaning:

/dev/hda, 3, 0
first IDE drive in the system (SPM's compact flash)
/dev/hda1, 3, 1
first partition on first IDE drive
/dev/mem, 1, 1
the machine's RAM
/dev/null, 1, 3
a black-hole/bit-bucket device--a kind of ground device; a receptical for data that you wish to make go away; most common use is to redirect messages from a command to this file
/dev/ptmx, 5, 2
pseudoterminal multiplexer; when a program opens this file, a new pseudoterminal is `automagically' created in the /dev/pts directory.
/dev/tty, 5, 0
the TTY device currently in use
/dev/ttyS0, 4, 64
first serial port
/dev/ttyS1, 4, 65
second serial port
/dev/ttyS2, 4, 66
third serial port
/dev/zero, 1, 5
a source of null-bytes; copy data from this to create empty files of desired size

FIFOs/pipes

Pipe-files are simple FIFO (First In First Out) queues--date written to them stays in them until it is read out. If you display the file-size of the pipe, you'll see how many bytes are queued in it. These are also referred to as `named pipes', because they have a file-name associated with them, rather than the dynamical, ephemeral pipes that link different commands together.

I/O-redirection: pipes

In unix, there are three standard I/O streams: standard input, standard output, and standard error. The first is what a program reads in, the second is what a program usually prints out, and the third is for when a program prints error messages.

All three of these streams can be redirected by the shell--you can redirect them to a file, or even to another command.

One of the most common redirections is to redirect the output of a command to a file, like:

echo this is some text > myfile

One of the most common redirections is to redirect the output of one command (or program--the two terms are often used interchangeably) to the input of another command.

For example: let's say that you want to count the number of files in a directory. For this, you can use a command like:

ls -1 | wc -l

The command above connects the output of ls -1 to the input of wc -l. The text that ls outputs (a list of files, one per line) is read in by wc, which proceeds to count the number of lines. This redirection of I/O streams is referred to as piping.