The shell you get when you log in is a login shell and reads both .login and the shell resource configuration file (.cshrc) The shells distributed with the base install (i.e. shells audited by the OpenBSD team implying a basis of security) are: /bin/{,c,k}sh
ksh is the default shell for OpenBSD's root user and there seems to be heaps of arguments for and against retaining it as the default root shell. The reasoning often deteriorates to user preferences. I'm documenting this shell, or the tidbits I'm starting to use, because I'm finally going to learn the shell. 'sh' is the default shell for single-user.
Unfortunately I'm a DOS/Windows throwback dinosaur so I word-process a lot better than I shell, and can't even program unless there's some GUI debugging environment to handhold me through those breakpoints.
Which ever shell you choose to use, it is most advisable to ensure your shell is statically linked [ldd(8)] if you intend to use it when booting in single-user mode. Essentially, dynamically linked shells are in danger of failing if the dependency libraries are unfortunately removed or you do not have access to the libraries for some reason.
[ref: csh(8), sh(8)]
[ref: Making
friends with c-Shell and t-Shell]
When csh starts it looks at a number of default configurations and you can make your modifications to your custom resource file: ~/.cshrc
File: ~/.cshrc
if ($?prompt) then
set prompt = "% "
set history = 10000
set notify
set filec
endif
alias h history
alias ll ls -l
alias dir ls
set path = ( /bin /usr/bin /sbin /usr/sbin /usr/local/bin /usr/local/sbin /usr/X11R6/bin )
|
The above is a simplified version of '.cshrc'.
The 1st part (the if condition) tests whether the shell is an interactive shell. If it is an interactive shell then it gives settings for things relevant to an interactive shell. After the test, we set a few alias' to simplify our commandline typing, and specify our path.
A few nice features that you get used to in Bash is file completion. We make that setting using 'filec'. Likewise, you can specify how long a history of your previous commands csh will store.
filec - Enable file name completion
history - the size of the history list
ignoreeof - if set the shell ignores end-of-file from input devices which are terminals. This prevents shells from accidently being killed by control-Ds
Some of the commands you wish to initialise are only relevant to the initial login process, and not every reincarnation of the shell. We can specify these specific commands in the ~/.login file
~/.login
set tterm='?'$TERM set noglob tset -I -Q setenv TERM vt220 stty erase '^?' unset noglob unset tterm |
If you have trouble backspacing or 'del' to delete mistakes, it is probably because the system and you don't agree on what the erase character should be. If you see ^H when you try to erase characters, then your terminal is sending CTRL-H when you hit the delete key. To ensure the terminal behaves as you expect, you can specify in login
stty erase ^h
If you see ^? when you try to erase, this means your terminal is being sent DEL. You can use the following to tell the terminal to interpret DEL as erase
stty erase '^?'
Note: In the above command we have 'quoted' the command because of '?'s specially meaning in shell commands. Likewise, you could 'escape' the command by using stty erase ^\?
stty erase '^?'
noclobber - ensure that files are not accidentally destroyed
noglob - filename expansion is inhibited. Useful in shell scripts that are not dealing with filenames, or after a list of filenames has been obtained and further expansions are not desirable.
[ref: Using csh & tcsh, Paul DuBois (O'Reilly & Assoc, Beijing, 1995)]
The following are a number of useful command-line sequences I use or have come across on a regular basis.
[ref: Making friends with c-Shell and t-Shell]
One redirection that is often observed in startup scripts is redirecting the stderr to the same place that stdout is directed. One major value of this is to prevent error messages from coming up on the screen.
$ /path/binary > /dev/null 2>&1
Sends output of standard error (2) to the same place as standard out >&1,
which is, in this case, /dev/null. So in this scenario all error messages sent
to stderr (2) are sent to the same place as stdout (1) which is all thrown at
/dev/null.
The device /dev/null is the ultra trash bin that automatically shreds everything that goes to it, like a void black-hole.
This is useful in rc scripts where you do not want trash sent to the console, or where you can redirect output to a log file other than /dev/null. A very useful scenario for this type of redirection is sending the output and error messages from programs that generate large screens of information (like 'make').
e.g.
make > makelog 2>&1
From the man page sh(8)
| <& fd Standard input is duplicated
from file descriptor fd. fd can be a single digit, indicating the number
of an existing file descriptor; the letter `p', indicating the file descriptor
associated with the output of the current co-process; or the character `-',
indicating standard input is to be closed.
>& fd Same as <&, except the operation is done on standard output. |
From the man page csh(8)
| > name >! name >& name >&! name The file name is used as the standard output. If the file does not exist then it is created; if the file exists, it is truncated; its previous contents are lost. If the variable noclobber is set, then the file must not exist or be a character special file (e.g., a terminal or /dev/null) or an error results. This helps prevent accidental destruction of files. Here, the `!' forms can be used to suppress this check. The forms involving `&' route the standard error output into the specified file as well as the standard output. name is expanded in the same way as `<' input filenames are. |
As far as I can discover, there are two general tools for finding files on your system. One is the "/usr/bin/locate" program and the other is the gnu "/usr/bin/find". For security purposes, the database used by "locate" is generated (by /etc/weekly) with limited access privileges, so it does not have a complete list of all files on your system.
To use "locate" merely requires giving the name of the file you are looking for.
$ locate filename
The simplest use of "find" is listed here.
$ find . -name "filename" -print
find is told to search from the current directory "." look for files with the name "filename" and display (-print) a list of the results.
[ref: find info]
One advantage of the 'find' utility is its flexibility to launch processing activities on files it has found. A number of useful examples exist for this.
For example, to compare each C header file in the current directory with the file `/tmp/master':
find . -name '*.h' -exec diff -u '{}' /tmp/master ';'
-exec command ; 'find' takes all arguments after `-exec' to be part of the command until an argument consisting of `;' is reached. It replaces the string `{}' by the current file name being processed everywhere it occurs in the command. Both of these constructions need to be escaped (with a `\') or quoted to protect them from expansion by the shell. The command is executed in the directory in which 'find' was run.
You can use shell command substitution (backquotes) to process a list of arguments, like this:
grep -l sprintf `find $HOME -name '*.c' -print`
However, that method produces an error if the length of the `.c' file names exceeds the operating system's command-line length limit.
To run a command on more than one file at once, use the `xargs'
command. `xargs' avoids that problem by running the command as many times as
necessary without exceeding the limit:
find $HOME -name '*.c' -print | xargs grep -l sprintf
However, if the command needs to have its standard input be a terminal (`less', for example), you have to use the shell command substitution method.
`xargs' is invoked like this:
xargs [OPTION...] [COMMAND [INITIAL-ARGUMENTS]]
`xargs' reads arguments from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines. It executes the COMMAND (default is `/bin/echo') one or more times with any INITIAL-ARGUMENTS followed by arguments read from standard input. Blank lines on the standard input are ignored.
Instead of blank-delimited names, it is safer to use `find -print0' or `find -fprint0' and process the output by giving the `-0' or `--null' option to GNU `xargs', GNU `tar', GNU `cpio', or `perl'.
One of the common issues that comes up in some of my web installations is for files and directories be given different permission rights. Being lazy, I either did not do it, or used a shortcut approach that just made the whole thing insecure.
Find and change all php, php3 files to mode 554
$ find . -name "*.ph*" | xargs chmod 554
Find and change all directories to mode 711
$ find . -type d | xargs chmod 711
Another common problem for administrators connected with Windows clients, is the plethora of Windows files that get downloaded. Or, there may just be a set of files that you wish to delete that are easily identifiable by their extensions.
| $ find / -type f \( -iname '*.mp3' -or -iname '*.exe' -or -iname '*.wav' \) -exec rm '{}' ';' |
A more comprehensive example is the one-line following:
Sometimes it's just interesting to browse through your /etc/passwd file to see what user accounts are set up on your machine.
To quickly sort through what are system and ports created accounts, you can use sort(1)
$ sort -bn -k 3 -t : /etc/passwd
In our above command-line we've asked sort to parse /etc/passwd with the following
-bn : ignore leading blanks, and sort as numeric
-k 3 : key field 3 is where we want to sort
-t : the field separator is the ":" colon
This essentially sorts the /etc/passwd file by userid, in which case a standard installation will sort the OS Installed userids first, then ports, then standard users, and then finally the nobody account.
The use of alias' can be great, they shorten the typing but they can also be forgotten so you type in a command you are used to using, and get an output not exactly as you expected.
You can turn off, or temporarily override the use of alias in the following manner:
| $ alias ls ls -al |
| $ \ls |
The 'escape' before the command-line forces the command to be executed directly, without use of the environment. Likewise you can also permenantly remove the alias attribute by doing:
| $ alias ls |
[ref: bzip2(1), gzip(1), tar(1)]
One of the more common things that I'm coming across is the need to compress, decompress tar'd files. One item to note is that if you have some tar'd files from Linux, it may not be POSIX compatible in which case you may need to install the GNU tar program.
There are a myriad of tools used in creating compressed files, but here I will deal with the common commandlines used.
The standard 'tar' program supports streaming the data together (archiving in the 'tar' format) and then compressing the data using 'z' gzip, or 'Z' compress.
For example:
| $ tar -czf archive.tgz files |
The above command will 'c' create the 'f' file 'archive.tgz' which is a 'tar' file that is compressed using gzip. The contents of archive.tgz are brought from 'files' which is either a list of different files or directories.
A compression method generally considered to generate smaller files (block zip2) can be used in a two step process. First we create the tar archive and then we can use the compression program bzip2.
| $ tar -cf archive.tar |
| $ bzip2 -c archive.tar > archive.tbz2 |
By far the most common activity I've had is to uncompress software distributions. 'tar' is generally good enough to complete most of these requirements.
gz, tgz: In most cases you will download tar/compressed files compressed using the 'z' gzip format. A direct untar, decompression method is:
| $ tar -xzf archive.tgz |
Those used to the two step process, may be more used to the following command-line.
| $ gunzip -c archive.tgz | tar -xf - |
bz2, tbz2: When you come across a bzip2 compressed file, then we can use the above methodology, adapted to bunzip2.
| $ bunzip2 -c archive.tbz2 | tar -xf - |
| $ bunzip2 -c archive.tar.bz2 | tar -xf - |
A few shell prompts of interest that I've seen on the 'Net include:
| PS1='\[\033[1;30m\]\u@\h:\w \$\[\033[0m\] ' |
| PS1='\[\033[1;30m\]\u@\h:./\W \$\[\033[0m\] ' |
Copyright (c) 2000/1/2 Samiuela LV Taufa. All Rights Reserved.
I reserve the right to be totally incorrect even at the best advice of betters. In other words, I'm probably wrong in enough places for you to call me an idiot, but don't 'cause you'll hurt my sensibilities, just tell me where I went wrong and I'll try again.
You are permitted and encouraged to use this guide for fun or for profit as you see fit. If you republish this work in what-ever form, it would be nice (though not enforceable) to be credited.
|
sh - The Basic, 1st Shell |
Copyright © 2000/1/2 NoMoa.COM All rights reserved.