<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="/stylesheet.xsl"?>

<page	name="Linux Commands"
	author="Hugh Sparks"
	email="hugh@csparks.com"
	date="February 6, 2012"
	url="http://www.csparks.com/LinuxCommands.xhtml"
	copyright="All rights reserved"
	xmlns="http://www.csparks.com/XMLWithoutTears"
>

	<p>
	I use these notes to remember various Linux commands and procedures.
	When I learn something new, a section gets appended to the document.
	Maybe you will find something useful. I appreciate hearing about errors.
	</p>

<contents name="Topics"></contents>

<!-- ********************************************************************* -->
<s name="Other cheat sheets">
	<p>
	Making a Linux cheat sheet is a popular activity. The following link
	will give you an up-to-date list:<cr/>
	<link
		name="Search for Linux cheat sheets"
		url="http://www.google.com/search?q=%22Linux+cheatsheet%22+OR+%22linux+cheat+sheet%22"
	/>
	</p>
</s>

<s name="Some usage hints">
	<p>
	If you know where you want to go, you can enter the section name
	as part of the browser URL. The browser will adjust the view
	to show the proper part of the document. Example:
	</p>
	
	<code><![CDATA[
	http://www.csparks.com/LinuxCommands.xhtml#Audio ]]></code>
	
	<p>
	If you want to display, print, or link to a section as 
	a stand-alone document (no other sections will be shown) 
	you can use:
	</p>
	
	<code><![CDATA[
	http://www.csparks.com/LinuxCommands.xhtml?section=Audio ]]></code>
	
</s>

<!-- ********************************************************************* -->
<s name="Apache">
<!-- ********************************************************************* -->

<sc name="Create and configure virtual hosts"><![CDATA[
	In /etc/httpd/conf/httpd.conf
	
	NameVirtualHost *
	
	For each host:
	
	<VirtualHost *>
		ServerName myHost.myDomain.com
		DocumentRoot /var/www/html/myDirectory
	</VirtualHost>

	You must have a CNAME entry for myHost in your
	zone file or a definition for myHost.myDomain.com
	in your /etc/hosts file.  ]]></sc>

<sc name="Configure Apache for XML"><![CDATA[
	Netscape won't display xml documents unless the associated xsl file
	is served with the appropriate mime type (text/xml or application/xml)
	This can be set in Apache by editing /etc/httpd/conf/srm.conf and
	adding two AddType directives:

	AddType application/xml .xml
	AddType application/xml .xsl ]]></sc>

<sc name="Typical changes to the httpd.conf file"><![CDATA[
	ServerName www.csparks.com
	ServerAdmin hugh@csparks.com ]]></sc>

<sc name="Talk to a web server with telnet"><![CDATA[
	telnet some.server.com 80
	GET /whatever.html HTTP/1.1
	host: your.host.com
	<enter another LF>  ]]></sc>

<sc name="Apache security"><![CDATA[
	The server will accept or reject requests based on rules.
	The rules can be categorized by what part of the request
	they examine:

	Access: 
		Access rules discriminate based on the IP number of the client.

	Authentication:  
		Authentication rules discriminate based on a username and
		password supplied by the client.

	Authorization: 
		One a client has passed the access and authentication
		barriers, authorization rules determine what the client
		is allowed to do.

	Limits:
		Limit rules apply different authorization rules depending
		on the request type.

	A common cause of confusion is that Apache sets up defaults for access 
	and authentication as well as rules that control arbitration between them. 
	If these rules are not explicitly stated in your sections, it's impossible 
	to understand how the directives work or why things don't work the way 
	you expect. 

	To diagnose access problems:
	
		tail -f /var/log/httpd/error_log ]]></sc>

<sc name="Basic authentication"><![CDATA[
	Basic authentication sends clear text passwords
	over the web, so it's not safe to use by itself.
	It can be used securely over SSL (https://) connections.
	There is a trend among "user friendly" operating systems to
	bully users into avoiding basic authentication over unsecure
	channels.

	Authentication directives are used inside Directory or Location sections:
	Example:
	
	<Directory /var/www/html/privateStuff>
		AuthType Basic
		AuthUserFile /etc/httpd/users.htpasswd
		AuthName "Access to private stuff is restricted"
		require valid-user
	</Directory>

	The AuthName message gets displayed by the client's browser
	when it pops up a dialog window requesting the username and password.

	The directive "Require valid-user" allows access to 
	anyone who appears in the htpasswd file. Alternatively,
	you can allow access for selected users:

		require user bevis mary 

	Creating a password file:
	
		htpasswd -c /etc/httpd/users.htpasswd aUserName
		
		The program will prompt for the password.
		The password file SHOULD NOT be located under 
		any Directory section controlled by the server.
		
	Adding a user to the password file:
	
		htpasswd /etc/httpd/users.htpasswd aUserName
		
		The program will prompt for the password.
	
	Deleting a user from the password file:
	
		htpasswd -D /etc/httpd/users.htpasswd aUserName ]]></sc>
		
<sc name="Digest authentication"><![CDATA[
	Digest authentication uses encryption, so it's a better choice
	for regular http:// access.

	Digest directives can be added to Location or Directory sections.
	For a Location:

	<Location /thisLocation>
		AuthType Digest
		AuthName Administrators 
		AuthUserFile /etc/httpd/users.htdigest
		AuthDigestDomain /thisLocation /someOtherLocation ...
		require valid-user
	</Location>

	The AuthName has a specialized meaning here: it names a "realm".
	Realms are an abstraction used to group one or more locations
	on the server you want to protect as a unit.

	Each line in the AuthUserFile contains a username, password, and
	realm name. This allows the administrator to have one AuthUserFile
	for all the authentication rules. 
	
	Realms control access to the path named in the Location
	directive and all "sub paths" relative to that location:
	In the example above, a path such as "/thisLocation/here" is also
	part of the realm.
	
	Most browsers allow users to "Remember my password" when they
	are prompted to enter credentials. The AuthDigestDomain directive 
	lists other paths protected by the same credientials so the user
	won't have to enter them again. The browser quietly submits the
	previously used credentials when any of the other paths are used.

	To construct the parameter list for AuthDigestDomain, simply
	list all the path expressions used in Location and Directory 
	sections names that have the same realm.

	Creating an digest password file:
	
		htdigest -c /etc/httpd/users.htdigest aRealm aUserName
		
	Adding a user to the password file:
	
		htdigest /etc/httpd/users.htpasswd aRealm aUserName
		
		The program will prompt for the password.
	
	Deleting a user:

		The htdigest command doesn't have a delete option.
		Just edit the file and delete the line with the
		username you want to remove. ]]></sc>

<sc name="Using groups"><![CDATA[
	Groups allow you to define sets of users.
	They can be used with any authentication type.
 
	To use a group called "slackers", add these directives:
		
		Require group slackers
		AuthGroupFile /etc/httpd/users.htgroups
		
	In this example, a user must authenticate as usual
	and in addition belong to the group "slackers"
			
	The file users.htgroups may define any number of
	groups and the users who belong to them. Each line
	in the file begins with a group name followed by the
	user names that belong: 
		
		administrators: fred kevin jane
		slackers: judy steve 

	As with other authentication data files, it's best to keep 
	the groups file out of the server's Directory scope. ]]></sc>

<sc name="Access control"><![CDATA[
	Individual ip addresses:

		Allow from 192.168.2.3
		Deny from 192.168.2.4

	Subnet expressions - These two directives are equivalent:

		Allow from 192.168.1.0/255.255.255.0
		Allow from 192.168.1.0/24

	The order in which allow and deny test are applied is
	important. There are two choices and they alter the
	way Allow and Deny directives are interpreted:

	Order allow,deny

		Initial state is "Deny from all".
		Process the allow conditions
			If access is not allowed, access is forbidden.
			If access is allowed proceed to:
		Process the deny conditions 
			If access is denied, access is forbidden.
			If access is not denyed, access is allowed.

	Order deny,allow

		Initial state is "Allow from all".
		Process the deny conditions.
			If access is not denyed, access is allowed.
			If access is denied, proceed to:
		Process the allow conditions.
			If any succeeds, access is allowed,
			otherwise access is forbidden.

	Common idioms

	Allow all ip addresses:

		Order allow,deny
		Allow from all

	Don't allow anyone:

		Order deny,allow
		Deny from all

	Allow only one subnet:

		Order deny,allow
		Deny from all
		Allow from 192.168.1.0/24 

	Allow only specified clients:

		Order allow,deny
		Allow from 192.168.1.2 192.168.1.3 

	Allow only one subnet and exclude one of those clients:

		Order allow,deny
		Allow from 192.168.1.0/24
		Deny from 192.168.1.7 ]]></sc>

<sc name="Combine access control and authorization"><![CDATA[
	Access and authorization directives are always in effect. 
	They may be specified explicity in sections or inherited 
	from the top level server configuration.

	The "Satisfy" directive determines how they are combined:

	Satisfy all

		Clients must pass access AND authentication control.

	Satisfy any

		Clients must pass access OR authentication control.

	Common idioms:

	Allow local LAN users without authentication but require 
	authentication from all others:

		Satisfy any
		Order deny,allow
		Deny from all
		Allow from 192.168.1.0/24
		AuthType Basic
		AuthName "Special area"
		AuthUserFile /etc/httpd/users.htpasswd
		Require valid-user

	Require everyone to authenticate:

		Satisfy all
		Order allow,deny
		Allow from all
		AuthType Basic
		AuthName "Special area"
		AuthUserFile /etc/httpd/users.htpasswd 
		Require valid-user 

	Allow users from only one subnet and they must authenticate:

		Satisfy All
		Order deny,allow
		Deny from all
		Allow from 192.168.1.0/24
		AuthType Basic
		AuthName "Special area"
		AuthUserFile /etc/httpd/useres.htpasswd
		Require valid-user ]]></sc>

<sc name="Use different rules for different request types"><![CDATA[
	The Limit directives allow the server to apply
	different rules depending on the type of request.
	(Sometimes called the "request method")

	The following example lets everyone read the site,	
	but restricts writing to authorized users:

		! Allow access from any ip
		Order allow,deny
		Allow from all

		! Setup authentication by password
		AuthType Basic
		AuthName "Special area"
		AuthUserFile /etc/httpd/users.htpasswd 
		Require valid-user

		! Decide how to combine authentication and access
		! rules based on the request type:

		<Limit GET PROPFIND OPTIONS REPORT>
			! Let anyone read
			Satisfy Any
		</Limit>
		<LimitExcept GET PROPFIND OPTIONS REPORT>
			! All other requests need authentication
			Satisfy All
		</LimitExcept>  ]]></sc>

<sc name="Prevent recursion in rewrite rules"><![CDATA[
	In this example, files that end with ".xml" or ".mml"
	are rewritten to find them in the "mxyzptlk" directory:
	
		RewriteEngine on
		RewriteCond %{REQUEST_URI} !(^/mxyzptlk/.*)
		RewriteRule (.*)\.(xml|mml)$ mxyzptlk$1.$2 [P]
		
	Using these rules, the client browser will show the orignal
	URL in the address display, not the rewritten version. ]]></sc>
	
<sc name="Test the validity of the httpd.conf file"><![CDATA[
	apachectl configtest ]]></sc>

<sc name="Clean up semaphores so Apache will restart"><![CDATA[
	This command will fix the following reported error:

		"...No space left on device: mod_python: Failed to create global mutex..."

	ipcrm sem `ipcs -s | grep apache | cut -d' ' -f2` ]]></sc>

<sc name="Enable Windows XP WebDAV access"><![CDATA[
	Getting apache to serve WebDAV content to Windows XP is
	notoriously difficult. See if you like this method:

	First, you need a lock file.
	On linux this could be:

		DAVLockDB /var/lib/dav/DavLock

	If you're running apache on Windows, you might use:

		DAVLockDB var/DavLock

	The "var" directory in the Windows case is a directory 
	you create in the Apache installation root directory.

	Add a Location section to the virtual host you want to
	make accessible. This configuration lets everyone read,
	but only authenticated users can write:

 	<VirtualHost *:80>
                ServerName www.yourPlace.com
                DocumentRoot /var/www/html
                <Location / >
                        DAV on
                        AuthType Digest
                        AuthName "yourRealm"
                        AuthUserFile /etc/httpd/davusers.digest
                        <LimitExcept GET HEAD OPTIONS>
                                Require valid-user
                        </LimitExcept>
                </Location>
        </VirtualHost>

	Create the digest authentication file:

	htdigest -c /etc/httpd/davusers.digest "yourRealm" yourUserName

	You will get a prompt for a password and the file will be created.
	Adding more users to the realm is similar, but leave out the -c 
	switch, which creates a new file erasing the old one. As the
	syntax suggests, htdigest can store many users with multiple
	realms all in the same file.

	On the Windows XP side, open "My Network Places" and double-click
	"Add Network Place". Hit "Next", then select "Choose another network
	location" and hit "Next" again. Enter a url for the virtual host in
	this form:

		http://www.yourPlace.com:80
	
	The wizard will grind away and then prompt for the username, password,
	and a name for the shortcut. The new shortcut will be added to 
	the "My Network Places" folder. Note the appended port number: It is
	important. It somehow short-circuits Microsoft's attempt to 
	discourage the use of the WebDAV protocol.]]></sc>

<sc name="Enable Windows XP WebDAV access using SSL"><![CDATA[
	This is a better method but it depends on having SSL
	configured on your server. Other than the aggravation
	of buying and configuring a certificate, this method
	seems to make Windows behave better - There are no more
	mysterious recursive directories and the protocol is 
	easier to specify. This configuration grants full 
	access to those who authenticate and no access to others:

	Alias /webdav  /var/www/webdav

	<Location /webdav >
		DAV on
		Satisfy all
		Order deny,allow
		Allow from all
		AuthType Digest
		AuthName "webdav"
		AuthDigestDomain /webdav
		AuthUserFile davusers.digest
		Require valid-user
		SSLRequireSSL
	</Location>

	Configure the digest file as described in the previous section.
	When you specify the url on the Windows side, you don't need
	the port number mumbo-jumbo:

		https://www.yourPlace.com/webdav

	Clearly, the SSL certificate must be created to exactly 
	match the server name. You can also use this method inside
	a virtual host if the name matches the certificate. 

	A word about AuthDigestDomain: the list of parameters consists
	of path expressions used in all Location directives that
	are protected by the same realm. For example if you used
	the "webdav" realm to protect the location /webdav as shown
	above and another location /website, the two locations
	should look like this:

	<Location /webdav >
		DAV on
		...
		AuthName "webdav"
		AuthDigestDomain /webdav /website
		...
	</Location>

	<Location /website >
		DAV on
		...
		AuthName "webdav"
		AuthDigestDomain /webdav /website
		...
	</Location>

	Windows XP and Vista clients need a patch to fix webdav
	bugs. (This is still true for XP SP3 and Vista SP1.) ]]></sc>

	<p indent="4">
	<link name="XP and Vista WebDAV Patch"
	url="http://www.microsoft.com/downloads/details.aspx?FamilyId=17C36612-632E-4C04-9382-987622ED1D64"/>
	</p>
</s>

<!-- ********************************************************************* -->
<s name="Backups">
<!-- ********************************************************************* -->

<sc name="Backup linux volumes"><![CDATA[
	Normal unix-to-unix with locally mounted paths:

		rsync -ax --numeric-ids --delete sourceDir/ destDir

	The trailing / on the sourceDir is very important:
	It means copy the contents of sourceDir into destDir,
	rather than copying the sourceDir itself. 

	If you have ssh setup from the source to the destination machine,
	backups are fast and easy to do over the network.

	If you can do this successfully: (See the SSH section in this document.)

		ssh user@remote.com

	Then you can do this:

		rsync -ax -e ssh --delete sourceDir/ user@remote.com:/path/to/sourceDir 

	Note that the /path/to/sourceDir is the path as seen on the remote machine.
	You can also pull data from a remote machine by reversing the source and
	destination parameters. 

	You can also rsync to or from network mounts via nfs or samba.
	If you rsync between linux and windows machines using samba, 
	all sorts of permission and symbolic link problems are likely.]]></sc>

<sc name="Backup NTFS or SMB volumes"><![CDATA[
	
	Backup to a vfat or smb filesystem using only time attribute:
	(Pulling from the linux side.)

		rsync -a --delete --exclude-from="excludeNT.txt" \
			sourceDir/ destDir
	
	The excludeNT.txt file contains the names of files that should
	not be copied. They are locked system files that will cause error
	messages if not excluded during the backup:

	excludeNT.txt:
		ntuser.dat
		NTUSER.dat
		ntuser.dat.LOG
		NTUSER.DAT.LOG
		UsrClass.dat
		UsrClass.dat.LOG
		hiberfil.sys
		pagefile.sys 

	Other applications running on Windows may lock files.
	By observing the messages from rsync you can add to
	the list and achieve a quiet backup. ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Archives">
<!-- ********************************************************************* -->

<sc name="Tar commands"><![CDATA[
	tar czf arch.tgz path	# Make an archive (Add v for verbose)
	tar xzf arch.tgz 	# Restore an archive (Add v for verbose)
	tar tf arch.tar		# List an archive (must not be gziped)
	
	Other tar options
	
	-C directory		# Change to this directory first
	-T fileList		# Use this list of  file names
	--same-owner		# Keep original owner when extracting
	--same-permissions	# Keep original permissions when extracting
	--absolute-paths	# Don't strip leading /
	--directory dirPath	# Change to this directory first
	--files-from=fileList	# Get file names from another file ]]></sc>
	
<sc name="Gzip a file or directory"><![CDATA[
	gzip file
	gunzip file.gz ]]></sc>

<sc name="Zip a file or directory"><![CDATA[
	zip -r archive.zip files...
	unzip archive.zip ]]></sc>

<sc name="Cpio options"><![CDATA[
	Mode of operation is one of "pio":
	p	Pass files through without using an archive file
	i	Extract from an archive
	o	Create an archive
	
	Other common options:
	t	List the contents of the archive
	m	Preserve modification times 
	d	Create directories as needed
	u	Overwrite files without warnings ]]></sc>

<sc name="Extract files from a cpio archive, create directories as needed"><![CDATA[
	cpio -mid < archive.cpio ]]></sc>

<sc name="Check for absolute file names in cpio archives"><![CDATA[
	List the archive to see if it has absolute names.
	Use --no-absolute-filenames if necessary.
	This doesn't happen very often, but if it does and
	you are root a Bad Thing (tm) can happen. ]]></sc>

<sc name="List a cpio archive"><![CDATA[
	cpio -t < archive.cpio ]]></sc>

<sc name="Use cpio to copy everyting in current dir to targetDir"><![CDATA[
	Includes invisible dot files. Preserves all dates.
	
	find . | cpio -pudm targetDir 

	On modern Linux systems "cp -a" will do the same thing. ]]></sc>

<sc name="Create a cpio archive from a list of files in current directory"><![CDATA[
	find . | cpio -o > archive.cpio ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Audio">
<!-- ********************************************************************* -->

<sc name="Play samples from a file"><![CDATA[
	play test.wav ]]></sc>

<sc name="Use 'play' on systems with artsd (such as kde)"><![CDATA[
	On these systems, /dev/dsp is always tied up by artsd.
	Use the artsdsp command to run any program that would 
	normally access /dev/dsp directly:
 
		artsdsp play test.wav ]]></sc>
	
<sc name="Record samples to a wav file"><![CDATA[
	Record a "normal" stereo wav file:
	
	rec -c 2 -f U -r 44100 -s w -v 8.0 test.wav
	
	Options:
	
	-c 2		Two channels (stereo)
	-r 44100	Sample rate
	-f	Sample encoding:
	 	s	Signed linear (2's compliment)
	 	u	Unsigned linear
	 	U	U-law (logarithmic) U.S. standard
	 	A	A-law (logarithmic) EU. standard
	 	a	ADPCM (Adaptive Differential Pulse-Code Modulation)
	 	i	IMA_ADPCM
	 	g	GSM
	-s	Sample size:
	 	b	8 bit bytes
	 	w	16 bit words
	 	l	32 bit long words
	 	f	32 bit floats
		d	64 bit floats
	 	D	80 bit IEEE floats
	-t	File format:
		au	Sun
	 	cdr	CD track
	 	gsm	GSM 06.10 Lossy Speech Compression
		wav	Windows RIFF (Header contains all params)
	-v	Set the volume
		1.0	No change
		2.0	Linear increase by 2.0
		0.5	Linear decrease by 2.0
		8.0	About right to balance with other .wavs
		
	The file format can be specified by giving the file
	a matching extension.
	
	ADPCM, IMA_ADPCM & GSM are intended for speech compression.
	U-law would be appropriate for music. ]]></sc>

<sc name="Play sounds concurrently"><![CDATA[
	esdplay
	
	(Some people make this an alias for 'play') ]]></sc>

<sc name="Reroute microphone through esd"><![CDATA[
	esdrec | esdcat ]]></sc>

<sc name="Play an mp3 file"><![CDATA[
	mpg123 yourfile.mp3 ]]></sc>
	
<sc name="Convert an mp3 file to a wav "><![CDATA[
	First run:

		mpg123 -s yourfile.mpg > yourfile.raw

	The above command will display the sample rate and the number
	of channels. (Mono or Stereo)

	The output is 16 bit, signed pcm, little endian. No header.
	
		sox -c 2 -w -s -r xxx yourfile.raw yourfile.wav

	The xxx value must be the sample rate displayed by mpg123.
	You can pipeline mpg123 into sox. Use a - for the sox input.
	
	An easier way to do both steps:
	
		lame --decode yourfile.mp3 yourfile.wav ]]></sc>

<sc name="Use sox to play (almost) any sound file"><![CDATA[
	sox inputOptions inputFile outputOptions outputFile

	Do a "man soxexam" to see many examples.
	
	Format options
	
	Channels
		-c n	Where n = 1,2 or 4
	Sample rate
		-r rate	Where rate is in Hertz
	Sample size
		-b	 8 bits
		-w	16 bits
		-l	32 bits
	Encoding
		-s	Signed linear
		-u	Unsigned linear
		-U	U-law (U.S. logarithmic)
		-A	A-law (Euro logarithmic)
		-a	ADPCM (Adaptive pulse-code modulation)
		-i	IMA_ADPCM
		-g	GSM
		-f	Floating point
	Input file format is controled by the file extension:
		.wav	(You don't need to specify other options)
		.au	(Options may or may not be needed) ]]></sc>
	
<sc name="Convert a wav to an mp3"><![CDATA[
	lame [-b bitrate] infile.wav outfile.mp3 ]]></sc>

<sc name="Resample an mp3"><![CDATA[
	lame [-b newbitrate] --mp3input oldfile.mp3 newfile.mp3 ]]></sc>

<sc name="Rip the audio from a video with ffmpeg"><![CDATA[
	ffmpeg -i myVideo.flv -ab 128k myAudio.mp3 ]]></sc>

<sc name="Rip the audio from a video with mplayer"><![CDATA[
	mplayer -novideo -ao pcm:file=result.wav source.avi ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Bash">
<!-- ********************************************************************* -->

<sc name="Variables"><![CDATA[
	Variables are created by assignement:
		
		strVar='This is a string'
		numVar=123

	They are referenced using the dollar prefix:
		
		newVar=$oldVar

	Concatenation of strings is implied:

		newVar='This is ' $oldVar

	Note: Spaces are not allowed around the = symbol. 

	Undefining variables:

		unset myVar ]]></sc>

<sc name="Using command results as a parameter"><![CDATA[
	Enclose the command in back-quotes:
	Example: getting the size of a directory
	
	dirSize=`du -s myDirectory | awk '{print $1}'` ]]></sc>

<sc name="Picking out the nth element of a string"><![CDATA[
	The string should be pipelined to this command:
	
	awk '{print $n}' 

	Example:

	SIZE=`du -s -k myPath/myDir | awk '{print $1}'`
	if [$SIZE -gt 4096]; then
		echo "The directory myDir contains more than 4096kb"
	fi ]]></sc>
		
<sc name="Picking out the nTh element from multi-line text"><![CDATA[
	This example returns the free memory of the machine, which
	appears in the middle of the second line of /proc/meminfo.
	Note the escapes required on nested quotes:
	
	sh -c 'echo $4' `cat /proc/meminfo` ]]></sc>

<sc name="Picking out the nTh line of a file"><![CDATA[
	awk "NR=123 {print;exit}" myfile.txt ]]></sc>

<sc name="Inline file creation"><![CDATA[
	cat > myPath/myFile <<- 'EOF'
		line1
		line2
		...
		lineN
	EOF ]]></sc>

<sc name="Predicates used on path names"><![CDATA[
	-d  Is a directory
	-e  Exists
	-f  Is a regular file
	-h  Is a symbolic link
	-r  Is readable
	-s  Size is > 0
	-w  Is writable
	-x  Is executable

	Example:

	if [ -e <path> ] ; then
		# Do this if file exists
	fi 

	if [ ! -d <path> ] ; then
		# Do this if it's not a directory
	fi ]]></sc>

<sc name="String predicates"><![CDATA[
	-z <astring>	# Length of string is zero
	-n <astring>	# Length of string is non-zero ]]></sc>

<sc name="Infix file predicates"><![CDATA[
	-nt  Newer than. Or file1 exists and file2 does not.
	-ot  Older than. Or file2 exists and file1 does not. 

	if [ <file1> -nt <file2> ] ; then
		Do this if file1 is newer than file2 (or file2 does not exist)
	fi ]]></sc>

<sc name="String infix operators"><![CDATA[
	=, !=, <, > ]]></sc>

<sc name="Numerical infix operators"><![CDATA[
	-eq, -ne, -lt, -le, -gt, -ge ]]></sc>
		
<sc name="Logical connectives"><![CDATA[
	NOT prefix operator: !
	AND operator: &&
	OR operator: || ]]></sc>

<sc name="Control structures"><![CDATA[
	If-then-else:

		if [ -e $pathname ] ;  then
			# It exists
		elif [ -e $thatname ] ; then
			# That exists
		elif [ -e $theOther ] ; then
			# The other exits
		else
			# They don't
		fi
	
	Iteration:

		myDirs="dev etc bin proc mnt tmp var lib"

		for dir in $myDirs ; do
			mkdir $targetRoot/$dir
			chmod u=rwx,og=rx $targetRoot/$dir
		done

		for i in 121 19 34 56 78; do
			echo $i
		done

		for i in `seq 1 10`; do
			echo $i
		done

		for ((i=1; i<=10; i+=1)) ; do
			echo $i
		done

		line="&test1=a1&test2=a2"

		while [ $line != "" ]; do
			a1=`echo $line | sed -e 's/.*&//'`
			line=`echo $line | sed -e "s/&"$a1"//"`
			echo $a1	
		done

		count=10
		until [ $count -lt 1 ]; do
			echo $count
			let count=count-1
		done ]]></sc>

<sc name="Script or function parameters"><![CDATA[
	$0              Name of the script or function
	$1 ... $n       Each parameter
	$@              All parameters starting with $1
	$#		Number of parameters
	$?		Exit status of last bash command
	
	To shift all parameters left by 1: $1=$2, $2=$3 etc:

		shift 1 

	You can shift by any positive n. ]]></sc> 

<sc name="User-defined functions"><![CDATA[
	Local functions work like shell scripts.
	The have their own $0..$n  parameters:

	function demo	
	{	echo Function: $0
		echo Param 1: $1
		shift 1
		for i in $@ ; do
			echo Arg: $i
		done
	}

	demo special 123 456 789

	Historical note: Instead of "function demo" to start a
	function definition, the form "demo()" is allowed.
	This notation confounds the unwashed because they wish 
	they could put a formal parameter list inside the ()s. ]]></sc>

<sc name="Exit status"><![CDATA[
	Every bash script or function returns a numerical status.
	A non-zero status denotes failure. 
	
	To exit a script immediately and return failure:
	
		exit 1

	To exit with success:

		exit 0

	If the script runs off the end, "exit 0" is implied. ]]></sc>

<sc name="Checking for expected number of parameters"><![CDATA[
	if [ $# -eq 3 ] ; then
		echo Usage: $0 arg1 arg2 arg3
		exit 1	
	fi ]]></sc>

<sc name="Process command line arguments in a script"><![CDATA[
	while [ $# -gt 0 ] ; do
		echo $1
		shift
	done ]]></sc>

<sc name="Process each line in a file"><![CDATA[
	for line in `cat myfile.txt`; do
		echo $line
	done ]]></sc>

<sc name="Using a prompt menu in a script"><![CDATA[
	select opt in "Hello Goodby"; do
		if [ $opt = "Hello" ]; then
			echo Hello there!
		elif [ $opt = "Goodby" ]; then
			echo done
			exit
		else
			clear
			echo Try again...
		fi
	done ]]></sc>

<sc name="Using read/write and file descriptors"><![CDATA[
	exec 3< MyFile.txt
	while [ ! $done ] ; do
		read <&3 myline
		if [ $? != 0 ]; then
			done=1
			continue
		fi
		echo $myline
	done ]]></sc>

<sc name="Redirecting command output"><![CDATA[
	Redirecting selected streams to a file:

		1>	stdout
		2>	stderr
		&>	both stdout and stderr

	Add stderr to stdout for subsequent redirection

		2>&1	combines stderr with stdout

	Examples: Assume the current directory contains a file:

		exists

	And assume that this file does not exist:

		nosuch

	A command that partly succeeds:

		ls -l exists nosuch

		Console will show the exists listing and an error about nosuch.

	Send stdout to a file: 
	
		ls -l exists nosuch > Demo

		Console shows exists listing and error about nosuch.
		Demo contains only the exists listing.

	Send stderr to a file:

		ls -l exists nosuch  2> Demo

		Console shows only the exists listing.
		Demo contains only the error message about nosuch.

	Add stderr to stdout and redirect to a file:

		ls -l exists nosuch 2>&1 1> Demo

		Console shows the error about nosuch.
		Demo contains only the exists listing.
		Note the precidence:
		First stdout goes to Demo.
		Then stderr replaces stdout and goes to the console.

	Add stderr to stdout and pipeline result to another program:

		ls exists nosuch 2>&1 | grep exists

	Add stderr to stdout and ignore stdout:

		ls -l exists nosuch 2>&1 1> /dev/null

		Console will still show stderr.
		This form is often used to discard information about
		normal command execution from a script.

	Combine all outputs and send to null:

		ls -l exists.txt nosuch.txt &> /dev/null

	The last example is often used to quiet down scripts. ]]></sc>

<sc name="Arithmetic"><![CDATA[
	The "exper" command evalutes a string as an arithmetic expression:

		expr 2 + 3
		expr 12 / 4
		expr 14 % 3  

	Note that expr requires spaces between operands and operators.

	Parenthesis and "*" must be escaped:

		expr 5 \* \(3 + 2\)

	A somewhat neater way:

		echo $[2*3+1]

	Using the $[...] construct, nothing needs to be escaped.

	The "let" command evalutaes the right side:

		let a=4+6

	This is equivalent to:

		a=expr 4 + 6

	Spaces are not allowed in "let" expressions.
	Parenthesis must be escaped, but not "*":

		let p=5*\(3+2\)

	Again, it's easier to forget about the escapes and use:

		let p=$[5*(3+2)]

	Use "bc" for floating point computation

		echo 45.3/2 | bc -l

	The trailing -l (lower case L) loads the floating point library 

		x=`echo 99.0/3.14 | bc -l`
		y=`echo 14.2 + 11 | bc -l`
		echo $x + $y | bc -l

	Base conversions

		echo "obase=16; 1234" | bc

	Select decimal places for result

		echo "scale=3; 1/3" | bc

	You don't need to use the -l if you set the scale > 0

		echo "scale=3; 7/2" | bc
		echo "scale=0; 7/2" | bc 

	Show how long a bc calculation takes (p to 1000 places)

		time echo "scale=1000; 4*a(1)" | bc -l -q ]]></sc>

<sc name="Formatting with printf"><![CDATA[
	Leading zeros:

		printf "%04d\n" 3

	Hex
		printf "%x\n" 23
	
	All the usual suspects...  ]]></sc>

<sc name="Alias commands"><![CDATA[
	An alias is a type of macro:

		alias name='expression'

	It is often used to "improve" shell commands.
	For example, to make the rm command ask for confirmation:

		alias rm="rm -i"

	By convention, aliases are defined in a hidden file
	in the users home directory named ".bashrc".

	You can display an alias defintion using:

		alias myName

	To remove an alias:

		unalias name ]]></sc>

<sc name="Exporting variables"><![CDATA[
	Variables defined inside a shell script are only 
	visible inside that script unless they are exported.
	Exporting a variable makes it visible to external
	scripts called from inside the parent script.

	To export one more more variables:

		export var1 ... varn

	Assignment and export can be combined:

		export var1=expression1 ... varn=expressionN ]]></sc>

<sc name="Pulling up exported variables"><![CDATA[
	When a parent script call a sub-script, variables exported
	by the sub-script are not visible in the parent. The parent
	can make them visible by using the "source" command:

		source myScript.sh

	There is a commonly used shorthand for this:

		. myScript.sh

	Note the space after the dot. 

	For example if you edit your login script ".bash_profile"
	and add some exported variables, you can make them visible
	(without loging out and back in) by executing:

		source .bash_profile ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Basics">
<!-- ********************************************************************* -->

<sc name="Files and directories"><![CDATA[
	ls                # Show current directory contents
	ls -l $path       # Show details about the file or directory
	ls -d $path       # List directory names instead of contents
	cd $dir           # Change current directory to $dir
	cd ..             # Change current directory to parent directory
	pwd               # Show current directory path
	mkdir $dir        # Create a directory
	cp $src(s) $dst   # Copy $src file(s) to $dst
	cp $src(s) $dir   # Copy $src file(s) into the directory $dir
	mv $src $dst      # Move $src to $dst. Also used to rename files.
	mv $src(s) $dir   # Move a group of files into a directory
	rm $file(s)       # Remove (delete) files
	rmdir $dir(s)     # Delete empty directory(s)
	rm -rf $dirs(s)   # Delete files and/or directory(s) with their contents 
	> $file           # Erase the contents of a file ]]></sc>

<sc name="Copy a hierarchical directory and preserve all attributes"><![CDATA[
	cp -a $sourceDir $destDir]]></sc>

<sc name="Backup a hierarchical directory"><![CDATA[
	rsync -a --delete $sourceDir $destDir
	
	1) Sym links, ownership, permissions and hidden files are copied.
	2) A trailing "/" on either dir means "contents of".
	3) Only the files that need to be copied get copied.
	4) Files in the destDir but not in source are deleted. ]]></sc>

<sc name="Change the owner of a file"><![CDATA[
	chown owner file         # owner only
	chown owner.group file   # owner & group
	chown .group file        # group only
	chown owner. file        # owner & group=owner]]></sc>

<sc name="Change the permissions of a file"><![CDATA[
	chmod changes fileName
	
	The changes are a comma separated list of expressions.
	Each expression is of the form:
	
		users+permissions	# Add permissions
		users-permissions	# Remove permissions
		users=permissions	# Set exactly these permissions
	
	The users can be one or more of the letters:
	
		u	User  	(Oner of the file)
		g	Group 	(Group of users)
		o	Others	(Everyone else)
		OR:
		a	All	(Same as "ugo", the default)
		
	The permissions can be one or more of the letters:
	
		r	Read
		w	Write	
		x	Execute
		
	The user classes are specified in the order
	UserGroupOther, with three bits for each to
	enable or disable ReadWriteExecute.
	
	Example:
		
		chmod u+rwx,g+rw,o-rwx aFile
	
	Numerical equivalent:
		
		Use three binary integers for ugo and one bit each for rwx:
	
		chmod 760 aFile

		Is the same as:

		chmod   u+rwx,g+rw-x,o-rwx aFile
		Binary:   111   11 0   000
		Decimal:   7     6      0 ]]></sc>

<sc name="Show disk usage of current dir or selected dir"><![CDATA[
	du -s <dir>]]></sc>

<sc name="Write to stdout"><![CDATA[
	echo anything]]></sc>

<sc name="Write to a file"><![CDATA[
	echo anything > <path> ]]></sc>

<sc name="Append to a file"><![CDATA[
	echo anything >> <path> ]]></sc>

<sc name="Update the modified time for a file"><![CDATA[
	touch <path> ]]></sc>

<sc name="Quickly create an empty file"><![CDATA[
	> <path> ]]></sc>

<sc name="Show differences between files"><![CDATA[
	diff -r leftDir rightDir ]]></sc>

<sc name="Show files that differ without details"><![CDATA[
	diff -r -q leftDir rightDir ]]></sc>

<sc name="Trace execution of a shell script"><![CDATA[
	sh -x <fileName> ]]></sc>

<sc name="Monitor additions to a log file"><![CDATA[
	tail -f <fileName> ]]></sc>

<sc name="Make a symbolic link"><![CDATA[
	ln -s <path> <name> ]]></sc>

<sc name="List files in color"><![CDATA[
	ls --color=tty
	(Alias this to ls) ]]></sc>

<sc name="List a single column of names only"><![CDATA[
	ls -1 ]]></sc>
	
<sc name="List directories only"><![CDATA[
	find -type d -maxdepth 1
	(Alias this to lsd) ]]></sc>

<sc name="List files in order of modification time"><![CDATA[
	ls -lrt ]]></sc>

<sc name="List files in order of size"><![CDATA[
	ls -lrS ]]></sc>

<sc name="List all open files and sockets"><![CDATA[
	lsof ]]></sc>
	
<sc name="Show the number of files in a directory"><![CDATA[
	ls -1 | wc -l ]]></sc>
	
<sc name="Run a shell script so it changes the environment"><![CDATA[
	source .bash_profile (or whatever script you changed) ]]></sc>

<sc name="Run a command relative to another root file system"><![CDATA[
	chroot newroot command ]]></sc>

<sc name="Execute a shell script and echo the commands for debugging"><![CDATA[
	sh -x yourScript ]]></sc>

<sc name="Low-level high speed copy"><![CDATA[
	The dd command can copy between files or devices.
	
		dd if=sourcePath of=destPath bs=1M

	Using the optional bs=n option can speed up the copy. You can use
	the suffix K, M, or G on numbers.

	By adding the count option, you can write an exact number of fixed-size records.
	For example, to destroy the partition table of a disk:

		dd if=/dev/zero of=/dev/sdb3 bs=1K count=1

	To display the status of a dd copy that's aready started, use this command
	in another shell window:

		kill -USR1 `pgrep '^dd$'`

	This will cause dd to show a status message in it's original window
	and continue with the copy operation. ]]></sc>
			
<sc name="Write a line to the syslog"><![CDATA[
	logger This line is appended to /var/log/messages 
	logger -t MYTAG This line gets a MYTAG: prefix  ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="CDs">
<!-- ********************************************************************* -->

<sc name="Using cdrecord with non-scsi drives"><![CDATA[
	The primary tool described in the following sections is "cdrecord".
	The most current versions of this program accept normal Linux
	CD device names, e.g. "/dev/cdrom" and support both SCSI and
	ATAPI drives.
	
	Earlier versions of cdrecord only worked with SCSI drives and
	required the bizarre "x,y,z" drive name notation. ]]></sc>

<sc name="Create a data CDR readable by Linux (-r) or Windows (-J)"><![CDATA[
	nice --18 mkisofs -l -J -r -V MyVolumeName sourceDirectory/  \
	    | cdrecord speed=x dev=/dev/cdrom -data -

	To make a CDRW, add blank=fast to cdrecord options.
	Speed should be 8 for CDRs and 4 for CDRW on my HP 9200. ]]></sc>

<sc name="Create a data DVD readable by Linux (-r) or Windows (-J)"><![CDATA[
	growisofs -dvd-compat -Z /dev/hdc -J -r /path/to/directory ]]></sc>

<sc name="Create a video DVD"><![CDATA[
	growisofs -dvd-video -Z /dev/hdc /pathTo/Directory

	The Directory should contain the AUDIO_TS and VIDEO_TS
	subdirectories expected on a video. ]]></sc>

<sc name="Create an ISO image file from a directory of files"><![CDATA[
	mkisofs -l -r -J -V MyVolumeName -o myISOfile.iso.bin sourceDirectory/ ]]></sc>

<sc name="Display info about writable media"><![CDATA[
	dvd+rw-mediainfo /dev/hdc ]]></sc>

<sc name="Copy a raw DATA CD at the sector level. Source is on /dev/cdrom"><![CDATA[
	cdrecord -v dev=/dev/cdrom speed=2 -isosize /dev/cdrom ]]></sc>
	
<sc name="Make an audio cd track from an mp3 file"><![CDATA[
	mpg123 -s file1.mp3 \
	    | cdrecord speed=x dev=/dev/cdrom -audio -pad -swab -nofix - 

	Use this command for each track, then fixate using the
	command documented next: ]]></sc>
	
<sc name="Fixate the CD"><![CDATA[
	cdrecord dev=/dev/cdrom -fix ]]></sc>

<sc name="Rip a music CD track"><![CDATA[
	cdparanoia [-d device] trackRange result.wav ]]></sc>

<sc name="Rip all the tracks on an audio cd to a set of wav files"><![CDATA[
	One wav per track:

	cdparanoia 1- -B ]]></sc>

<sc name="Rip and convert one track to one mp3"><![CDATA[
	cdparanoia trackNumber - | lame -b 160 - result.mp3 ]]></sc>

<sc name="Record an audio cd from a directory full of wav files"><![CDATA[
	One wav per track:

	cdrecord speed=s dev=/dev/cdrom -audio *.wav ]]></sc>
		
<sc name="Track range examples"><![CDATA[
	1-	# Entire CD
	-- -3	# Beginning through track 3
	2-4	# Tracks 2 through 4 ]]></sc>
	
<sc name="Create a CDR from an ISO image"><![CDATA[
	cdrecord speed=4 dev=/dev/cdrom -data imageFile.iso.bin
	For cdrw, add: blank=fast ]]></sc>

<sc name="Create a CDR from a raw partition"><![CDATA[
	cdrecord speed=4 dev=/dev/cdrom -isosize -dao -data /dev/hda2 
	For cdrw, add: blank=fast ]]></sc>

<sc name="Create an ISO image file from a CD"><![CDATA[
	readcd dev=/dev/cdrom f=myImageFile.iso.bin ]]></sc>

<sc name="Dealing with older versions of cdrecord"><![CDATA[
	Older versions of cdrecord require scsi drivers or
	scsi emulation with atapi drives. The following sections
	show how to deal with this situation. ]]></sc>
	
<sc name="Make your ide cdrom look like a scsi device"><![CDATA[
	The cdrecord program wants to see scsi devices:
	The cdrom module must be loaded first, but it will
	normally be loaded if it was operating in ide mode.
	Otherwise, do an "insmod cdrom" first.
	
	rmmod ide-cd
	insmod cdrom
	insmod sr_mod
	insmod ide-scsi

	The scsi-mod will be loaded if you have
	a real scsi interface in your machine.
	Otherwise, # it must be loaded before sr_mod. ]]></sc>
			
<sc name="Restore the cd to normal (IDE) operation"><![CDATA[
	rmmod sr_mod ide-scsi
	insmod ide-cd ]]></sc>

<sc name="Make atapi cd drives look like scsi at boot time"><![CDATA[
	For this example, assume you have two ide drives:
	hdc and hdd.
	
	Method 1: Add this line to you kernel boot options:

	    append="hdc=ide-scsi hdd=ide-scsi"

	Method 2: Add these lines to /etc/modules.conf:
	
	    options ide-cd ignore=hdc 
	    options ide-cd ignore=hdd
	    pre-install sg modprobe ide-scsi
	    pre-install sr_mod modprobe ide-scsi
	    pre-install ide-scsi modprobe ide-cd ]]></sc>
	
<sc name="Devices for the cd drives in scsi mode"><![CDATA[
	/dev/scd0	cdram
	/dev/scd1	cdrom
	/dev/scd1	dvd ]]></sc>

<sc name="Device names for cd drives in ide mode"><![CDATA[
	/dev/hdc	cdram
	/dev/hdd	cdrom
	/dev/hdd	dvd ]]></sc>
	
<sc name="List all SCSI devices visible to cdrecord in x,y,z format"><![CDATA[
	The cdrecord program will use "dev=x,y,z" notation where x,y,z are
	shown by the command:
	
	cdrecord -scanbus ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Configuration">
<!-- ********************************************************************* -->

<sc name="File locations and descriptions"><![CDATA[
	/etc/hosts                      # Known IP number/name bindings
	/etc/fstab                      # Define mount points & filesystems
	/etc/samba/smb.conf             # Config Samba server
	/etc/exports                    # List of nfs exported directories
	/etc/cram-md5.pwd               # Imap & pop3 access: username <tab> password
	/etc/dhcp/dhcpd.conf            # Configure dhcp server
	/etc/dhcp/dhclient.conf         # Configure dhcp client
	/etc/xinetd                     # Configure sub-servers (telnet, tftp, etc)
	/etc/bashrc                     # Global functions and aliases
	/etc/localtime                  # Link into a /usr/share/zoneinfo file
	/etc/named.conf                 # Configuation for named DNS (bind)
	/etc/resolv.conf                # IP names and config for DNS
	/etc/securetty                  # Terminals that are allowed to be root
	/etc/DIR_COLORS                 # Colors used by color ls
	/etc/modprobe.conf              # Configure module loader
	/etc/printcap                   # One entry per printer
	/etc/profile                    # Global environment and startup 
	/etc/profile.d/*.sh             # Modular global environ additions
	/etc/ppp/options                # Contains lock for ppp (Remove lock!)
	/etc/ppp/ip-up.local            # Things to do after connecting
	/etc/ppp/pap-secrets            # Username-password entries
	/etc/ppp/resolv.conf            # Created by ppp with usepeerdns option
	/etc/pcmcia/config.opts         # Used to exclude IRQ 12 for PS/2 mouse
	/etc/pcmcia/network.opts        # Configure and start pcmcia ethernet
	/etc/securetty                  # List terminals allowed to login as root
	/etc/sysconfig/pcmcia           # Use this to turn on pcmcia
	/etc/sysconfig/network          # Start networking, set def gateway
	/etc/sysconfig/network-scripts  # ifcfg-xxx files for each interface
	/etc/sysconfig/clock            # Vars used in rc.sysinit to set the clock
	/etc/sysctl.conf                # Kernel settings for /proc/sys boot
	/etc/rc.d/init.d                # Start/stop scripts for system services 
	/etc/rc.d/rc.sysinit            # Boot time configuration script

<sc name="Other interesting files"><![CDATA[
	/boot/vmlinuz                   # Conventional symbolic link to kernel image
	/var/log/dmesg                  # Startup messages
	/var/log/messages               # Main system message log
	/var/log/maillog                # Log for mail i/o
	/var/log/httpd                  # Apache web server log files
	/var/named/                     # Location of zone files for named
	/var/spool/mail                 # Each user's mbox file for new mail
	/var/spool/lpd/xxx              # One xxx directory per printer 
	/var/spool/lpd/xxx/.config      # Hidden access info for printer 
	/var/spool/mqueue               # Directory for queued outgoing mail
	/usr/X11R6/lib/X11/rgb.txt      # Names for all the X colors
	/usr/X11R6/lib/X11/             # X configuration stuff
	/lib/modules                    # Path to system modules
	/usr/share/zoneinfo		# Subdirectories contain time zone files 
	/usr/src/linux/.config          # Hidden kernel config file
	/usr/src/redhat/...             # RPM source and build directories  ]]></sc>
	
<sc name="Example /etc/fstab"><![CDATA[
	# Root and swap volumes

	/dev/hda1           /              ext3    defaults 1 1
	/dev/hda3           swap           swap    defaults 0 0

	# Special device mounts

	none                /proc          proc    defaults 0 0
	none                /dev/pts       devpts  gid=5,mode=620 0 0
	none                /dev/shm       tmpfs   defaults 0 0

	# Removable media

	/dev/fd0            /mnt/floppy    auto    noauto,owner 0 0
	/dev/cdrom          /mnt/cdrom     iso9660 noauto,owner,ro 0 0

	# Logical volumes on the boot device

	/dev/vg2/spoolVol   /var/spool     ext2    defaults 0 0
	/dev/vg2/homeVol    /home          ext2    defaults 0 0
	/dev/vg2/wwwVol     /var/www       ext2    defaults 0 0

	# Logical volumes on the backup device

	/dev/vg1/backVol    /mnt/back      ext3    defaults 0 0
	/dev/vg1/archVol    /mnt/dos       ext3    defaults 0 0

	# Samba network

	//hp/dos            /mnt/hpDos     cifs   noauto,username=administrator 0 0
	//hp/c              /mnt/hpWin     cifs   noauto,username=administrator 0 0
	//sparksVaio/C$     /mnt/vaio      cifs   noauto,username=administrator 0 0
	//sparks9k/Main     /mnt/9kWin     cifs   noauto,username=administrator 0 0

	# NFS network

	# hp:/mnt/c         /mnt/dummy1    nfs     noauto,_netdev 0 0

	# Loop mount example

	# /mnt/Mac.hfs      /mnt/mac       hfs     noauto,loop 0 0 ]]></sc>
	
<sc name="Example /etc/exports"><![CDATA[
	/mnt/back      *.csparks.com(rw,no_root_squash)
	/mnt/dos       *.csparks.com(rw,no_root_squash)
	/var/www/html  *.csparks.com(rw,no_root_squash) 
	/mnt/thing     192.168.1.0/24(rw,no_root_squash) ]]></sc>

<sc name="Example /etc/lilo.conf"><![CDATA[
	boot=/dev/hda
	root=/dev/hda6
	map=/boot/map
	message=/boot/message	
	install=/boot/boot.b
	prompt
	timeout=50
	default=linux
	
	# Enable boot partition beyond cylinder 1024:
	lba32
	
	image=/boot/vmlinuz
	        label=linux
	        root=/dev/hda6
	        read-only  ]]></sc>

<sc name="Example /etc/grub.conf"><![CDATA[
	default=0
	timeout=0
	splashimage=(hd0,0)/grub/splash.xpm.gz
	hiddenmenu
	title Fedora (2.6.32.10-90.fc12.i686.PAE)
		root (hd0,0)
		kernel /vmlinuz-2.6.32.10-90.fc12.i686.PAE ro root=/dev/mapper/vg0-rootVol2 rhgb quiet
		initrd /initramfs-2.6.32.10-90.fc12.i686.PAE.img
	title Fedora (2.6.31.5-127.fc12.i686.PAE)
		root (hd0,0)
		kernel /vmlinuz-2.6.31.5-127.fc12.i686.PAE ro root=/dev/mapper/vg0-rootVol2  rhgb quiet
		initrd /initramfs-2.6.31.5-127.fc12.i686.PAE.img ]]></sc>



<sc name="Example /etc/sysconfig/static-routes"><![CDATA[
	When a device is started, the static-routes file
	is read by the script ifup-routes. For each line
	that matches the device in the first parameter it
	reads the line:

		read device args

	The routes are added by a script that performs "route add"
	(Note the minus character before $args)

		route add -$args $device

	For example: (This is used to route back to basilisk)

		eth0 host 192.168.2.3 gw 192.168.0.1 ]]></sc>

<sc name="Example /etc/modules.conf (cira 1996)"><![CDATA[
	Messing around with modules.conf used to be a necessary
	right-of-passage for linux administrators. Now I never look
	at the thing. The following is a sample from one of my
	ancient boxes. Perhaps something is interesting. I have
	no memory of why I had to deal with this $@#*&!, but each
	line was earned with hours of frustration and pain.

	alias eth0 tulip
	alias tap0 ethertap

	alias scsi_hostadapter aic7xxx
	
	alias parport_lowlevel parport_pc

	alias sound-slot-0 es1371
	alias sound-service-0-0 es1371
	alias sound-service-0-3 es1371
	alias sound-service-0-4 es1371
	
	post-install sound-slot-0 /bin/aumix-minimal \
	    -f /etc/.aumixrc -L >/dev/null 2>&1 || :
	pre-remove sound-slot-0 /bin/aumix-minimal \ 
	    -f /etc/.aumixrc -S >/dev/null 2>&1 || :
	
	alias usb-controller usb-uhci
	alias char-major-180 usbcore
	alias cdrom sr_mod
	alias cdram sr_mod
	above sr_mod ide-scsi
	alias char-major-195 NVdriver
	alias net-pf-1 unix
	alias net-pf-17 af_packet ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Cryptography">
<!-- ********************************************************************* -->

<sc name="List available ciphers"><![CDATA[
	openssl list-cipher-commands ]]></sc>
		
<sc name="Encrypt a document using openssl"><![CDATA[
	openssl des3 -salt -in mydoc.txt -out mydoc.txt.des3 ]]></sc>
		
<sc name="Decrypt a document using openssl"><![CDATA[
	openssl des3 -d -salt -in mydoc.txt.des3 -out mydoc.txt ]]></sc>
		
</s>

<!-- ********************************************************************* -->
<s name="Devices">
<!-- ********************************************************************* -->
	
<sc name="Examples from my workstation"><![CDATA[
	mouse  -> /dev/input/mice
	modem  -> /dev/ttyS0
	cdrom  -> /dev/hdc
	cdrom1 -> /dev/hdd ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="DHCP">
<!-- ********************************************************************* -->

<sc name="/etc/dhcpd.conf"><![CDATA[
	# Shared

		ddns-update-style none ;
		option domain-name "csparks.com" ;
		option domain-name-servers 192.168.1.2 ;
		log-facility local1;

		subnet 192.168.0.0 netmask 255.255.255.0
		{       authoritative ;
		}

		subnet 192.168.1.0 netmask 255.255.255.0
		{       option routers 192.168.1.2 ;
		        option subnet-mask 255.255.255.0 ;
		        option broadcast-address 192.168.1.255 ;
		        option domain-name "csparks.com" ;
		        option domain-name-servers 192.168.1.2 ;
		        pool
		        {       range 192.168.1.100 192.168.1.200 ;
		        }
		        authoritative;
		}

	# Fixed

		host sparksc2
		{       hardware ethernet 00:16:36:a5:fe:fb ;
		        fixed-address 192.168.1.3;
		}

		host sparksc2w
		{       hardware ethernet 00:18:de:5b:50:c6 ;
		        fixed-address 192.168.1.3;
		}

		host cgsVaio
		{       hardware ethernet 00:01:4a:16:b6:58;
		        fixed-address 192.168.1.5;
		} ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Disk drives">
<!-- ********************************************************************* -->

<sc name="List all drives"><![CDATA[
	fdisk -l ]]></sc>

<sc name="Display or modify partitions"><![CDATA[
	fdisk /dev/devname ]]></sc>

<sc name="hdparm syntax  (IDE drives only)"><![CDATA[
	hdparm options /dev/hda ]]></sc>
	
<sc name ="Options"><![CDATA[
	-c  1	I/O support mode 1 (32 bit)
	-c  2	I/O support mode 2 (16 bit)
	-c  3	I/O support mode 3 (32 bit & sync)
	-m 16	Multi sector count 16 on
	-A  1	Enable drive read-ahead
	-a  8	Drive read-ahead count
	-d  1	DMA On
	-u  1	Enable interruptable driver (dangerous)
	-X 66	Ultra DMA mode 2 (dangerous, unnecessary)
	-X 34	Multiword DMA mode 2 (dangerout, unnecessary)
	-S  n	Spindown time in 5sec tics (0 <= n <= 240)
	
	-t	Perform & display drive test results
	-T	Perform & display Linux disk cache test ]]></sc>

<sc name ="Example tuning"><![CDATA[
	A 200G Maxtor on my server has these settings:

	hdparm -A 1 -a 8 -m 16 -d 1 -c 2 ]]></sc>
		
<sc name ="Boot time settings for hdparm"><![CDATA[
	/etc/sysconfig/harddisks ]]></sc>
	
</s>

<!-- ********************************************************************* -->
<s name="DNS">
<!-- ********************************************************************* -->

<sc name="Using DNS at home"><![CDATA[
	I find that "things go better with NDS". 
	This applies to lots of programs including MySQL and sendmail.

	I host my own domain and 2 or 3 others without having external
	secondary servers. This causes the angels to weep. But even if
	you just keep a local LAN, runnng DNS is convienient. If you
	don't host externally visible domains, proceed as shown below
	but leave out the external view in /etc/named.conf. ]]></sc>

<sc name="/etc/host.conf"><![CDATA[
	multi on
	order hosts,bind ]]></sc>
	
<sc name="/etc/resolv.conf"><![CDATA[
	domain csparks.com
	nameserver 127.0.0.1
	search loaldomain csparks.com ]]></sc>

<sc name="/etc/hosts"><![CDATA[
	127.0.0.1   localhost localhost.localdomain ]]></sc>
	
<sc name="/etc/sysconfig/network"><![CDATA[
	NETWORKING=yes
	HOSTNAME=server
	GATEWAY=192.168.0.254 ]]></sc>

<sc name="/etc/named.conf"><![CDATA[
	acl "mynet" { 127/8; 192.168.1.0/24; } ;
	
	options {
	        listen-on port 53 { any; };
	        listen-on-v6 port 53 { ::1; };
	        directory       "/var/named";
	        dump-file       "/var/named/data/cache_dump.db";
	        statistics-file "/var/named/data/named_stats.txt";
	        memstatistics-file "/var/named/data/named_mem_stats.txt";
	        allow-transfer    { none; } ;
	        allow-update      { none; } ;
	        dnssec-enable yes;
	        dnssec-validation yes;
	        dnssec-lookaside auto;
	        bindkeys-file "/etc/named.iscdlv.key";
	        managed-keys-directory "/var/named/dynamic";
	};
	
	logging {
	        channel default_debug {
	                file "data/named.run";
	                severity dynamic;
	        };
	        category lame-servers { null; };
	        category edns-disabled { null; };
	        category dnssec { null; };
	};

	view "internal"
	{
	        match-clients { mynet;  } ;
	        allow-query { mynet; } ;
	        allow-query-cache { mynet; } ;
	        allow-recursion { mynet; } ;
	        match-recursive-only yes ;
	
	        zone "." IN {
	                type hint;
	                file "named.ca";
	        };
	
	        include "/etc/named.rfc1912.zones";
	
	        zone "csparks.com" {
	                type master;
	                file "csparks.internal.zone";
	        };
	
	        zone "1.168.192.in-addr.arpa" {
	                type master;
	                file "csparks.internal.rev";
	        };
	
		...More internal zones...
	
	} // end of internal view
	
	view "external"
	{
	        match-clients { any; } ;
	        allow-query { any; } ;
	        allow-recursion { none; } ;
	        match-recursive-only no ;
	
	        zone "." IN {
	                type hint;
	                file "/var/named/named.ca";
	        };
	
	        zone "csparks.com" {
	                type master ;
	                file "csparks.external.zone" ;
	        } ;
	
		...More external zones...
	
	} // end of external view
	
	include "/etc/named.root.key"; ]]></sc>
	
<sc name="/etc/named.rfc1912.zone"><![CDATA[
	zone "localhost.localdomain" IN {
		type master;
		file "named.localhost";
		allow-update { none; };
	};

	zone "localhost" IN {
		type master;
		file "named.localhost";
		allow-update { none; };
	};

	zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" IN {
		type master;
		file "named.loopback";
		allow-update { none; };
	};

	zone "1.0.0.127.in-addr.arpa" IN {
		type master;
		file "named.loopback";
		allow-update { none; };
	};

	zone "0.in-addr.arpa" IN {
		type master;
		file "named.empty";
		allow-update { none; };
	}; ]]></sc>

<sc name="/var/named/csparks.internal.zone"><![CDATA[
	$TTL 3D
	@       IN      SOA     dns1.csparks.com. root.csparks.com. (
		                2010040701      ; serial: todays date + todays serial
		                8H              ; refresh, seconds
		                2H              ; retry, seconds
		                4W              ; expire, seconds
		                1D )            ; minimum, seconds

		        NS      192.168.1.2.
		        NS      192.168.1.2.
		        MX 10   mail.csparks.com.
		        MX 20   mx1.mc.mpls.visi.com.
		        A       192.168.1.2
	server          A       192.168.1.2
	mail            A       192.168.1.2
	dns1            A       192.168.1.2
	dns2            A       192.168.1.2

	another		A	192.168.1.3
	...

	ftp             CNAME   server
	www             CNAME   server
	shell           CNAME   server 
	... ]]></sc>

<sc name="/var/named/csparks.rev"><![CDATA[
	$TTL 3D
	@       IN      SOA     server.csparks.com. root.csparks.com. (
		                2010040701 ; Serial, todays date + todays serial
		                8H         ; Refresh
		                2H         ; Retry
		                4W         ; Expire
		                1D)        ; Minimum TTL

		        NS      server.csparks.com.

	2               PTR     server.csparks.com.
	3               PTR     another.csparks.com.
	... ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Email">
<!-- ********************************************************************* -->

<sc name="Send a typed message to another user"><![CDATA[
	mail -s 'A subject string' someone@somewhere.com
	Type your message here
	and end with a <control>d ]]></sc>

<sc name="Send mail with a text file attachment"><![CDATA[
	cat afile.bin | mail -s "This is a test" someone@somewhere.com ]]></sc>

<sc name="Send mail with a binary file attachment"><![CDATA[
	cat afile.bin | uuencode temp.txt | mail -s "This is a test" someone@somewhere.com ]]></sc>

<sc name="Talk to sendmail directly for debugging"><![CDATA[
	telnet <destinationMachine> 25
	ehlo <yourDomainName>
	mail from: <yourEmailAddress>
	rcpt to: <receiverEmailAddress>
	data
	Type your message here and end with a dot:
	.
	quit ]]></sc>

<sc name="Talk to a POP server directly for debugging"><![CDATA[
	telnet <destinationMachine> 110
	USER <yourEmailAddress>
	PASS <yourPassword> 
	STAT
	RETR n
	DELE n
	QUIT ]]></sc>

<sc name="Talk to an IMAP server directly for debugging"><![CDATA[
	telnet <destinationMachine> 143
	a login <yourUsername> <yourPassword>
	a select inbox
	a fetch <n> full
	a fetch <n> body[header]
	a fetch <n> body[text]
	a logout ]]></sc>
	
<sc name="Configure sendmail as a server"><![CDATA[
	This is only useful if your machine will act as a mail
	server for your domain. It is not necessary if you send
	and receive email via an ISP. This is not an adequate
	recipe if you intend to host mulitple domains. 

	Changes for /etc/sendmail.mc

	Enable listening on the external smtp port

		dnl DAEMON_OPTIONS(Port=smtp,Addr=127.0.0.1, Name=MTA)dnl

	Masquerade changes header fields on outgoing mail so they alway
	appear to come from username@yourdomain.com rather than from whatever
	machine on your internal LAN was the source. That's almost always
	what you want to to:

		MASQUERADE_AS(`yourdomain.com')dnl
		MASQUERADE_DOMAIN(`yourdomain.com')dnl
		FEATURE(`masquerade_envelope')dnl
		FEATURE(`masquerade_entire_domain')dnl

	If-and-only-if you don't have DNS (bind) configured,
	you need to explicity tell sendmail your server's host name.
	This should match the whatever an external reverse-lookup 
	of your IP address returns. If the names don't agree, some
	remote servers may reject mail from your domain.
	
		define(`confDOMAIN_NAME', `yourserver.yourdomain.com')dnl
		
	After changing /etc/mail/sendmail.mc you need to run the
	macro processor:

		m4 /etc/mail/sendmail.mc &gt; /etc/mail/sendmail.cf

	Note: On Fedora systems, you can rebuild sendmail.cf and
	any modified database files by simply running "make" in
	the sendmail directory.

	Enable relaying for your domain in /etc/mail/access.
	This allows other machines on your LAN to send mail through
	the server to other destinations:

		Connect:localhost.localdomain	RELAY
		Connect:localhost		RELAY
		Connect:127.0.0.1		RELAY

		annoying.ru	550 You are a poltroon
	
		yourdomain.com	RELAY

	Rebuild the database (access.db)

		makemap hash /etc/mail/access < /etc/mail/access

	Populate local-host-names with all domain names and
	host names sendmail will accept as mail recipiants: 
	The name of your server "server.yourdomain.com" should
	match the name you specified for the MX record when you
	registered your domain name.
 
		yourdomain.com
	  	server.yourdomain.com
		mail.yourdomain.com

	If you have linux client machines running on your internal LAN
	that will send mail via your server, they need to have
	the "dotted" name of the mail server in their /etc/hosts file.
	(This is not necessary if you are running a properly configured
	DNS server.) Note the trailing dot:
	
		192.168.0.2 mail.yourdomain.com.
	
	Enable the sendmail daemon at boot time: 

		chkconfig --add sendmail

	Restart the server after making changes:

		service sendmail restart ]]></sc>

<sc name="Reroute mail sent to your server"><![CDATA[
	The /etc/virtusertable is used to reroute mail. The left column has
	addresses for domains or email addresses accepted by your server.
	(You listed them in local-host-names.)
	The right column has the destination where the mail will be sent:

		root@yourdomain.com	yourname@yourdomain.com
		admin@yourdomain.com	yourname@yourdomain.com

	You can also send the same message to multiple destinations:

		exuser@yourdomain.com	responder@yourdomain.com 
		exuser@yourdomain.com	exuser@somewhere_else.com 

	This is a catch-all entry for yourdomain.com:

		@yourdomain.com		satan@hell.org

	You can also send mail to the same user on a different domain:

		@otherdomain.com	%1@somewhere.com
	
	In the example above, the %1 matches the username on mail
	directed to otherdomain.com. ]]></sc>

<sc name="Redistributing local mail via aliases"><![CDATA[
	The /etc/aliases file redirects mail accepted for local
	delivery. It is used after the virtusertable does its thing.
	It has a similar format, but note the required colons:

		root:		yourname
		postmaster: 	yourname
		happylist: 	yourname,bill,jane,walter,golum@mordor.com

	Note that the last line implements a simple mailing list.
	The last member is on a remote machine. 

	Note: The "postmaster" is a required user on a domain that
	conforms to the email RFCs. If you discard mail not directed
	to known local users in virtusertable, you should first match
	and redirect postmaster@yourdomain.com in that file because
	it will never make it to the aliases redirect. ]]></sc>

<sc name="Configure the IMAP server"><![CDATA[
	Entry for  /etc/xinetd.d
	
		service imap
		{	socket_type     = stream
			wait            = no
			user            = root
			server          = /usr/sbin/imapd
			disable         = no
		}

	Create an md5 password file owned by root:
	
		touch /etc/cram-md5.pwd
		
	Add one line for each imap user of this form:
	
		username<tab>password
		
	Both pop & imap will use this file to avoid
	transmitting clear-text passwords.
	
	After editing, the file permissions should be changed:
	
		chmod a-rwx,o+r /etc/cram-md5.pwd ]]></sc>

<sc name="Serve mailing lists using GNU mailman"><![CDATA[
	This example assumes you have installed a redhat/fedora mailman rpm.
	
	Initial setup of the program:
	
	Edit:
		/usr/lib/mailman/Mailman/mm_cfg.py

	Modify these definitions:
	
		DEFAULT_URL_HOST   = 'www.yourdomain.com'
		DEFAULT_EMAIL_HOST = 'yourdomain.com'

	Create the "mailman" mailing list:
	
		cd /usr/lib/mailman
		./bin/newlist mailman
	
	You will be asked to provide your email address and a password.
	A list of alias definitions are presented and you must copy
	these into:
		
		/etc/aliases
	
	Then run:
	
		newaliases

	Provide a site password by running:
	
		cd /usr/bin/mailman
		./bin/mmsitepass
	
	Configure the system service
	
		chkconfig mailman on
		service mailman start
	
	Edit the httpd configuration file in:
	
		/etc/httpd/conf.d/mailman
		
	Un-comment and edit the line at the end to redirect mailman
	queries on your server, then restart httpd:
	
		service httpd restart
	
	Now you can visit
	
		http://www.yourdomain.com/mailman
	
	Check your own email and you should see the creation
	announcement for the new list "mailman."
	
	To create new lists:
	
		cd /usr/lib/mailman
		./bin/newlist mynewlist
	
	To delete a list
	
		cd /usr/lib/mailman
		./bin/rmlist listname
		
	To remove all the associated archives as well:
		
		./bin/rmlist -a listname]]></sc>
</s>
		
<!-- ********************************************************************* -->
<s name="File systems">
<!-- ********************************************************************* -->

<sc name="Format a floppy disk"><![CDATA[
	fdformat /dev/fd0H1440
	mkfs -t msdos /dev/fd0H1440 1440

	When putting ext2 on a floppy, omit the su reserve:
	
		mkfs -t ext2 -m 0 /dev/fd0H1440 1440
	
	Some-but-not-all floppies can be enlarged:
	
		fdformat /dev/fd0u1722 ]]></sc>
	
<sc name="Mount filesystems"><![CDATA[
	mount -t iso9660 -ro /dev/hdc /mnt/cdrom
	mount -t vfat /dev/hda5       /mnt/dos
	mount -t ext2 /dev/sda3       /mnt/jazz
	mount -t ntfs /dev/hda1       /mnt/nt
	mount -t cifs //sparks750/c   /mnt/sparks750
	(See fstab below for more cifs options)
	mount -t hfs  /dev/sda /mnt/jazz -o afpd -o uid=500
		(Currently, the afpd option hangs up the Mac...)
	mount -t nfs mac.sparks.com:/root /mnt/macroot
	To support nfs mounts, remote system must have /etc/exports:
		/root *.sparks.com(rw) 

	Newer versions of Linux figure out the filesystem type automatically
	so the -t options can often be omitted. ]]></sc>

<sc name="Make and mount a file system inside a file"><![CDATA[
	dd if=/dev/zero of=MyDiskImage.ext2 bs=1k count=1000
	mkfs -t ext2 MyDiskImage.ext2
	mkdir here
	mount -t ext2 -o loop MyDiskImage.ext2 here ]]></sc>

<sc name="Make and mount a file system using a loop device"><![CDATA[
	Show all active (in use) loop devices:

		losetup -a

	Show the first available loop device:

		losetup -f

	Attach a loop device to a file:

		losetup /dev/loop0 MyDiskImage.ext2

	Mount the device with a specified filesystem:

		mount -t ext2 /dev/loop0 here 

	This does the same thing as mount with the -o option.
	It is easier to use the -o option because you don't have 
	to deal with finding and specifying a free loop device.

	When you are finished, unmount the volume:

		umount here

	And free the loop device:

		losetup -d /dev/loop0 ]]></sc>

<sc name="Make and format a Macintosh filesystem inside a file"><![CDATA[
	dd if=/dev/zero of=MacDiskImage.hfs bs=1k count=whatever
	hformat -l "HD1" MacDiskImage.hfs ]]></sc>

<sc name="Show free space on all drives"><![CDATA[
	df -h 

	The -h option selects human-readable units. ]]></sc>

<sc name="Show details about a linux file system"><![CDATA[
	tune2fs -l /dev/hdax ]]></sc>
	
<sc name="Create an ext3 file system"><![CDATA[
	mkfs -t ext2 -j /dev/hdax ]]></sc>
	
<sc name="Convert ext2 to ext3"><![CDATA[
	tune2fs -j /dev/hdax ]]></sc>
	
<sc name="Resize a file system (offline)"><![CDATA[
	Revert from ext3 to ext2 if necessary (see below)
	I have heard that this step is unnecessary.

	unmount /dev/hda1
	e2fsck -f /dev/hda1
	resize2fs /dev/hda1 newSizeInBlocks
	mount /dev/hda1 /mnt/point

	If newSize is not specified, the file system will grow to
	fill the partition.
	After shrinking a file system, you can shrink the partition to match.
	After growing a partition, you can grow the file system to match. ]]></sc>

<sc name="Revert an ext3 file system to ext2"><![CDATA[
	umount /dev/hda1			# Unmount the partition
	tune2fs -O ^has_journal /dev/hda1	# Turn off journaling
	e2fsk -y /dev/hda1			# Check for errors
	mount -t ext2 /dev/hda1 /mnt/point	# Remount as ext2
	cd /mnt/point				# Go to root directory
	rm -f .journal				# Remove the journal
	
	You must update entry in fstab if this is a permanent change.
	Ext3 should be reverted to ext2 before resizing. ]]></sc>

<sc name="Convert an ext2 file system to ext3"><![CDATA[
	tune2fs -j /dev/hda1

	Edit fstab to indicate ext3
	If this is the root partition, you need to use an initrd to boot.	
	See redhat documentation for details. ]]></sc>
	
<sc name="Create and use an encrypted dm_crypt volume"><![CDATA[
	This is the new and prefered way to handle file system encryption.
	See the next section on the older "cryptoloop" method.
	
	You need a device to access a whole drive, a partition, a logical
	volume or a loopback file. We will use "myDev" for this example.
	A new filesystem will be created in this example.
	
	Create a dm_crypt mapping to the device
	
		cryptsetup create mymap mydev
		
		You will be prompted for the passphrase.
		The default cipher is AES 256.

		Note that "mydev" can also be the name of a file
		that contains the filesystem.

	Now you can create and mount any normal filesystem:
	
		mkfs -t ext2 /dev/mapper/mymap
		mount -t ext2 /dev/mymap /mnt/mymount
	
	When you are finished using the volume:
	
		umount /mnt/mymount
		cryptsetup remove mymap
	
	When mounting a previously-created dm_crypt volume:
	
		cryptsetup create mymap mydev
		mount /dev/mapper/mydev /mnt/mymount ]]></sc>

<sc name="Create and use an encrypted cryptoloop volume"><![CDATA[
	This is the older and depricated method for using an encrypted
	loopback filesystem. It depends on patched versions of of losetup
	that are not part of recent Linux distributions.
	
	First make a big file of random stuff:
	
		dd if=/dev/urandom of=myfile bs=1M count=50
	
	Load the crypto module group and your selected cypher:
	
		modprobe cryptoloop
		modprobe cipher-twofish
	
	Mount the file as an encrypted loopback device:
		
		losetup -e twofish /dev/loop0 myfile
	
	You will need to answer these questions:
	
		Available keysizes (bits): 128 192 256
		Keysize: 128
		Password :

	Now you can create and mount any normal filesystem:
	
		mkfs -t ext2 /dev/loop0
		mount -t ext2 /dev/loop0 /mnt/myMount
	
	When you are finished using the volume:
	
		umount /mnt/myMount
		losetup -d /dev/loop0
	
	To mount a previously-created cryptoloop volume:
	
		mount -t ext2 -o loop,encryption=twofish myfile /mnt/myMount ]]></sc>
		
<sc name="Automatically mount file systems"><![CDATA[
	Configure autofs and you'll never have to type mount commands again!

	The autofs service must be running for this to work.
	
		service autofs status
	
	If autofs was not running, you can start it using:
	
		service autofs start
	
	Configure autofs to start after reboot:
	
		chkconfig autofs on
	
	Configuration files
	
	The master file specifies one or more directores where mount
	points will be automatically created and the files that contain
	the items to be mounted.
	
		/etc/auto.master
	
			/mnt   /etc/auto.mount
			/goop  /etc/auto.goop
	
	Each mount point file contains any number lines of the form:
	
		mount-point-name  -fstype=filesystem,options  :device

	An example:
			
		/etc/auto.mount

			dvd     -fstype=iso9660,ro,nosuid,nodev  :/dev/cdrom
			stick   -fstype=auto  :/dev/sdb1
			floppy  -fstype=auto  :/dev/fd0
			asus    -fstype=cifs,rw,noperm,username=xxxx,password=yyyy ://asus/mydir
	
	After editing these files, you must reload:
	
		service autofs reload
	
	You can now access the contents of these directories by simply using them:
	
		ls /mnt/stick
		cd /mnt/asus
		...
	
	The autofs deamon will unmount these resources when they are unused
	for a specified time. This timeout can be configured in:

		/etc/sysconfig/autofs

	The timeout is specified in seconds using this expression:

		TIMEOUT=300  ]]></sc>		
</s>

<!-- ********************************************************************* -->
<s name="Firewall">
<!-- ********************************************************************* -->

<sc name="Overview of IPTables"><![CDATA[
	Incoming and outgoing IP packets pass through chains.
	A chain is a list of rules.
	A rule specifies a pattern to match in an IP packet's header.
	If the rule does not match, the packet is passed on to the 
	next rule in the chain.
	If the rule matches, the packet is passed to the target.
	The target of a rule can be another chain or one of the 
	special targets: ACCEPT, DROP, QUEUE or RETURN.
	
		ACCEPT - Let the packet through
		DROP   - Throw the packet away
		RETURN - Leave this chain and let the caller decide.
		QUEUE  - Pass the packet to an external program. 
		
	There are built-in chains and user-defined chains.
	If packet 'runs off' the end of a user-defined chain without
	triggering a rule, RETURN is the default target. If a packet
	runs off the end of a built-in chain, a default target is
	selected. This target is configured by a command that sets 
	the default chain policy. 
	
	Chains are organized into named tables. There are two commonly 
	used tables: "filter" and "nat". Both of these tables have some
	built-in chains that are connected in a flow diagram. 
	(A link to the diagram is in the next section.)

	Chains have names local to their parent table.
	It convenient to think of the complete name of a chain as the 
	concatenation of the table name and the chain name. 
	(Different tables may use the same local chain names.)
	
	When a packet arrives for processing by the firewall, its source 
	and destination address are examined to determine which built-in
	filter chain should be used:

		INPUT   - Destination is on this machine.
		OUTPUT  - Source is on this machine, destination is elsewhere.
		FORWARD - Source and destination are elsewhere.

	The FORWARD chain is exclusive: packets that arrive from outside 
	to be routed elsewhere do not pass through the INPUT or OUTPUT chains.
	
	The "nat" table contains chains for packets that get altered by rules.
	Built-in chains for "nat":
	
		PREROUTING  - Alters packets before routing to INPUT or FORWARD.
		OUTPUT      - Alters packets after INPUT and before OUTPUT.
		POSTROUTING - Alters packets after OUTPUT or FORWARD.

	PREROUTING is used to alter the packet destination (DNAT).
	This is used, for example, when you want to route mail or web traffic
	to some other machine on your LAN.

	POSTROUTING is used to alter the packet source (SNAT). This is used
	to allow machines on your LAN to share a single IP address on the internet. ]]></sc>
	
<ss name="IPTables flow diagram">
	<p indent="4">
	To really see what&apos;s going on, you need to study
	this <link name="diagram." url="IPTablesFlow.txt"/>

	</p>
</ss>
	
<sc name="Commonly used flags for creating rules"><![CDATA[
	-t TableName (default is filter)
	-A ChainName to append this new rule
	-s Source IP address
	-d Destination IP address
	-i Input interface
	-o Output interface
	-p IP protocol 
	-j Target
	--dport Desination port 
	--sport Source port

	Examples:
	To drop all packets from an ip address stored in "badGuy":

		iptables -t filter -A INPUT -i eth0 -s $badGuy -j DROP 

	To pass all mail arriving on "netDev" to "anotherIP":

		iptables -t nat -A PREROUTING -i $netDev -p tcp \
			--dport smtp -j DNAT --to-destination $anotherIP:smtp 

	In the example above, the packet destination will be altered so
	it goes to $anotherIP. The FORWARD chain will then process the
	packet becase the source and destination are now external.
	If the the default policy for the FORWARD chain is not ACCEPT,
	you need to add this rule:
 
		iptables -t filter -A FORWARD -i $netDev -p tcp \
			--dport smtp -d $otherMachine -j ACCEPT ]]></sc>

<ss name="TCP/IP header diagram">
	<p indent="4">
	The flags are used to match various parts of the IP 
	and/or TCP header. <cr/>
	To really see what&apos;s going on, you
	need to study this <link name="diagram." url="TCPIPHeaders.txt"/>
	</p>
</ss>
		
<sc name="Commonly used IP protocols"><![CDATA[
	tcp, udp, icmp ]]></sc>
	
<sc name="Commonly used ports"><![CDATA[
	http, ftp, nntp, pop3, imap, smtp, ssh, domain ]]></sc>

<sc name="Remove all rules on a chain or on all chains (--flush)"><![CDATA[
	iptables -F optionalChainName ]]></sc>
	
<sc name="Delete a chain or all chains (--delete-chain)"><![CDATA[
	iptables -X optionalChainName ]]></sc>
	
<sc name="Zero packet &amp; byte counters in all chains (--zero)"><![CDATA[
	iptables -Z optionalChainName ]]></sc>

<sc name="Create new chain (--new-chain)"><![CDATA[
	iptables -N newChainName ]]></sc>

<sc name="Apply a default policy (--policy)"><![CDATA[
	Only valid for built-in chains (INPUT, OUTPUT, etc.)
	The policy target cannot be another chain.
	
	iptables -P chainName target ]]></sc>
	
<sc name="List the rules in a chain"><![CDATA[
	iptables -L optionalChainName ]]></sc>
	
<sc name="Rules to reset (eliminate) a firewall"><![CDATA[
        iptables -t filter -F
        iptables -t filter -X
        iptables -t filter -Z
	
        iptables -t nat -F
        iptables -t nat -X
        iptables -t nat -Z	

        iptables -P INPUT ACCEPT
        iptables -P OUTPUT ACCEPT
        iptables -P FORWARD ACCEPT ]]></sc>

<sc name="Target for logging a rule (must go before the planned action)"><![CDATA[
	-j LOG --log-prefix "Firewall: My rule fired" ]]></sc>
	
<sc name="Enable forwarding NAT when the server has a static IP address"><![CDATA[
	(The static IP of the server is in the variable $inetIP)
	echo 1 > /proc/sys/net/ipv4/ip_forward
	iptables -t nat -A POSTROUTING -o $inetDev -j SNAT --to-source $inetIP
	iptables -A FORWARD -i $lanDev -j ACCEPT ]]></sc>

<sc name="Enable forwarding NAT when the server has a dynamic IP address"><![CDATA[
	echo 1 > /proc/sys/net/ipv4/ip_forward
	echo 1 > /proc/sys/net/ipv4/ip_dynaddr
	iptables -t nat -A POSTROUTING -o $inetDev -j MASQUERADE ]]></sc>

<sc name="Forwarding a port to another server"><![CDATA[
	iptables -t nat -A PREROUTING -i $inetDev -p $proto --dport $port
		-j DNAT --to-destination $targetIP:$port
	iptables -A FORWARD -i $netDev -p $proto --dport $port
		-d $targetIP -j ACCEPT 

	Where
		$inetDev  = Device for incomming packets
		$proto    = Protocol: tcp, udp, or icmp
		$port     = The port you want to forward
		$targetIP = The target server ]]></sc>

<ss name="Simple iptables firewall">
	<p indent="4">
	<link name="My firewall" url="server.firewall"/>
	</p>
	</ss>

<sc name="Automatic iptables using the redhat init script"><![CDATA[
	When the system boots, the firewall configuation is restored from: 
	
		/etc/sysconfig/iptables

	This file can be updated by using the command

		iptables-save > /etc/sysconfig/iptables

	Enable the script at boot time using
	
		chkconfig --add iptables
	
	Other init script operations:

	service iptables start		# Apply /etc/sysconfig/iptables
	service iptables stop		# Admit all packets (remove firewall)
	service iptables panic		# Stop all incomming packets
	service iptables restart	# Reload the tables
	service iptables save		# Does iptables-save for you
	service iptables status		# Display the tables ]]></sc>
	
<sc name="Common kernel settings for a firewall"><![CDATA[
	IMPORTANT: Changing the value of ip_forward resets many other
	parameters to their default values. Your script should always
	set the value of ip_forward first! 

	Bash commands to configure the kernel:
	
	echo 1 > /proc/sys/net/ipv4/ip_forward
	echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
	echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
	echo 1 > /proc/sys/net/ipv4/tcp_syncookies
	echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
	echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
	echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects

	Alternatively, the /proc settings may be configured in the
	file /etc/sysctl.conf:

	net.ipv4.ip_forward = 1
	net.ipv4.icmp_echo_ignore_broadcasts = 1
	net.ipv4.icmp_ignore_bogus_error_responses = 1
	net.ipv4.tcp_syncookies = 1
	net.ipv4.conf.default.rp_filter = 1
	net.ipv4.conf.all.accept_source_route = 0
	net.ipv4.conf.all.accept_redirects = 0

	At boot time, sysctl.conf is loaded by /etc/rc.d/rc.sysinit ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Firewire">
<!-- ********************************************************************* -->

<sc name="Load the firewire packet module"><![CDATA[
	modprobe ieee1394 ]]></sc>
	
<sc name="Load the firewire card controller"><![CDATA[
	modprobe ohci1394

	The ohci module will recognize your disk as a SCSI device
	and automatically load the serial bus protocol (sbp2) module.
	If you need to see what's going on for debugging, do a 
	tail -f /var/log/messages in another shell window before
	you load the module. ]]></sc>
		
<sc name="Scan the bus for the SCSI address"><![CDATA[
	cdrecord --scanbus
	
	Mine was at SCSI addresss 2,0,0 so it is /dev/sdb.
	If the result had been 1,x,y it would be on /dev/sda. ]]></sc>

<sc name="Use fdisk to find the partition name"><![CDATA[
	fdisk /dev/sdb
	
	I found the DOS partition on the ipod at /dev/sdb2 ]]></sc>
	
<sc name="Create a mount point"><![CDATA[
	mkdir /mnt/ipod ]]></sc>
	
<sc name="Mount the device by hand"><![CDATA[
	mount -t vfat /dev/sb2 /mnt/ipod ]]></sc>

<sc name="Example fstab entry"><![CDATA[
	/dev/sb2  /mnt/ipod  vfat  noauto 0 0 ]]></sc>
	
<sc name="Mount the device when an fstab entry exists"><![CDATA[
	mount /mnt/ipod ]]></sc>
	
<sc name="Before you remove the device!"><![CDATA[
	umount /mnt/ipod
	rmmod sbp2
	
	After the rmmod, the iPod will tell you that
	it's ok to disconnect. This precaution should
	be observed before unplugging any firewire disk. ]]></sc>

<sc name="Remounting (With firewire and ohci already loaded)"><![CDATA[
	modprobe sbp2
	mount /mnt/ipod ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Graphics">
<!-- ********************************************************************* -->

<sc name="Resize images by percentage"><![CDATA[
	mogrify -resize 50% *.jpg]]></sc>

<sc name="Resize images to specified width (height will be proportional)"><![CDATA[
	mogrify -resize 400 *.jpg]]></sc>

<sc name="Convert color images to grayscale (blank and white)"><![CDATA[
	mogrify -colorspace gray *.jpg]]></sc>

<sc name="Convert all gifs to jpgs"><![CDATA[
	mogrify -format jpg *.gif]]></sc>

<sc name="Rotate a jpg 90 degrees clockwise, width equals height"><![CDATA[
	mogrify -rotate 90 myfile.jpg]]></sc>

<sc name="Rotate a jpg 90 degrees clockwise, width greather than height"><![CDATA[
	mogrify -rotate "90>" myfile.jpg]]></sc>

<sc name="Rotate a jpg 90 degrees clockwise, width less than height"><![CDATA[
	mogrify -rotate "90<" myfile.jpg]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Kernel">
<!-- ********************************************************************* -->

<sc name="View the startup messages"><![CDATA[
	dmesg ]]></sc>

<sc name="Slow down the boot process so you can see what happens"><![CDATA[
	Add 'confirm' (no quotes) to the lilo command line:
	Example, At the lilo promp:
	
	LILO: vmLinuz confirm ]]></sc>

<sc name="Display all system version information"><![CDATA[
	uname -a ]]></sc>

<sc name="Display only the kernel version string"><![CDATA[
	uname -r ]]></sc>

<sc name="Specify the root device on a boot floppy"><![CDATA[
	rdev /dev/fd0 /dev/hda7 ]]></sc>

<sc name="Show the root device for an image file"><![CDATA[
	rdev anImageFile ]]></sc>

<sc name="Set the root device for an image file"><![CDATA[
	rdev anImageFile /dev/hda7 ]]></sc>
	
<sc name="Add a device entry"><![CDATA[
	mknod /dev/name type major minor
	Where type is p b c or u ]]></sc>

<sc name="Make a ramdisk root file system image with support for PCMCIA"><![CDATA[
	pcinitrd --all myInitrdFile ]]></sc>

<sc name="Mount a RAM disk root file system image so you can poke around inside"><![CDATA[
	mount -t ext2 -o loop myInitrdFile /mnt/initrd
	
	(You have to gunzip compressed images first) ]]></sc>

<sc name="Core dump file size"><![CDATA[
	ulimit -c <size>

	You can disable core dumps by putting "ulimit -c 0" in
	/etc/profile ]]></sc>
	
<sc name="Controlling PCMCIA slots"><![CDATA[
	cardctl { suspend, resume, status, eject, insert } slot#
	cardinfo 		# X interface for cardctl ]]></sc>

<sc name="Copy raw kernel image to floppy device (obscure way)"><![CDATA[
	dd if=/boot/vmlinuz of=/dev/fd0 bs=8192 ]]></sc>

<sc name="DOS command to boot with a compressed RAM disk root file system"><![CDATA[
	loadlin vmlinuz initrd=myGZippedFileSystemImage ]]></sc>

<sc name="Change a dynamic kernel parameter (example)"><![CDATA[
	echo anInteger > /proc/sys/kernel/file_max ]]></sc>

<sc name="Update module dependancies after editing /etc/modules.conf"><![CDATA[
	depmod -a ]]></sc>

<sc name="Tell lilo you have edited lilo.conf"><![CDATA[
	lilo ]]></sc>

<sc name="Tell the kernel to flush the write-behind cache"><![CDATA[
	sync ]]></sc>
	
<sc name="Write something in the system log (Great for system script debugging)"><![CDATA[
	logger -t MyProgram "This is a message"
	
	Also see "man initlog" for debugging init.d scripts. ]]></sc>

<sc name="Building a new kernel"><![CDATA[
	Update /usr/src/linux symbolic link to point at sources. 
	Go into /usr/src/linux
	Backup .config to a safe place if you want to keep a copy.
	
		make mrproper (Will delete old .config)
		
		make xconfig (Fill in the blanks and write the .config file)
		OR Copy in an old .config file and do:
		make oldconfig
		
	Edit the Makefile to bump the version number!
	
		make dep clean bzImage install ;
		make modules modules_install
	
	If your root device has a modular driver
	you will need an initial ram disk at boot time.
	For kernel/module version set xx.yy.zz use:

		mkinitrd /boot/initrd-xx.yy.zz xx.yy.zz	

	This will build a ramdisk file system image that contains
	all the loadable modules for block devices described in your
	/etc/conf.modules file. See also pcinitrd for PCMCIA boot
	devices.

	Add another entry for your old kernel to lilo.conf & run lilo.
	Move any modules you don't build (like dpc)
	Some versions of gcc are not compatible with some kernels.
	Redhat supplies a "kgcc" for these systems. ]]></sc>

<sc name="Update PCMCIA"><![CDATA[
	OBSOLETE: This is part of the kernel make process now!
	Preserve the Redhat-modified /etc/pcmcia/network script.
	In the pcmcia-cs source directory:
	
		make clean config
	
	Answer the questions: Symbols from the source tree and
	don't say yes to the plug & play bios question.
	
		make all install
	
	Restore the redhat version of /etc/pcmcia/network ]]></sc>

<sc name="Patch a kernel"><![CDATA[
	Put the patch file in /usr/src (above 'linux') and cd there.
	Then:

	patch -s -p0 < patchfile ]]></sc>

<sc name="Test a patch before you apply"><![CDATA[
	Add the --dry-run option ]]></sc>

<sc name="Copy raw kernel image to make a bootable floppy device"><![CDATA[
	cp zImage /dev/fd0 ]]></sc>

<sc name="Cross compiling a kernel"><![CDATA[
	Build cross versions of binutils and gcc:
	Define the appropriate CROSS_COMPILE prefix and
	use ./config & make as usual.
	Make a separate copy of kernel sources.
	Don't update the /usr/src/linux symbolic link.
	The /usr/src/linux must point to your host kernel source.
	Edit the Linux Makefile in the new kernel sources. 
	The CROSS_COMPILE must match the one used for the
	binutils & gcc. Example:

		ARCH := ppc
		CROSS_COMPILE =powerpc-linux-
		
	Proceed as usual. ]]></sc>

<sc name="Re-lilo a linux boot partition that is not the running system"><![CDATA[
	The need for this arrises when you forget to lilo a new kernel.
	Boot from a CD or floppy, mount the target Linux partition. Then:

	chroot linuxPartition lilo ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Keyboard">
<!-- ********************************************************************* -->

<sc name="Redefine the backspace/delete key"><![CDATA[
	Used when telneting to unusual systems

	stty erase <press a key> ]]></sc>

<sc name="Show the keycodes as you press keys"><![CDATA[
	showkey ]]></sc>

<sc name="Turn on autorepeat (Sometimes it goes away...)"><![CDATA[
	xset r ]]></sc>

<sc name="Restore default backspace key operation"><![CDATA[
	xmodmap -e "keycode 22 = BackSpace" ]]></sc>

<sc name="Restore default delete key operation"><![CDATA[
	xmodmap -e "keycode 107 = Delete" ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Logical volumes">
<!-- ********************************************************************* -->

<sc name="Terminology"><![CDATA[
	Physical Volume - A whole disk or a partition on a disk.
	Volume Group - A collection of physical volumes.
	Logical volume - A "partition" on a Volume Group. ]]></sc>

<sc name="Getting started"><![CDATA[
	If LVM has never been used on a system, first run
	vgscan to create the /dev directory and other structures.
	
	Each partition must have a partition type of 0x8E. (Use fdisk)
	(This does not apply if you are using a whole disk.) ]]></sc>

<sc name="Specifying size"><![CDATA[
	For the commands that follow, the size may have a suffix:

	None	filesystem blocks
	s	512 byte sectors
	K	Kilobytes
	M	Megabytes
	G	Gigabytes ]]></sc>

<sc name="Define each physical volume"><![CDATA[
	pvcreate /dev/hdb	# A whole disk
	pvcreate /dev/hda3	# A partition 
	
	An error may be reported if you try to create a physical
	volume from a whole disk that had partitions defined.
	To destroy the partition table for a whole disk:
	
	dd if=/dev/zero of=/dev/hdb bs=1K count=1
	blockdev --rereadpt /dev/hdb ]]></sc>

<sc name="Create a volume group using several physical volumes"><![CDATA[
	vgcreate myVG /dev/hdb /dev/hda3

	Note: If you are using devfs, you must use the whole physical name
	not just the symbolic link in /dev. For example:
	/dev/ide/host0/bus0/target0/lun0/part1 ]]></sc>

<sc name="Extend a volume group by adding another physical volume"><![CDATA[
	vgextend /dev/myVG /dev/hda5 ]]></sc>

<sc name="Reduce a volume group by removing a physical volume"><![CDATA[
	This can be done live, but first you have to make sure
	all the extents in use on the physical volume are moved
	to other physical volumes in the group. For example, to move
	everything off partition hda3:

		pvmove /dev/hda3

	Now it is safe to remove the physical volume:

		vgreduce /dev/myVG /dev/hda3 ]]></sc>

<sc name="Remove a volume group"><![CDATA[
	Make sure everything is unmounted, then:

		vgremove myVG ]]></sc>

<sc name="Create a  logical volume"><![CDATA[
	lvcreate --size 200M --name myVol myVG

	You can now use this logical volume like a normal partition

	mkfs -t ext2 /dev/myVG/myVol
	mount -t ext2 /dev/myVG/myVol /mnt/myMP ]]></sc>

<sc name="Extend a logical volume to a specific size"><![CDATA[
	lvresize --size 12G /dev/myVG/myVol 

	Does NOT extend the size of the file system! ]]></sc>

<sc name="Extend a logical volume by adding a specific size"><![CDATA[
	lvresize --size +1G /dev/myVG/myVol 
	
	Does NOT extend the size of the file system! ]]></sc>

<sc name="Extend the file system to fill an enlarged logical volume"><![CDATA[
	You have to unmount first
	
		umount /mnt/myMP
		
	Check the filesystem (It makes you do this before the resize)
		
		e2fsck -f /dev/myFG/myVol
		
	Resize the file system to take up all the available space

		resize2fs /dev/myVG/myVol ]]></sc>

<sc name="Reduce the size of a logical volume"><![CDATA[
	First check the filesystem 
	
		e2fsck -f /dev/myVG/myVol

	This would be a good time to do a backup...

		TBD
	
	Resize the file system:

		resize2fs /dev/myVG/myVol newSize 
	
	Resize the volume:

		lvresize --size newSize /dev/myVG/myVol

	Before reducing the volume, lvresize will shout a scary warning
	which you may disregard if your calculations are correct. ]]></sc>

<sc name="Activate all volume groups at boot time"><![CDATA[
	vgscan
	vgchange --available y ]]></sc>

<sc name="Remove a logical volume"><![CDATA[
	umount /mnt/myMP
	lvchange --available n /dev/myVG/myVol
	lvremove /dev/myVG/myVol ]]></sc>

<sc name="Remove a volume group"><![CDATA[
	Make sure all the logical volumes are unmounted!
	vgchange --available n /dev/myVG 
	vgremove /dev/myVG ]]></sc>

<sc name="Snapshots"><![CDATA[
	A snapshot lets you do a backup of the instantanious state of
	a logical volume. You create a snapshot, back it up, and then
	delete the snapshot. Conceptually, the snapshot is a copy of the
	whole drive frozen in time.

	How to do an rsync backup of "myVol" using a snapshot:
	
		lvcreate --size 200M --snapshot --name snapVol /dev/myVG/myVol
		mount -t ext2 /dev/myVG/snapVol /mnt/snap
		rsync -a --delete /mnt/snap/ /mnt/backups/myVol
		umount /mnt/snap
		lvremove /dev/myVG/snapVol

	The neat thing about this is that the size of snapVol can be
	much smaller than the size of myVol - The snapVol really contains
	only the changes being made to myVol while the snapVol exists.
	When you remove the snapVol, the changes somehow get "put back" on myVol.
	(I'm not sure if this is exactly how it works, but this is how
	it appears to work.) ]]></sc>

<sc name="Diagnostics"><![CDATA[
	pvscan                        # Display all physcial volumes
	lvscan                        # Display all logical volumes
	pvdisplay/dev/hda4            # Display the state of a physical volume
	vgdisplay/dev/myVG            # Display the state of a volume group
	lvdisplay/dev/vg1/archVol     # Display the state of a logical volume ]]></sc>
	
<sc name="My server layout"><![CDATA[
	vgscan
	pvcreate /dev/hdb
	vgcreate vg1 /dev/hdb
	lvcreate --size 30G --name backVol vg1
	lvcreate --size 40G --name archVol vg1
	lvcreate --size  4G --name tempVol vg1
	mkfs -t ext2 -j /dev/vg1/backVol
	mkfs -t ext2 -j /dev/vg1/archVol
	mkfs -t ext2 /dev/vg1/tempVol

	pvcreate /dev/hda4
	vgcreate vg2 /dev/hda4
	lvcreate --size 5G  --name homeVol vg2
	lvcreate --size 9G  --name wwwVol vg2
	lvcreate --size 1G  --name spoolVol vg2
	lvcreate --size 3G  --name tempVol vg2
	mkfs -t ext2 -j /dev/vg2/homeVol
	mkfs -t ext2 -j /dev/vg2/wwwVol
	mkfs -t ext2 -j /dev/vg2/spoolVol
	mkfs -t ext2 /dev/vg2/tempVol ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="MySQL">
<!-- ********************************************************************* -->

<sc name="Installation"><![CDATA[
	Install the server and client rpms.
		
		rpm -i mysql-server...
		rpm -i mysql-...

	Configure for autostart at boot time

		chkconfig --del mysqld  # To clean up	
		chkconfig --add mysqld  # Add to the runlevels

	Start the service immediately

		service mysqld start
	
	Set the root password for the first time
	
		mysqladmin password firstPassword ]]></sc>

<sc name="Change the root password after installation"><![CDATA[
	Using mysqladmin:

		mysqladmin --password=oldPassword password newPassword
	
	The mysqladmin statements show here assume you are logged
	in as root. Otherwise add the parameter: --user=root

	Alternative method using the mysql client:

		update mysql.user set password=password('newpassword') where user='root';
		flush privileges; 

	Key concept: mysql usernames and passwords have 
	nothing to do with Linux usernames and passwords:
	You must explicitly authorize all mysql users.
	(See the GRANT command below.) ]]></sc>

<sc name="Login to the command line interface as a user"><![CDATA[
	mysql --user=myName --password=xxxyyy

	If you don't specify the database user name,  
	mysql will try to connect using your linux user name. ]]></sc>

<sc name="Specify a default username and password"><![CDATA[
	If you don't specify a username or password on the
	mysql command line, the values (if present) will be
	take from the configuration file.

	Edit:
		/etc/my.cnf

	Add (or edit) this section:
		
		[client]
		user=myName
		password=myPassword ]]></sc>

<sc name="Show all existing databases"><![CDATA[
	show databases ; 

	If you are not logged in as the mysql administrator,
	you will only see the databases you have privileges
	to access. ]]></sc>

<sc name="Create a new database"><![CDATA[
	It is the usual practice that only the mysql administrator
	creates new databases. From within mysql, this command line
	adds a new database:

		create database databaseName ; 

	A new database can also be created from the shell:

		mysqladmin --password=password create databaseName ]]></sc>

<sc name="Delete a database"><![CDATA[
	From inside mysql:

		drop database databaseName ;
	
	From the shell:

		mysqladmin --password=password drop databaseName

	1) You can't drop a database that some program is using. 
	
	2) On some versions of MySQL, deleting a database is more
	involved. When you try to drop a database, the "show databases"
	command will show that the database is still there. This occurs
	because some files are left in the top-level database directory.
	On Redhat/Fedora installations, the top-level database directories 
	are located in /var/lib/mysql. After the first "drop database"
	fails, delete all the debris in the top-level database directory.
	A second "drop database" command will now succeed. ]]></sc>
	
<sc name="Add a user"><![CDATA[
	Access privileges are assigned to a username/hostname combination.
	The syntax looks like an email address: "username@hostname".
	Adding a user simply means allowing a username@hostname
	to perform certain operations on all or part of one or
	more databases.

	The most typical case is to assign all privileges to 
	some user who manages the database. If this username
	and hostname are new, this operation "adds" the new
	user:

	grant all privileges
		on databaseName.*
		to username@localhost
		identified by 'aPassword' ;

	The wild card * in the example above refers to all table
	names. (Even though the database may not have any tables
	yet.) 

	The "grant" command may be used multiple times to allow
	access from other hosts or to assign different privileges
	to different tables for the same user. 

	If a user must be able to grant access to other users,
	the grant command must be used again with a special option:

	grant grant option on databaseName.* to username@localhost ;

	A user can only grant privileges to others that they
	already have on the database. ]]></sc>

<sc name="Remove a user"><![CDATA[
	Removing a user means removing the privileges of
	the username@hostname from all or part of a database:

	revoke all privileges on *.* from username@localhost
	
	If you are sure that a username@hostname has been
	revoked on all databases, you can purge the user from 
	the mysql database:

	delete from mysql.user where user='username' and host='hostname' ;
	
	flush privileges ; ]]></sc>

<sc name="Show all users allowed to access a database"><![CDATA[
	select host,user from mysql.db where db="databaseName" ; ]]></sc>

<sc name="Show all users and the databases they can access"><![CDATA[
	select host,user,db from mysql.db ; ]]></sc>

<sc name="Show all mysql users"><![CDATA[
	select host,user,password from mysql.user ; ]]></sc>

<sc name="Change a password"><![CDATA[
	set password for user@somehost.somewhere=password('newpassword') ; ]]></sc>

<sc name="Run a script to configure a database"><![CDATA[
	mysql --password=xxxyyy dataBaseName < configFile.sql ]]></sc>
		
<sc name="Select a database to use"><![CDATA[
	use dataBaseName ; ]]></sc>

<sc name="Show the tables defined in the database"><![CDATA[
	show tables ; ]]></sc>

<sc name="Describe a table (Show the column names and types)"><![CDATA[
	describe tableName ; 
	show columns from tableName ; ]]></sc>

<sc name="Create a new table in the current database"><![CDATA[
	create table pet
	(	name VARCHAR(20),
		owner VARCHAR(20),
		species VARCHAR(20)
	) ; ]]></sc>

<sc name="Common data types"><![CDATA[
	char(size)
		Fixed-length character string.
		Size is specified in parenthesis.
		Unused positions are padded with spaces.

	varchar(size)
		Variable-length character string.
		Max size is specified in parenthesis.
		Limit is 255 bytes. (1 byte size field)

	text
		A large block of variable-sized text.
		Limit is 65535 bytes. (2 byte size field)

	int	
		4 byte signed integer value.

	float
		4 byte floating point value

	date
		Date value

	time
		Time value  ]]></sc>

<sc name="Constraints"><![CDATA[
	Each column is defined by a name, data type and optional constraint.
	Example constraints:

		unique
		not null
		primary key 
		default <default_value> ]]></sc>

<sc name="Adding rows to a table from the command line"><![CDATA[
	Note the use of NUL and quotes around string values.

	insert into pet values
	(	'Puffball',
		'Diane',
		'hamster'
	) ; ]]></sc>

<sc name="Adding rows to a table from a text file"><![CDATA[
	load data local infile "pet.txt" into table pet ; ]]></sc>

<sc name="Table text file format has tab delimited fields"><![CDATA[
	# Note the use of \N for null values.

	Fido	Mary	\N ]]></sc>

<sc name="Inserting only selected column values"><![CDATA[
	insert into pet (name, owner) values ('Goober', 'George') ; ]]></sc>

<sc name="Inserting selected columns from another table"><![CDATA[
	insert into pet select (name, owner) from oldpet ; ]]></sc>

<sc name="Copy a row"><![CDATA[
	insert into pet(owner, species) select owner, species from table where name="Puffball" ; 

	Note that we must leave out the 'name' column or we'll have a duplicate.
	To fix the name (which will be null) use:
	
	update pet set name="Marvin" where name is null ; ]]></sc>

<sc name="Deleting a row"><![CDATA[
	delete from pet where name = 'Puffball' ; ]]></sc>

<sc name="Delete all rows"><![CDATA[
	delete from pet ]]></sc>

<sc name="Deleting a table and all the data"><![CDATA[
	drop table tableName ]]></sc>

<sc name="Modify an existing row"><![CDATA[
	update tableName set columnName1=value1, columnName2=value2,...
	where optionalConditions ; 

	update pet set species="alien" where name="Leo" ; ]]></sc>

<sc name ="Modify rows using values and conditions from multiple tables"><![CDATA[
	update table1, table2,...,tableN
	set table1.column1=table2.column2,...
	where optionalConditions ;

	update new,old set new.email=old.value 
	where new.name=old.name and old.type="Email"; ]]></sc>

<sc name="Modify a table"><![CDATA[
	alter table tableName add newColumnName dataType
	alter table tableName add newColumnName dataType first
	alter table tableName add newColumnName dataType after otherColumnName
	alter table tableName drop columnName  
	alter table tableName modify columnName newDataType
	alter table tableName modify columnName dataType first
	alter table tableName modify columnName dataType after otherColumnName
	alter table tableName change oldColumnName newColumnName dataType
	alter table oldTableName rename newTableName 
	alter table tableName alter columnName set default someValue ]]></sc>

<sc name="Change the column order"><![CDATA[
	alter table tableName modify column columnName dataType after otherColumnName
	alter table tableName modify column columnName dataType before otherColumnName
	alter table tableName modify column columnName dataType first

	This is not-destructive, but you must supply the correct dataType for the column. ]]></sc>

<sc name="Looking things up in the database"><![CDATA[
	select <what to select> from <which table> where <conditions>

	<what to select> a list of columns or * for all columns

	select * from pet ]]></sc>

<sc name="Reload the whole table from a text file"><![CDATA[
	set autocommit=1;  # Used for quick re-create of the table
	delete from pet;
	load data local infile "pet.txt" into table pet ; ]]></sc>

<sc name="Selections"><![CDATA[
	select * from pet where name = "Bowser" ;
	select * from pet where species = "dog" and owner = "smith" ;
	select name, birth from pet;
	select owner from pet ;
	select name, owner from pet where species in ('dog', 'cat') ;
	select distinct owner from pet ;
	select name, birth from pet order by owner ;
	select name, birth from pet order by birth desc ;
	select name, species, birth from pet order by species, birth desc ;
	select pet.name, pet.age, employee.salary, employee.title
		from pet, employee where pet.name = "Bugsy"; ]]></sc>

<sc name="Enable remote access"><![CDATA[
	The configuration file must be changed so the daemon mysqld will
	listen on a tcp interface rather than just the local socket.

		/etc/my.cnf:
			...
			bind-address=myserver.mydomain.com
			...

	In the example shown above, the dns name must resolve to an
	ip address other than 127.0.0.1.

	You'll need to restart the service:

		service mysqld restart

	Next the individual database users must be granted network access:

		grant all privileges
			on databaseName.*
			to username@lclient.somedomain.com
			identified by 'aPassword' ;

	In this expression, client.somedomain.com is the machine
	where the database connection and queries will originate. ]]></sc>

<sc name="Testing remote access"><![CDATA[
	From the remote system (with mysql client installed) execute:

		mysql -u remoteUser -h remoteHostIP -p

	The -p will make it prompt for the remoteUser's password. ]]></sc>

<sc name="Backup a database"><![CDATA[
	mysqldump --user=userName --password=aPassword --host=hostName \
		dbName > backupFile.sql ]]></sc>

<sc name="Restore a backup"><![CDATA[
	Create an empty database with the same name and privileges.
	Next:
		use yourDatabase ;
		source backupFile.sql ;
	
	Or from the shell:
	
		mysql --user=userName --password=aPassword --host=hostName \
			dbName < backupFile.sql ]]></sc>

<sc name="Reset the root password"><![CDATA[
	Create a text file with two lines:

		UPDATE mysql.user SET Password=PASSWORD('myNewPassword') WHERE User='root';
		FLUSH PRIVILEGES;

	Save this as:

		mysql-reset.sql

	Stop the sql server.

	Restart the server from the command line using this form:

		mysqld --init-file=mysql-reset.sql
	
	The name of the server will vary. Examples:

		Windows: mysqld.exe
		Linux: mysqld_safe

	Now restart the server in the usual way.  ]]></sc>

<sc name="Weirdness with localhost"><![CDATA[
	After performing a grant to someuser@localhost, you may
	find that an external application configured to access the
	database will not be able to connect.
	
	Many Linux configurations will have an /etc/hosts file that contains:
		
		127.0.0.1 myname.mydomain myalias localhost.localdomain localhost
	
	When DNS (named) is not configured and running, the /etc/hosts file
	is used for forward and reverse lookups. It appears that many
	programs do some sort of security checking before connecting to MySQL
	by looking up "localhost" and then doing a reverse lookup on the
	result. The reverse lookup on "127.0.0.1" using the /etc/hosts file
	shown above will yield: "myname.mydomain.com". This string gets
	used when connecting to MySQL, which fails because it doesn't match
	the string "localhost" in the SQL grant expression.
	
	To fix this (only for machines without DNS), I suggest that  
	/etc/hosts contain:
	
		127.0.0.1 localhost localhost.localdomain myname myname.mydomain
	
	In other words, make sure localhost is the first name.
	A better solution is to run DNS... (See the DNS section) ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="PostgreSQL">
<!-- ********************************************************************* -->

<sc name="Installation"><![CDATA[
	Install the server and client rpms
		
		yum install postgresql
		yum install postgresql-server

	Initialize the database

		service postgresql initdb

	Configure for autostart at boot time

		chkconfig postgresql on

	Start the service

		service postgresql start ]]></sc>

<sc name="Run the client"><![CDATA[
	psql ]]></sc>

<sc name="Meta commands"><![CDATA[
	\h 	    Help with SQL
	\?	    Help with psql
	\q	    Quit
	\l	    SHOW DATABASES
	\d	    SHOW TABLES 
	\d table    SHOW COLUMNS ]]></sc>

<sc name="SQL expressions to show databases, tables, and columns"><![CDATA[
	SELECT yourDatabase FROM pg_database ;

	SELECT table_name FROM information_schema.tables
		WHERE table_schema='public';

	SELECT column_name FROM information_schema.columns
		WHERE table_name='yourTable'
		ORDER BY ordinal_position ;
	
	The ORDER BY clause is optional and will display
	the columns in the order they were defined. ]]></sc>

<sc name="Log file"><![CDATA[
	/var/lib/pgsql/data/pg_log ]]></sc>

<sc name="Tutorials and manual"><![CDATA[
	http://www.postgresql.org/docs/8.0/static/index.html ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Networking">
<!-- ********************************************************************* -->

<sc name="Start/stop a network device"><![CDATA[
	ifup <interface>
	ifdown <interface> 
	
	These commands are scripts that automatically set up all
	the ip parameters and take care of special cases
	such as PPP, PPPoE, DHCP, firewalls and others.
	In Redhat-like systems, extra implicit parameters go in:

		/etc/sysconfig/network
		/etc/sysconfig/network-scripts/ifcfg-<interface> ]]></sc>

<sc name="Show or configure interface parameters"><![CDATA[
	ifconfig		# Show params for active interfaces
	ifconfig -a		# Show params including inactive interfaces
	ifconfig <interface>	# Show params for a specific interface
	
	ifconfig <interface> \  # Set params and start the interface
		address <ipaddress> \
		netmask <mask> \
		broadcast <address> \
		metric <ametric>
		
	The ifconfig command directly configures and starts the interface.
	It is up to you to take care of routing and other issues. ]]></sc>

<sc name="Show and modify routing tables"><![CDATA[
	route -n		# List numbers, not names
	route add default <dev>	# Add a default route
	route delete <dev>	# Remove a route ]]></sc>

<sc name="Export NFS files systems after editing /etc/exports"><![CDATA[
	exportfs -r ]]></sc>

<sc name="Display TCP/IP traffic"><![CDATA[
	Show all traffic from all interfaces

		tcpdump -i all

	Show all traffic on a specific interface:

		tcpdump -i eth0 

	Show all traffic from a specific host:

		tcpdump host <host>

	Only input from the host:

		tcpdump src <host>
	
	When using src or dst, you may also specify a port:

		tcpdump src <host> port 80

	Only ouput to the host

		tcpdump dst <host>

	The first parameter to tcpdump can be the name of a protocol:

		tcpdump icmp host <host>

		The protocol may be: tcp, udp, or icmp
		
	If you run this from a remote session, you will want
	to ignore your own session:

		tcpdump -i eth0 not $myAddress 

	You  can send output to a file:

		tcpdump ... -w aFile.txt

	Youu can play the file back into tcpdump:

		tcpdump -r aFile.txt

	The interface will expose more information if it operates
	in promiscuous mode:

		ipconfig eth0 promisc

	You will want to turn this off after debugging:

		ipconfig eth0 -promisc ]]></sc>

<sc name="Restart xinetd after you edit /etc/xinetd.d files"><![CDATA[
	killall -HUP xinetd ]]></sc>

<sc name="Configure a tftp directory path"><![CDATA[
	Add the path as a parameter to the tftp daemon in inetd.conf ]]></sc>

<sc name="Run a command on another computer"><![CDATA[
	ssh user@remoteMachine anyCommand

	Any text output from the command will be displayed locally.
	You must have appropriate keys configured. ]]></sc>
	<p indent="4">See the <link name="SSH" sec="SSH"/> section for details.</p>
	
<sc name="Return the ip information about a host"><![CDATA[
	host hostName
	dig hostName
	nslookup hostName <dnsServerName>
	ping hostName
	ping ipAddress ]]></sc>

<sc name="Show all connections"><![CDATA[
	netstat -vat ]]></sc>

<sc name="Show only external internet connections"><![CDATA[
	netstat -n --inet ]]></sc>

<sc name="Show numerical ports, tcp connections, associated processes"><![CDATA[
	netstat -ntp ]]></sc>

<sc name="Show which processes on localhost are listening for connections"><![CDATA[
	netstat -tupl ]]></sc>

<sc name="Show which ports on any host are listening for connections"><![CDATA[
	nmap -sT hostName ]]></sc>

<sc name="Obtain and install network configuration from a DHCP server"><![CDATA[
	dhclient -nw ]]></sc>

<sc name="Show or configure a wireless interface"><![CDATA[
	iwconfig		   # Show params for active interfaces
	iwconfig eth0 essid GOOB   # Set the network name to GOOB  
	iwconfig eth0 key 43224598a34bc2d457e2	# Specify a hex WEP key 
	iwconfig eth0 key s:ThisIsAnAsciiPassphrase ]]></sc>

<sc name="Show or modify ethernet connection settings"><![CDATA[
	Show all settings:

		ethtool eth0

	Show the speed:

		ethtool eth0 | grep Speed 

	Show duplex setting:

		ethtool eth0 | grep Duplex

	Modify duplex setting:

		ethtool -s eth0 duplex half
		ethtool -s eth0 duplex full 

	Change several settings at once:

		ethtool -s eth0 speed 100 autoneg off ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="OpenSSL">
<!-- ********************************************************************* -->

<sc name="Create an rsa key set"><![CDATA[
	openssl genrsa -des3 -out server.key 1024 ]]></sc> 

<sc name="Create an open version of the key"><![CDATA[
	openssl rsa -in server.key -out server.key.open

	This is the key file required by apache and sendmail. ]]></sc> 

<sc name="Create a certificate signing request"><![CDATA[
	This is essentially your certificate in the unsigned form.

	openssl req -new -key server.key -config openssl.conf -out server.csr

	You get pestered for a description of your business.
	The important thing is the "Common Name": That is the domain name
	you want certified.

	Common name example: myhost.mydomain.com ]]></sc> 

<sc name="Sign the certificate"><![CDATA[
	This step uses your key to sign the certificate:
	(An alternative is to pay to have an agency sign it. See below.)

	openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

	You can install this in apache, sendmail and other applications.
	The clients will complain that the certificate cannot be verified
	because there is no chain of trust. Most applications will let you
	add the certificate to the local database anyway. Then you won't
	be troubled. ]]></sc> 

<sc name="View your certificate"><![CDATA[
	openssl x509 -in server.crt -noout -text ]]></sc> 

<sc name="Create a certificate authority (CA) to sign your certificate"><![CDATA[
	This is an alternative way to sign your server.csr.
	It introduces the concept of a  certificate authority.

	A "real" purchased certificate will be signed by an
	authority already known to the client operating system
	such as Thwait, Verisign, or GoDaddy.

	Creating your own certificate authority won't save you
	from having the client applications nag the user about
	an untrusted certificate. But the client can choose to
	install the new certificate authority as "trusted."
	This has the small advantage that all other certificates
	you sign with the same CA will be accepted by that client
	without complaints.  ]]></sc> 

<sc name="Create an rsa key set for the new certificate authority"><![CDATA[
	openssl genrsa -des3 -out server-ca.key 4096

	The common name you use CANNOT be the same as the name
	used in the certificates you want to sign.

	Example: authority.csparks.com ]]></sc> 

<sc name="Create a CA certificate"><![CDATA[
	openssl req -new -x509 -days 365 -key server-ca.key -out server-ca.crt ]]></sc> 

<sc name="Sign your server.csr using server-ca.crt"><![CDATA[
	openssl x509 -req -days 365 -in server.csr -CA server-ca.crt -CAkey server-ca.key -set_serial 01 -out server.crt
	
	This replaces your old self-signed server.crt ]]></sc> 

<sc name="Use a real certificate authority"><![CDATA[
	Proceed as above to create a certificate signing request.
	Then pay an agency to sign it and send it back. I've used
	GoDaddy, which is easy and inexpensive. You get back
	two files:

		your.domain.com.crt
		gd_bundle.crt

	The first is your certificate, signed with your private key and
	signed again by godaddy's private key. Someone who wants to
	deal with you can decrypt the certificate using godaddy's
	public key followed by your public key. The proves that
	you signed it and that godaddy (hopefully) took pains to
	verify your identity.

	The gd_bundle.crt file contains the certificate authority path
	for godaddy.]]></sc>

<sc name="Test a commercial certificate for validity"><![CDATA[
	openssl verify -CAfile gd_bundle.crt your.domain.com.crt ]]></sc>

<sc name="Test a certificate with the openssl server"><![CDATA[
	Run the openssl server:

		openssl s_server -cert server.crt -key server.key -www

	If the server starts quietly, all is probably well.
	Visit the server on your local LAN with the URL:

		https://yourserver:4433

	In the url, "yourserver" should be the name the cert certifies.
	You should see a page full of information about openssl and
	your certificate. ]]></sc>

<sc name="Test an ssl server from the client side"><![CDATA[
	Run the server side program. (whatever...)
	On the client side:

		openssl s_client -connect your.server.com:your_port -crlf

	Now you can type plain text commands and see the responses.  ]]></sc>

</s>


<!-- ********************************************************************* -->
<s name="Partitions">
<!-- ********************************************************************* -->

<sc name="Managing partitions with the parted utility"><![CDATA[
	Partitions must not be mounted while being changed.
	Run from a bootable floppy or CD if you need to alter 
	the root or any other partition that can't be
	unmounted while running the normal system.

	Parameters for <start> <end> and <size> are floating
	decimal numbers. When creating adjacent partitions,
	the <end> of the last partition should match the
	<start> of the next.

	Use df to see how much space is used if you intend
	to shrink a working partition. You must take care of
	shrinking the file system before you attempt to shrink
	the partition itself. ]]></sc> 

<sc name="Partition types (PART-TYPE)"><![CDATA[
	primary, logical, extended 

	The partition types extended and logical are only
	used with the msdos PART-TYPE. It is a concept
	needed by Windows to support more than four partions
	on a disk. ]]></sc>
		
<sc name="Common file system types (FS-TYPE)"><![CDATA[
	ext2, ext3, linux-swap, reiserfs, fat16, fat32, HFS, NTFS ]]></sc>
	
<sc name="Flags"><![CDATA[
	Flags are used to indicate other attributes of a partition.

		set partitionNumber, flag, [on | off] 

	The flags :

		boot   : The partition is bootable.
		lba    : Tells Windows that linear addression is used.
		swap   : Linux swap space
		hidden : Hide the partition from Windows
		raid   : Linux RAID partition
		LVM    : Linux logical volume manager 
		PALO   : Mark for use by Linux/PA-RISC boot loader
		PREP   : PowerPC PReP boot partition ]]></sc>
		
<sc name="Show the current layout"><![CDATA[
	print ]]></sc>
		
<sc name="Create an unformatted partition"><![CDATA[
	mkpart ptype start end ]]></sc>
		
<sc name="Create a new primary ext2 partition"><![CDATA[
	mkpartfs ptype ftype start end ]]></sc>
	
<sc name="Remove a partition"><![CDATA[
	rm pnumber ]]></sc>
		
<sc name="Change the partition state flag"><![CDATA[
	set pnumber flag state ]]></sc>
		
<sc name="Perform a simple check"><![CDATA[
	check pnumber ]]></sc>

<sc name="Make a new partition table (Destroys the whole disk)"><![CDATA[
	mklabel type 

	Linux can create file systems on disks that don't have
	partitions, but a partition table is necessary when sharing
	a disk with Windows. ]]></sc>

<sc name="Label types"><![CDATA[
	msdos, bsd, mac, pc98, sun, loop ]]></sc>
	
</s>

<!-- ********************************************************************* -->
<s name="Patch">
<!-- ********************************************************************* -->

<sc name="Create a patch file"><![CDATA[
	oldVersion	# Path to the unmodified files
	newVersion	# Path to the modified files

	diff -rN oldVersion newVersion > patchFile

	-r	Perform diff recursively
	-N	Support creating new files ]]></sc>

<sc name="Apply a patch file"><![CDATA[
	You should be in the directory above oldVersion:

	patch -u -s -p0 < patchFile

	-s	Silent
	-p0	Don't modify file path names in the patch
	-pN	Remove first N components of file path names
	-d p	Switch to the directory named by p ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Perl">
<!-- ********************************************************************* -->

<sc name="Install CPAN"><![CDATA[
	Perl has it's own "module" (package) manager called CPAN.
	It is only necessary to use CPAN if there
	is no perl-XXXX rpm available, so first try using

		yum list perl-XXXX

	To install CPAN:
	
		yum install perl-CPAN

	I found that perl wanted this as well:

		yum install perl-YAML ]]></sc>
	
<sc name="Install modules using CPAN"><![CDATA[
	One-line command:

		perl -MCPAN -e 'install XXXX::YYYY'

	If you have several modules to install or want confirmations
	you can enter the CPAN shell:

		perl -MCPAN -e shell
	
	Ask for confirmations:

		o conf prerequisites_policy ask

	Install the module(s)

		install XXXX::YYYY 
		install PPPP::QQQQ
		... ]]></sc>
			
<sc name="List installed modules"><![CDATA[
	perldoc perllocal ]]></sc>
			
<sc name="Building and installing a package by hand"><![CDATA[
	You need to do this if you have downloaded and upacked a 
	package by hand. Navigate into the directory and execute:

		perl Makefile.PL;
		make
		make test
		su
		make install ]]></sc>
</s>
	
<!-- ********************************************************************* -->
<s name="Printing">
<!-- ********************************************************************* -->

<sc name="Print a file on the default printer"><![CDATA[
	lpr myfile ]]></sc>

<sc name="Print a file on a selected printer"><![CDATA[
	lpr -P printer myfile ]]></sc>

<sc name="Show a list of available printers"><![CDATA[
	lpstat -p ]]></sc>
	
<sc name="Show the default printer"><![CDATA[
	lpstat -d ]]></sc>

<sc name="Set the default printer for the current user"><![CDATA[
	lpoptions -d LaserJet ]]></sc>
		
<sc name="Set the default printer for everyone"><![CDATA[
	lpadmin -d LaserJet ]]></sc>
		
<sc name="Show what's on the print queue"><![CDATA[
	lpq ]]></sc>
	
<sc name="Remove a job from the print queue"><![CDATA[
	lprm nn ]]></sc>
	
<sc name="Remove all jobs queued by the user"><![CDATA[
	lprm - ]]></sc>
	
<sc name="Control the printers (has help for commands)"><![CDATA[
	lpc  ]]></sc>

<sc name="Web interface for CUPS"><![CDATA[
	http://localhost:631 ]]></sc>
		
<sc name="Configure a remote Windows printer"><![CDATA[
	Determine the remote printer name:

		smbclient -L hostname -U%

	If a username and password are required by the host, use:

		smbclient -L hostname -U username%password
 
	(In this case, the printer was called "Deskjet")

	1) Device: Windows Printer via Samba
	2) URI:    smb://username:password@sparksvaio/Deskjet
	3) Driver: HP New Deskjet Series Cups v1.1 (en) ]]></sc>
		
<sc name="Configure a local printer-port printer"><![CDATA[
	1) Device: Parallel Port #1 (Hewlett-Packard HP LaserJet 4000 Series) 
	2) Driver: HP LaserJet Series CUPS v1.1 (en) ]]></sc>
		
<sc name="CUPS directory for manufacturer's ppd files"><![CDATA[
	/usr/share/cups/model ]]></sc>

<sc name="CUPS ppd files added by me"><![CDATA[
	hp4000.ppd.gz
	hp970Cse.ppd
	
	These came from the sourceforge project sponsored by HP.
	The hp970Cse.pdd requires foomatic which requires a TON of
	perl stuff. If you don't want all this, the cups built-in
	"New Deskjet" works fine. ]]></sc>

<sc name="Fixing the the Samba rec_read bad magic 0x0 error"><![CDATA[
	This is caused by a bug that has been in Samba for 
	many years. It is evidently nearly impossible to
	fix in the Samba code. Fortunately, there is an easy
	work-around to clear up the problem. Stop the samba
	service and delete all the .tbd files in the printer
	cache:
		service smb stop
		rm -rf /var/cache/samba/printer/*.tbd
		service smb start ]]></sc>

<sc name="Configure printers on a Linksys print server"><![CDATA[
	1) Select LPD/LPR Protocol.
	2) Device URIs for each port:
	
		lpd://Sc0405b5/L1
		lpd://Sc0405b5/L2

	3) Select the drivers
	
		HP New Deskjet Series Cups v1.1 (en)
		HP LaserJet 4000 Series  PS (en)  ]]></sc>
		
<sc name="Dealing with Vista/Windows 7 connection errors"><![CDATA[
	Newer versions of Windows refuse to connect to some-but-not-all
	Linux/CUPS printers. The error message includes the code: 0x000006d1.
	The fix is not obvious: Using the Add Printer dialog:

		Add a local printer.
		Select "Create a new port".
		Select "Local port".
		For the port name, enter the Samba path, e.g.:
			
			\\server\hp3600

		Select the right driver in the usual way. ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Processes">
<!-- ********************************************************************* -->

<sc name="Show the current process list"><![CDATA[
	ps ax ]]></sc>

<sc name="Kill a process by name"><![CDATA[
	killall name ]]></sc>

<sc name="Kill a process by id number"><![CDATA[
	kill pid ]]></sc>

<sc name="Kill a process that is being difficult"><![CDATA[
	kill -s 9 pid ]]></sc>

<sc name="Run a command in the background"><![CDATA[
	command & ]]></sc>

<sc name="Put an active command into the background"><![CDATA[
	First break with control Z, then 
	
	bg ]]></sc>

<sc name="List all the jobs you have running"><![CDATA[
	jobs ]]></sc>

<sc name="Bring a job back to the forground"><![CDATA[
	fg ]]></sc>

<sc name="Stop a background job"><![CDATA[
	kill ]]></sc>

<sc name="Suspend a backgroud job"><![CDATA[
	stop ]]></sc>

<sc name="Fix terminal that has fonts garbled by a binary dump"><![CDATA[
	Just type: <control>V <control>O ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Programming">
<!-- ********************************************************************* -->

<sc name="Compile and link a C program"><![CDATA[
	cc file1.c file2.c file3.c -o program]]></sc>

<sc name="Compile for subsequent linking"><![CDATA[
	cc -c file.c   # Produces file.o by default ]]></sc>

<sc name="Link compiled modules"><![CDATA[
	ld file1.o file2.o file3.o -o result ]]></sc>

<sc name="Create a dynamically linkable library"><![CDATA[
	This library can be used with dlopen, dlclose, dlsym:
	cc -rdynamic -c test.c -o test.o
	ld -shared test.o -o test.so ]]></sc>

<sc name="Debug with gdb"><![CDATA[
	gdb aProgram    # Start gdb and select the program
	file aProgram   # Specify or change the program in gdb
	attach pid      # Attach to a running process
	cd              # Change directories
	pwd             # Show working directory
	directory path  # Add a source file directory
	list <line>     # List source starting at line
	list l1,ln      # List source from l1 to ln
	list            # No <line> continues listing
	break <line>    # Set breakpoint
	clear <line>    # Clear breakpoint
	run p1 p2 ...   # Start program with parameters
	start           # Start program and break at main()
	step            # Step into
	next            # Step over
	quit            # Exit debugger
	continue        # Continue from break
	print expr      # Show value of expression
	display expr    # Print value at each break
	backtrace       # Show the calling stack 
	edit <loc>	# Edit a file at the location
	
	Examples of locations:
	
	234             # A line number
	myfun           # A function
	myFile.c:234    # A line in a source file
	myFile.c:myfun  # A function in a file ]]></sc>
	
<sc name="Show the libraries used by a program"><![CDATA[
	ldd <program> ]]></sc>

<sc name="List all the symbols defined by an object file"><![CDATA[
	nm <objfile> ]]></sc>

<sc name="Ask dynamic linker to scan for new libraries"><![CDATA[
	ldconfig ]]></sc>

<sc name="Check out a module with CVS"><![CDATA[
	export CVSROOT=":pserver:anonymous@cvs.computer.com:/var/cvsroot"
	cvs login
	
	Answer the password prompt.
	Then cd to the local diretory where you want the source.	
	Check out the files:
	
	cvs -z3 checkout name ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="RAID">
<!-- ********************************************************************* -->

<sc name="Linux software RAID levels"><![CDATA[
	linear:
		Combines several disks into one big disk: "JBOD" (Just a Big Old Disk)
	raid0:
		Block-level striping without parity or mirroring.
		Used to get speed.
		At least two drives are required.
		No safety.
	raid1:
		Mirroring without parity or striping.
		Used to get safety.
		At least two drives are required.
		Can recover if one drive fails.
		Slightly slower than one disk.
	raid4:
		Block-level striping with dedicated parity.
		At least three drives are required.
		One only holds parity information.
		Uses less space that total mirroring. (raid1)
		Can recover from one drive failure.
	raid5:
		Block-level striping with distributed parity.
		Like raid4, but parity information is distributed between all drives.
		Can recover from any one drive failure.
		Faster than raid4.
	raid6:
		Block-level striping with double distributed parity.
		Can recover from 2 failed drives.
	raid10:
		A mirrored data set (RAID 1) that is then striped (RAID 0).
		Used to get safety and speed.
		Normally requires 4 drives, but Linux can do it with 2. ]]></sc>

<sc name="Preparation"><![CDATA[
	In this example, we create a RAID 1 group using two drives.
	Each drive needs to have a partition of the same size and type.

	The first step is to use fdisk to create the partitions and set
	their type (id) to be 0xFD, which is the type code for
	"Linux raid autodetect".

	I'm not sure if you have to use partitions: Without them there's
	no place for the "Linux raid autodetect" but the startup process
	uses the UUID for the drives directly so that may not be necessary.

	For this example the partitions are on:

		/dev/sda1
		/dev/sdb1

	You can verify the partition types using:

		fdisk -l /dev/sda
		fidks -l /dev/sdb ]]></sc>

<sc name="Create the RAID device"><![CDATA[
	mdadm --create /dev/md0 --level=raid1 --raid-devices=2 /dev/sda1 /dev/sdb1

	This command creates the raid device md0 by combining two partitions. ]]></sc>
	
<sc name="Create a file system on the device"><![CDATA[
	mkfs -t ext3 /dev/md0 

	The /dev/md0 device behaves like any other drive. ]]></sc>

<sc name="Check the status a RAID device"><![CDATA[
	If one of the drives fails, you should get an email... (Fedora)
	To see what happened:

		mdadm --detail /dev/md0 ]]></sc>

<sc name="Check the status of all RAID devices"><![CDATA[
	cat /proc/mdstat ]]></sc>

<sc name="Puting a drive back online"><![CDATA[
	Once you've fixed or replaced a drive, (sdb1 for example) you
	have to manually add it back to the array:

		mdadm /dev/md0 -a /dev/sdb1 

	If you check the status, you'll see that the new drive is being
	"Syncronized", but you can continue using the md0 device. ]]></sc>

<sc name="RAID at boot time"><![CDATA[
	At boot time, the script:

		/etc/rc.d/rc.sysinit

	Runs this command:

		/sbin/mdadm -As --auto=yes --run

	It uses this file which describe all raid arrays:

		/etc/mdadm.conf

	Anaconda adds entries to mdadm.conf for raid arrays
	created during the installation process.
	
	Example of /etc/mdadm.conf for two RAID1 arrays

		MAILADDR root
		ARRAY /dev/md0 level=raid1 num-devices=2 UUID=<big hex mess>
		ARRAY /dev/md1 level=raid1 num-devices=2 UUID=<big hex mess> 

	The MAILADDR specifies where email will be sent when raid problems
	are detected. 

	To get your own raid arrays mounted at boot time, you have
	to add entries to mdadm.conf yourself. You can see the right
	expressions by first mounting the array and then running
	this command:

		mdadm --detail --scan --verbose 

	Just pick out the line for your new array and add it to the
	end of the configuration file: /etc/mdadm.conf ]]></sc>

<sc name="RAID vs LVM"><![CDATA[
	I like to use both. I put LVM on top of RAID: 
	RAID provides physical safety and LVM provides the flexibilty of virtual partitions.
	See the Logical Volumes section for details. ]]></sc>

<sc name="Fixing problems"><![CDATA[
	When you get a report about a mismatch count,
	for example on device md1:

	Diagnostics:

		cat /proc/mdstat
		cat /sys/block/md1/md/mismatch_cnt

	Repair:

		echo repair >/sys/block/md1/md/sync_action
		watch cat /proc/mdstat

	Recheck:

		echo check >/sys/block/md1/md/sync_action
		watch cat /proc/mdstat

	Verify:
		cat /sys/block/md1/md/mismatch_cnt

		(Should be zero now...) ]]></sc>

<sc name="Adding a disk drive"><![CDATA[
	Your supposed to be able to do this with everything online and mounted.

	For this example, we'll assume the new drive name is /dev/sde1
	and that we have a linear (JBOD) RAID array at /dev/md0.

	Using fdisk, create one partition that fills the new drive.
	Make the partition type "fd", which is the code for "Linux RAID autodetect". 

	Check the status of the array to make sure it's happy:

		mdadm --status /dev/md0

	Check the filesystem on the array to make sure it's happy:

		e2fsck -f /dev/md0

	Add the new drive:

		mdadm --grow --add /dev/md0 /dev/sde1

	Expand the filesystem to fill the new space:

		resize2fs /dev/md0

	If you didn't do it live, remount md0. ]]></sc>

<sc name="More concepts..."><![CDATA[
	There are commands to stop, start, replace, grow, add, and delete drives.
	All while the raid device is still being used! This is a Good Thing™
	For details:

		man mdadm ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Regular expressions">
<!-- ********************************************************************* -->

<sc name="Anchors"><![CDATA[
	^		Beginning of the line 
	$		End of the line 
	<		Left word boundary
	>		Right word boundary ]]></sc>
	
<sc name="Quantifiers"><![CDATA[
	.		Any single character except eol
	x*		Zero or more x's (maximal)
	x+		One or more x's (maximal)
	x?		Zero or one x's (maximal)
	x*?		Zero or more (minimal)
	x+?		One or more (minimal)
	x??		Zero or one (minimal) ]]></sc>
	
<sc name="Character classes"><![CDATA[
	[abcdef]	Any of the enclosed characters
	[a-z]		Any in the range of characters
	[^a-e]		Any char except a-e
	[^abcdef]	Not any of the characters ]]></sc>
	

<sc name="Expressions"><![CDATA[	
	(expression)	Grouping an expression
	\c		Escape a meta character c like *+. etc.
	exp1|exp2	Matches expression1 or expression 2.  ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Router">
<!-- ********************************************************************* -->

<sc name="Router model"><![CDATA[
	The configuration examples shown in this section are for the
	3Com OfficeConnect Remote 812 ADSL Router. It's one of the
	more capable consumer-grade products although now obsolete.
	Conifiguring other desktop routers involes very similar concepts. ]]></sc>

<sc name="Router URL"><![CDATA[
	Most routers are configured using a built-in webserver.
	After adding the static IP of the router to your DNS,
	you can visit it from any client on your LAN. Example:

	http://router.csparks.com:8080 ]]></sc>
	
<sc name="Global Settings"><![CDATA[
	UNCHECK: Enable Bridging
	CHECK: Enable IP Routing
	UNCHECK: Enable IPX ]]></sc>
	
<sc name="Local LAN configuration"><![CDATA[
	IP Address & DHCP:	
		IP:   192.168.0.254
		Mask: 255.255.255.0
		Rip:  None
		Use this network as DHCP: No
		
	DNS: Disable
	IP Static Routes: None
	IPX: All off ]]></sc>

<sc name="Filter Configuration"><![CDATA[
	No filters ]]></sc>
	
<sc name="Remote site profile"><![CDATA[
	This is the main setup for the ADSL connection.
	I have one remote site profile called "Citizens".

	Remote Site Name: 
		Citizens
		CHECK: Enable Remote Site
	Network Service:
		PPP over ATM (PPPoA)
		User Name: xxxxx@citlink.net
		Password: yyyyy 
	VC Parameters:
		VPI: 0 
		VCI: 35
	Quality of Service: 
		Unspecified Bit Rate
	UNCHECK: Enable Bridging
	CHECK: Enable IP Routing
	UNCHECK: Enable IPX Routing

	Address Translation: 
		CHECK: Nat
		Default Workstation: 0.0.0.0
		Static Ports: (See below)
	Routing Information:
		CHECK: Use this connection as default gateway
		RIP: None
	Static IP Routes:
		None
	Security:
		CHECK: Verify packets can be routed back
		CHECK: Enable protect files and printers
	IPX Stuff:
		Turn all this off.  ]]></sc>
		
<sc name="Port forwarding setup"><![CDATA[
	TCP Ports:

	21	ftp	192.168.0.2:21
	22	ssh	192.168.0.2:22
	25	smtp	192.168.0.2:25
	80	http	192.168.0.2:80
	443	https	192.168.0.2:443
	465	smtps	192.168.0.2:465
	993	imaps	192.168.0.2:993
	1723	pptp	192.168.0.2:1723

	UDP Ports:
	
	53	domain	192.168.0.2:53 ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="RPM">
<!-- ********************************************************************* -->

<sc name="Install or remove a package"><![CDATA[
	rpm -i package.rpm	# Install a package
	rpm -U package.rpm	# Update an installed package
	rpm -F package.rpm	# Freshen (Update only if installed)
	rpm -e packageName	# Remove a package ]]></sc>
	
<sc name="Query the rpm database"><![CDATA[
	rpm -qi			# Describe an installed package              
	rpm -qa			# List all installed packages
	rpm -qf afile		# See which package installed a file
	rpm -qR package		# Find out what a package needs
	rpm -qa --last          # List by installation time ]]></sc>

<sc name="List the contents of an rpm file"><![CDATA[
	rpm -qlp package.rpm ]]></sc>

<sc name="List packages by the source Linux distribution"><![CDATA[
	rpm -qai | grep Dist | awk -F': ' '{print $3}' | sort | uniq -c ]]></sc>

<sc name="Build a binary rpm using a source rpm"><![CDATA[
	rpmbuild --rebuild your.src.rpm
	The result is in /usr/src/redhat/RPMS/i386 ]]></sc>

<sc name="Build a new source rpm from an installed source rpm"><![CDATA[
	rpm -i xxxx.src.rpm
	
	You can now tamper with the tgz in /usr/src/redhat/SOURCES
	
	rpmbuild -bs /usr/src/redhat/SPECS/xxxx.spec
	
	The result is in /usr/src/redhat/SRPMS ]]></sc>
	
<sc name="Create a binary rpm from a tar.gz that contains a .spec"><![CDATA[
	rpmbuild -tb yourpackage.tar.gz ]]></sc>
	
<sc name="Install rpm on an empty linux partition mounted on 'mp'"><![CDATA[
	rpm --root mp --initdb ]]></sc>
	
<sc name="Create a cpio archive from an rpm and write to an archive"><![CDATA[
	rpm2cpio rpmFile > archive.cpio ]]></sc>

<sc name="Expand a cpio archive"><![CDATA[
	cpio -mid < archive.cpio ]]></sc>

<sc name="Unpack an rpm on one step"><![CDATA[
	rpm2cpio rpmFile | cpio -mid ]]></sc>

<sc name="Use query formats"><![CDATA[
	The whole format is one "string"
	Each tag specification looks like this: %{NAME}
	You usually want a newline at the end:
		
		rpm -q xmms --qf "%{SIZE}\n"
	
	Between the "%" and the opening brace "{" you can
	specify field sizes, or any other C printf formatting chars.
	Positive integers select right alignment in the field.
	Negative integers select left alignment in the field:
	
		rpm -qa --qf "%-30{NAME} %10{SIZE}\n"
	
	Some header tags select arrays of values.
	Use square brackets to iterate over the set.
	You can specify more than one array tag inside the query:
	
		rpm -q xmms --qf "[%-50{FILENAMES} %10{FILESIZES}\n]"
	
	Normally, all tags inside square brackets must be array tags.
	If you want to print a fixed tag as a label on each line, add
	an "=" char to the fixed-tag name:

		rpm -q xmms -qf "[%{=NAME} %{FILENAMES}\n]"
		
	Display a list of all rpms sorted by size:
	
		rpm -qa --qf "%-50{NAME} %10{SIZE}\n" | sort -nk 2,2
		
	Display a list of all "devel" packages sorted by size:
	
		rpm -qa | grep devel | \
		xargs rpm -q --qf "%-50{NAME} %10{SIZE}\n" | \
		sort -nk 2,2 ]]></sc> 
	
<sc name="List all the available header tags for query formats"><![CDATA[
	rpm --querytags ]]></sc>
	
<sc name="Show the value of a header element"><![CDATA[
	rpm -q packageName --qf "%{SIZE}\n" ]]></sc>
	
<sc name="List the sizes of selected packages"><![CDATA[
	rpm -qa | grep devel | xargs rpm -q --qf "%{NAME} %{SIZE}\n" ]]></sc>

<sc name="Fix a hoarked rpm database"><![CDATA[
	Symptom: All rpm commands "hang up"
	
	Find and kill all processes running rpm or up2date:

		ps ax | grep rpm
		ps ax | grep up2date
		
		(Kill them by hand)

	Remove all rpm database lock files:

		rm -f /var/lib/rpm/__db*

	This usually gets things going. If not:
	
	First make a backup of the database:

		cp -a /var/lib/rpm /var/lib/rpm.copy

	Then rebuild the database

		rpm --rebuilddb

	This takes some time, but if it hangs forever, repeat
	the "Find and kill rpm" step and proceed with:
	
		cd /var/lib/rpm
		db_verify Packages

		(You may need to install db4-utils)
	
	If db_verify reports errors, try:

		cp Packages Packages.backup
		db_dump Packages.backup | db_load Packages
		rpm --rebuilddb
		
	If all these steps fail, you are in big do-do. ]]></sc>
		
<sc name="Fix signature verification errors"><![CDATA[
	Recent versions of Redhat require signature verification
	when processing packages. If you havn't imported the 
	Redhat GPG signature, you will get errors of the form:
	
		warning: ... V3 DSA signature: NOKEY, key ID ...
		
	To fix this, first obtain a copy of the file RPM-GPG-KEY.
	If you are creating your own rpm-based distribution, the
	file is widely available on the web.
	
	On a Redhat system, it can be found using:
	
		find /usr -name RPM-GPG-KEY
	
	When you have the file, execute the following expression:
	
		rpm --import RPM-GPG-KEY ]]></sc>	

<sc name="Use RPM to verify all packages"><![CDATA[
	rpm -Va
	
	The code letters:
	S file Size differs
	M Mode differs (includes permissions and file type)
	5 MD5 sum differs
	D Device major/minor number mis-match
	L readLink(2) path mis-match
	U User ownership differs
	G Group ownership differs
	T mTime differs
	c A configuration file
	
	A streamlined report that ignores date-only changes:
	
	rpm -Va | grep -v  ".......T"
	
	To make this a cron job that mails the result:
	
	rpm -Va | grep -v ".......T" | mail myself@mydomain
	
	To skim off acceptable changes
	
	rpm -Va | grep -v ".......T" | grep -vf rpmChanges | \
		mail myself@mydomain
	
	Append any new acceptable changes to the rpmChanges file. ]]></sc>
</s>


<!-- ********************************************************************* -->
<s name="Yum">
<!-- ********************************************************************* -->

<sc name="Install package and all required dependencies"><![CDATA[
	yum install <packageName(s)> ]]></sc>

<sc name="Remove packages"><![CDATA[
	yum remove <packageName(s)> ]]></sc>

<sc name="Obtain and install updates for all installed packages"><![CDATA[
	yum update	
	The downloaded files are in /var/cache/yum ]]></sc>

<sc name="List available updates without installing them"><![CDATA[
	yum check-update ]]></sc>

<sc name="Display information about a package"><![CDATA[
	yum info <packageName> ]]></sc>

<sc name="List the installed repositories"><![CDATA[
	yum info repolist ]]></sc>

<sc name="Install a new repository"><![CDATA[
	You can edit or create files in:

		/etc/yum.repos.d

	Alternatively, most yum repositories have and associated
	rpm file you can install or remove. ]]></sc>

<sc name="Command line options"><![CDATA[
	Install relative to an alternative root filesystem:

		--installroot=<path>

	Sometimes different repositories contain packages with
	conflicting names or build attributes. It is necessary
	to resolve this to avoid installing or updating with
	the wrong package. Repositories can be enabled or
	disabled by editing their yum.repos.d files. Otherwise,
	these settings can be overridden on the command line:

		--enablerepo=<repoName>

		--disablerepo=<repoName> ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Scanner">
<!-- ********************************************************************* -->

<sc name="Find the scsi device that controls your scanner"><![CDATA[
	sane-find-scanner
	
	(For this example, we will assume that /dev/sg0 is the result)]]></sc>

<sc name="Make a new user &amp; group for the scanner"><![CDATA[
	useradd saned ]]></sc>

<sc name="Give this group access to the scanner device"><![CDATA[
	chown root:saned /dev/sg0
	chmod g+rw /dev/sg1 ]]></sc>
	
<sc name="Add an entry to /etc/services"><![CDATA[
	sane-port     6566/tcp saned   # SANE network scanner daemon ]]></sc>

<sc name="Add an entry to /etc/xinet.d"><![CDATA[
	service sane-port
	{	
		socket_type = stream
		server = /usr/sbin/saned
		protocol = tcp
		user = saned
		group = saned
		wait = no
		disable = no
	} 

	You will need to verify the location of the saned program
	on your system. Use "which saned" and modify the xinet.d 
	file shown above appropriately. ]]></sc>

<sc name="Specify allowed hosts"><![CDATA[
	Edit:
	
		/etc/sane.d/saned.conf
	
	Append your allowed hosts (names, ip numbers, or subnets)
	Example for a local subnet:
	
		192.168.1.0/24 ]]></sc>
	
<sc name="Eliminate unused backends"><![CDATA[
	This is not strictly necessary, but it may prevent some
	module loading errors. Edit:
	
		/etc/sane.d/dll.conf
	
	Remove everything but the entry for your scanner type and "net."
	The "v41", for example, causes the char-major-81 error.
	
	UPDATE: None of this section applies to Fedora core II. ]]></sc>
	
<sc name="Tell xinetd to reload the configuration files"><![CDATA[
	service xinetd restart ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Searching">
<!-- ********************************************************************* -->

	<p> 
	Most of the search command use patterns that are described
	in the section 
	<link name="Regular Expressions" url="#Regular Expressions"/>
	</p>

<sc name="Find a pattern in a file"><![CDATA[
	grep pattern file ]]></sc>

<sc name="Search recursively through multiple directories and files"><![CDATA[
	grep -r pattern startDirectory ]]></sc>

<sc name="Find files whose names match a pattern"><![CDATA[
	find startDirectory -name pattern

	If startDirectory isn't specified, find starts in
	the current directory.  By default, the search looks
	recursively down into all subdirectories. 

	The pattern usually contains one or more * wildcards.

	You can pipeline the output of find directly to any command
	that acceptss a stream of filenames. For example:

		find path | grep <pattern> 

	This is equivalent to "grep -r pattern path" ]]></sc>

<sc name="Find files and apply a command to each file"><![CDATA[
	find startDirectory -name "pattern" -exec command arguments \;

	The arguments are passed to the command. You can insert the
	matched filename anywere among the arguments using {}. 
	For example, to make an extended directory listing of files 
	with the extension "mp3":

		find -name *.mp3" -exec ls -l {} \;

	You can use -ok instead of -exec to get a prompt to
	confirm the operation for each file. 

	You can stream filenames to xargs as an alternative -exec:

		find startDirectory -name pattern | xargs <command> 

	When using xargs, the file name always appears after the command,
	so this form is less general than using -exec.

	Example: Change the permissions on all mp3 files at
	or below the current directory:

		find -name *.mp3 | xargs chmod 644

	The example above will fail if the file names contains spaces.
	(Which music files often do.)
	To deal with that, we pipeline the file names though a sed expression
	that puts quotation marks around each name:

		find -name *.mp3 | sed 's/^.*$/"&"/' | xargs chmod 644 ]]></sc>
 
<sc name="Find a file using the locate database"><![CDATA[
	Unlike "find", The locate command depends on a database 
	updated by a system service that runs periodically.
	On most linux systems, this is done daily. Consequently, 
	locate only finds files created on previous days.
	By using a database, locate is much faster than find,
	especially when you have no idea where to look for the file.

	Basic form:

		locate pattern
		
	For example, if you are looking for files that contain
	the string "resolv.conf" anywhere in their name:
	
		locate resolv.conf 

	In other words, locate works "as if" you had used:

		locate *resolv.conf* ]]></sc>

<sc name="Display the path to an executable file"><![CDATA[
	which command ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Sed">
<!-- ********************************************************************* -->

<sc name="Introduction"><![CDATA[
	Sed operates on files or streams that contain lines of text.
	The output is the result of applying a command to lines that
	match a pattern. By far the most common commands are
	substitution and deletion. ]]></sc>

<sc nsme="Learning sed"><![CDATA[
	Sed has a well-deserved reputation for being a write-only
	programming language. There are entire books and many 
	web sites devoted to sed. Some specialize in demonstrating 
	unbelievably obscure expressions. 

	Most of the effort to master Sed is associated with learning
	to write pattern expressions. The introductory sections that
	follow cover the basics. After the introduction, 15 examples
	are presented. If you take time to understand them, you will
	become reasonably proficient. ]]></sc> 

<sc name="Testing sed expressions"><![CDATA[
	Most of the examples shown below can be tested
	by sending through a single line:

		echo 'test string' | sed 'some expression'

	Some examples only make sense when applied to a whole file.
	In those cases you can test the expression using one of these forms:

		cat testFile | sed 'some expression'

	Or:

		sed 'some expression' testFile]]></sc>

<sc name="Example command line formats"><![CDATA[
	sed 'expression' infile >outfile
	sed 'expression' <infile >outfile
	echo "some text" | sed 'expression' ]]></sc>

<sc name="Applying a sequence of sed commands"><![CDATA[
	sed -e 'expression1' -e 'expression2'

	Or the shorter form:

	sed 'expression1;expression2;' ]]></sc>

<sc name="Sed script files"><![CDATA[
	A sequence of sed expressions can be stored in a file.
	Each line of the file is a sed expression without the
	bounding quotes. The script file may contain comments
	that begin with "#" as in a bash script. Usage:

		sed -f scriptFile inputFile

	Or:

		cat inputFile -f scriptFile ]]></sc>

<sc name="Patterns"><![CDATA[
	Patterns may be string literals, character sets or
	special symbols. Special symbols must be escaped
	using a backslash:
	
		? $ . [ ] \ / ^
		
	Common patterns:
	
		mystring        - A literal
		^               - Beginning of the line
		$               - End of the line
		.               - Any single character
		\n              - Newline
		.*              - Zero or more characters
		.+              - One or more characters
		.?              - Zero or one characters

		(The * + or ? may be used after any construct)
	
	Grouping is done using parentheses:
	
		(abc)+          - One or more instances of abc
		(a \| b)        - a or b 

	Character sets:

		[pqr]		- Any one of p q or r	
		[a-z]           - Any lower case letter
		[^a-z]          - Any non lower case letter
		[a-z]*          - Any number of lower case letters
		[a-zA-Z]*       - Any number of mixed lower and upper case letters

	Character classes and their equivalent sets:

		[[:alnum:]]  - [A-Za-z0-9]     Alphanumeric characters
		[[:alpha:]]  - [A-Za-z]        Alphabetic characters
		[[:blank:]]  - [ \x09]         Space or tab characters only
		[[:cntrl:]]  - [\x00-\x19\x7F] Control characters
		[[:digit:]]  - [0-9]           Numeric characters
		[[:graph:]]  - [!-~]           Printable and visible characters
		[[:lower:]]  - [a-z]           Lower-case alphabetic characters
		[[:print:]]  - [ -~]           Printable (non-Control) characters
		[[:punct:]]  - [!-/:-@[-`{-~]  Punctuation characters
		[[:space:]]  - [ \t\v\f]       All whitespace chars
		[[:upper:]]  - [A-Z]           Upper-case alphabetic characters
		[[:xdigit:]] - [0-9a-fA-F]     Hexadecimal digit characters ]]></sc>

<sc name="Substitution"><![CDATA[
	A basic principle of sed is the phrase: "On each line". 
	Consider that a prefix to each comment below.

	Substitute only the first instance of old with new:

		sed 's/old/new/'

	Substitute all instances of old with new:

		sed 's/old/new/g'

	Substitute 3rd instance of old with new:

		sed 's/old/new/3' 

	Substitute old with new on lines that contain red:
	
		sed '/red/s/old/new/g' 

	Remove leading whitespace:
	
		sed 's/[ \t]*//'

	Remove trailing whitespace:

		sed 's/[ \t]*$//' ]]></sc>

<sc name="Deletion"><![CDATA[
	Delete lines that contain a pattern:
	
		sed '/pattern/d' 

	Output lines that contain a pattern:
	
		sed '/pattern/!d'

	Delete all blank lines:

		sed '/^$/d' ]]></sc>

<sc name="Using the value of a pattern"><![CDATA[
	The "&" symbol inserts the whole pattern matched:

	Add a prefix to every line:

		sed 's/.*/myPrefix&/'

	Add a suffix to every line:

		sed 's/.*/&mySuffix/'

	Put quotes around a line:

		sed 's/^.*$/"&"/'

	Quoting lines is great for processing file names that may contain spaces:

		find * -name *.mp3 | sed 's/^.*$/"&"/' | xargs chmod 644

		(Change the ownership of all mp3 files.) ]]></sc>

<sc name="Using capture groups"><![CDATA[
	The literal values matched in pattern expressions may
	be captured in escaped parenthesis: 

		\(any pattern\)

	Multiple capture groups may be used.
	On the substitution side, the value of each capture group
	may be inserted:

		\1 for the first capture
		\2 for the second capture, etc.

	The expression:

		echo "his name was Fred" | sed 's/his name was \(.*\)/Name: \1/' 
	
	Produces:

		Name: Fred ]]></sc>

<sc name="Obscure file operations"><![CDATA[
	The 23rd line:

		sed '23q;d'

	Number the lines:

		sed = myfile.txt | sed 'N;s/\n/\t/'

	Reverse the order of lines:

		sed '1!G;h;$!d' ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Services">
<!-- ********************************************************************* -->

<sc name="SysVinit vs Systemd"><![CDATA[
	SysVinit is the old way of managing system services.
	Systemd is the new way of managing system services.
	Most linux distributions provide an emulation layer so
	users familiar with SysVinit can work in a familiar way.
	See the section "Systemd" following this one (Services). ]]></sc>

<sc name="Control individual services"><![CDATA[
	Services or 'daemons' are programs that run in the background,
	usually without any user interaction.

	They implement system functions such as logging, network 
	servers, and many other housekeeping tasks.

	To start a service by hand:

		service <serviceName> <selector>
	
	Typical selectors are: start, stop, restart, status. 
	
	If you run the command without a selector, it will display
	a list of possible selectors. ]]></sc>
	
<sc name="Run levels identify groups of system services"><![CDATA[
	The operating system can run in different modes called
	run levels. Each runlevel determines a set of services to
	run and a set of services to stop.
	
	Run levels are identified by small integers. The group
	of services associated with each run level is conventional:

		0	Halt
		1	Single user
		2	Multiuser, no networking, local additions
		3	Multiuser, networking, local additions
		4	Multiuser, networking, no local additions
		5	Same as 3 plus X Windows Login
		6	Reboot ]]></sc>
	
<sc name="Show the current run level"><![CDATA[
	who -r ]]></sc>

<sc name="Change the run level of the system immediately"><![CDATA[
	telinit newLevelNumber  ]]></sc>
	
<sc name="Change the run level the system will use after reboot"><![CDATA[
	This is done by editing the file:
	
		/etc/inittab
		
	Inside, you will find an expression that looks like this:
	
		id:3:initdefault::
		
	In the example shown above, "3" is the run level used at boot time.
	If you wanted to have an X-Windows splash screen with a login dialog,
	you would change this number to "5". ]]></sc>
	
<sc name="Configuring runlevels by hand"><![CDATA[
	For each runlevel, we need to specify which services start and which
	services stop. We also need to specify the order in which services
	start or stop to allow for interdependencies.
	
	A collection of directories and symbolic links are used to perform 
	these functions. The Linux boot process uses these links to start
	or stop the appropriate services at boot time or when you explicitly
	switch the run level.

	A directory exists for each run level X:
	
		/etc/rc.d/rcX.d 
		
	Each run level directory contains symbolic links. The links all
	point to the service control files found in:
	
		/etc/rc.d/init.d

	The name of the link begins with the letter "S" if the service
	should start. The name of the link begins with "K" if the service
	should stop. (Think "killed.") The start and stop links for a
	given service point to the same file.
	
	The link names also determine the order of starting or stopping: 
	Following the S or K is a two-character integer that determines
	the order of execution relative to the other links in the directory. 
	Higher numbers make the service start later.

	After the ordering digits, the service name appears. For example,
	the following link will start networking at relative step 10 of
	runlevel 3:
	
		/etc/rc.d/rc3.d/S10network -> ../init.d/network
		
	Networking gets turned off in runlevel 1, so we find this link:
	
		/etc/rc.d/rc1.d/K90network -> ../init.d/network
	
	When a service is installed, a start or stop link should should
	be created in every run level directory. Here's a complete example
	for the web server httpd:
	
	Starting:
		/etc/rc.d/rc3.d/S85httpd -> ../init.d/httpd
		/etc/rc.d/rc4.d/S85httpd -> ../init.d/httpd
		/etc/rc.d/rc5.d/S85httpd -> ../init.d/httpd
		
	Stopping:
		/etc/rc.d/rc0.d/S15httpd -> ../init.d/httpd
		/etc/rc.d/rc1.d/S15httpd -> ../init.d/httpd
		/etc/rc.d/rc2.d/S15httpd -> ../init.d/httpd
		/etc/rc.d/rc6.d/S15httpd -> ../init.d/httpd
				
	It is important idea to keep the links complimentary: If you create
	start links on levels 2 and 5, you should  create kill links on
	levels 0,1,3,4, and 6.
	
	It is clearly a pain to do all this correctly by hand. ]]></sc>
	
<sc name="Configuring runlevels with chkconfig"><![CDATA[
	The chkconfig command helps you maintain run level links.
	It doesn't start or stop services, it only creates or deletes the
	appropriate symbolic links in the run level directories.
	
	The chkconfig command obtains run level and starting order information
	from a special comment found inside each service control file.
	A typical comment in a service control file looks like this:
	
		# chkconfig: 2345 90 60
	
	This was extracted from my /etc/rc.d/init.d/crond control file.
	The comment suggests that the crond service should start on 
	runlevels 2345 at relative position 90. By the complimentary 
	priciple, it should have kill links on levels 0, 1 and 6 at relative
	position 60.
	
	Install both start and kill links for a newly installed service:

		chkconfig --add serviceName
	
	Remove all start and kill links for a service at all run levels.

		chkconfig --del serviceName

	Some service control files will have a minus character for the list
	of run levels. For example, my Samba control file (smb) contains:
	
		# chkconfig - 91 35
	
	To install a new service like this you first use:
	
		chkconfig --add serviceName
		
	This will put kill links on every level.
	
	Then you specify the levels where you want the service to run:
	
	Add start links and remove kill links from specified levels:
	
		chkconfig --level levelString serviceName on
	
	Add kill links and remove start links from specified levels:
	
		chkconfig --level levelString serviceName off
	
	If you don't use the "--level levelString" option, the default
	levels 2345 will be used.
	
	Example to start Samba at runlevels 345:
	
		chkconfig --level 345 smb on
		
	It often happens that people try to maintain the links
	by hand and get everything messed up. To clean house when you
	are uncertain about a service configuration, first get rid of all
	the links using:
	
		chkconfig --del serviceName ]]></sc>
</s>

<!-- ********************************************************************* -->
<s name="Systemd">
<!-- ********************************************************************* -->

<sc name="List all running services"><![CDATA[
	systemctl ]]></sc>

<sc name="Show status of a service"><![CDATA[
	systemctl status foo.service  ]]></sc>

<sc name="Start/stop/restart"><![CDATA[
	systemctl start foo.service 
	systemctl stop foo.service 
	systemctl restart foo.service  ]]></sc>

<sc name="Enable/disable at boot time"><![CDATA[
	systemctl enable foo.service 
	systemctl disable foo.service  ]]></sc>

<sc name="Check boot-time enabled status"><![CDATA[
	systemctl is-enabled foo.service; echo $? 

	The value returned is a script status:

		0 => enabled 
		1 => disabled ]]></sc>

<sc name="Targets and runlevels"><![CDATA[
	Systemd uses "targets" instead of runlevels.

	Run level 3 is emulated by multi-user.target.
	Run level 5 is emulated by graphical.target.

	Some retro symbolic links are provided as well:

	runlevel3.target -> multi-user.target
	runlevel5.target -> graphical.target ]]></sc>

<sc name="Switching runlevels"><![CDATA[
	systemctl isolate multi-user.target
	systemctl isolate graphical.target ]]></sc>

<sc name="Set the boot runlevel"><![CDATA[
	Systemd uses a symbolic link "default.target". 
	The old /etc/inittab file is no longer used. 

	First, delete the existing symlink:

		rm /etc/systemd/system/default.target 

	To boot into runlevel 3:

		ln -sf  /lib/systemd/system/multi-user.target \
			/etc/systemd/system/default.target 

	To boot into runlevel 5:

		ln -sf  /lib/systemd/system/graphical.target \
			/etc/systemd/system/default.target  ]]></sc>

<sc name="Show the current run level"><![CDATA[
	systemctl list-units --type=target 

	This isn't as easy to interpret. It dumps all the active targets. ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="SSH">
<!-- ********************************************************************* -->

<ss name="The concept">
	<p>
	Secure Shell (ssh) lets you connect to a remote host
	and start a shell session just like Telnet. <cr/>
	Unlike Telnet, ssh uses cryptography to log in and 
	protect the data flow between you and the remote host.
	</p>
	
	<p> 
	Setting up ssh access is conceptually involved, but
	once this is done, ssh is very easy to use. 
	For example: To start a shell session on a remote host
	you simply type:
	</p>
	
	<code><![CDATA[
	Login using your current user name:
	
		ssh remoteHostIpName
		
	Specify the remote user name:
	
		ssh -l userName remoteHostIpName
		
	Or use 'email' notation:
	
		ssh userName@remoteHostIpName 

	You can run a command on a remote system and see
	the results locally:

		ssh userName@remoteHost ls ]]></code>
	
	<p>
	SSH can perform many other marvels such as port
	forwarding: This lets you channel tcp/ip traffic
	between any selected client and server port through
	the secure connection. A common use of this feature
	is to run remote X-Windows programs and have them
	display on the client automatically.
	</p>

	<p>
	The following sections deal with understanding and
	configuring basic ssh access.
	</p>
</ss>

<ss name="RSA cryptography">
	<p>
	SSH supports several encryption mechanisms, but one
	of the best is based on the RSA public key system.
	</p>

	<p>
	To use RSA, you need a pair of numerical keys.
	One key is public: You can pass it out to your
	friends or publish it in a public directory.
	The other key is private and must be keep secret.
	</p>

	<p>
	RSA is a Good Thing&#153; because it works without
	ever exchanging private keys over an insecure communication
	channel, e.g. the internet. It also supports signatures:
	A person who recieves a message can verify that only
	you could have sent the message.
	</p>
</ss>

<ss name="Create your own set of RSA keys">
	<p>
	First, you need to create a hidden directory in your
	home directory and set restricted permissions:
	</p>
	<code><![CDATA[
	mkdir .ssh
	chmod u=rwx,g-rwx,o-rwx .ssh 
	
	Or using numerical permissions:
	
	chmod 700 .ssh ]]></code>
	
	<p>
	Next, run ssh-keygen to create your public and private key files. 
	</p>

	<code><![CDATA[
	ssh-keygen -t rsa -C "A comment" ]]></code>
	
	<p>
	The program will propose default filenames for your,
	public and private key files, which you should accept:
	</p>

	<code><![CDATA[
	/home/yourName/.ssh/id_rsa 
	/home/yourName/.ssh/id_rsa.pub ]]></code>
		
	<p>
	You will also be asked for a passphrase.
	If you specify a passphrase, you will need
	to enter it whenever ssh or other programs want to use
	your private key. 
	</p>

	<p>
	The <i>comment</i> parameter is optional. If you don't
	supply a comment using "-C", the default is a string
	derived from your login name and the name of your host
	formatted like an email address:
	</p>

	<code><![CDATA[
	yourName@yourMachine.yourDomain ]]></code>
	
	<p>
	The comment appears as plain text in your public key
	string. When examining an authorization file on a remote
	server, this text helps you remember who is authorized.
	</p>

	<p>
	Once you have a key set, you can freely distribute copies
	of your id_rsa.pub file to anyone who wants to send you
	secure messages.
	</p>

	<p>
	The file permissions for private key files must be set
	correctly or the ssh program will not work. The ssh-keygen
	program will do this properly, but to set them by hand you
	would use these expressions:
	</p>

	<code><![CDATA[
	chmod u=rw,g-rwx,o-rwx id_rsa 
	chmod u=rw,g=r,o=r id_rsa.pub 
	
	Or if you're of the old school:
	
	chmod 600 id_rsa
	chmod 644 id_rsa.pub ]]></code> 
		
</ss>
		
<ss name="Enable ssh access to a remote account">
	<p>
	You must setup your client ssh keys as decribed above.
	They will be in the hidden .ssh directory in your
	home directory on the client machine.
	</p>

	<p>
	Email, ftp or otherwise copy your id_rsa.pub file to
	your home directory on the remote machine. To avoid
	confusion, we rename the file "client_rsa.pub". You must
	append the contents of this file to the authorized_keys
	file in the .ssh directory at the top-level of your
	remote home directory.
	</p>

	<p>
	To do this, you need to log into your remote account
	by some other means or ask someone who has access to
	do this for you. This command will append your key
	to the authorized_keys file:
	</p>

	<code><![CDATA[
	cat client_rsa.pub >> .ssh/authorized_keys ]]></code>

	<p>	
	If you're creating a new .ssh/authorized_keys file,
	you must set the permissions or remote access will
	be denied:
	</p>

	<code><![CDATA[
	chmod u=rw,g-rwx,o-rwx .ssh/authorized_keys ]]></code>
	
	<p>
	If some other user such as "root" does this for you,
	they also need to make sure that you own the file:
	</p>

	<code><![CDATA[
	chown yourName:yourGroupName .ssh/authorized_keys ]]></code>

	<p>
	Similarly, the remote .ssh directory must have the
	correct permissions and owner:
	</p>

	<code><![CDATA[
	chmod u=rwx,g-rwx,o-rwx .ssh
	chown yourUserName:yourGroupName .ssh ]]></code>

	<p>
	Here's a quick check on how the .ssh directory should look:
	</p>

	<code><![CDATA[
	ls -ld .ssh

	drwx------ 2 you you 4096 2008-02-27 13:58 .ssh

	ls -l .ssh

	-rw------- 1 you you 1727 2007-08-04 07:15 authorized_keys
	-rw------- 1 you you  887 2004-07-16 03:48 id_rsa
	-rw-r--r-- 1 you you  221 2004-07-16 03:48 id_rsa.pub
	-rw-r--r-- 1 you you 2553 2008-02-25 10:55 known_hosts ]]></code>
	
	<p>
	The above listing shows the <i>known_hosts</i> file, which is
	automatically created and/or updated whenever remote clients
	connect to this account.
	</p>
</ss>

<ss name="Per host configuration">
	<p>
	By adding a "config" file to your .ssh directory, different
	configuation options and defaults can be set for each host
	you commonly use. Here is an example .ssh/config file:
	</p>

	<code><![CDATA[
	Host someserver.somewhere.com
		User myusername
		ForwardX11 yes
		ForwardX11Trusted yes

	Host otherserver.elsewhere.com
		User otherUserName
		... ]]></code>

	<p>
	By specifying a username as shown above, the command line
	for remote login becomes very simple:
	</p>

	<code><![CDATA[
	ssh somewerver.somewhere.com ]]></code>
	<p>
	Most of the options you can specify system-wide for the
	ssh client in /etc/ssh/ssh_config may alternatively go in
	your local .ssh/config file, elminating the need to modify
	the system defaults.
	</p>

	<p>
	Permissions for the config file should be 644.
	</p>

</ss>

<ss name="Creating a host key set">
	<p>
	An entire host machine may have a key set.
	The public part of this key is kept on remote
	servers to authorize access by the entire machine.
	Many services can be configured to use host-level
	authorization.
	</p>
	
	<p>
	Host keys should be located in:
	</p>

	<code><![CDATA[
	/etc/ssh/ssh_host_rsa_key
	/etc/ssh/ssh_host_rsa_key.pub ]]></code>
	
	<p>
	The automatic installers for many Linux distributions
	create the host key files in /etc/ssh automatically.
	</p>

	<p>
	To create them by hand, run ssh-keygen and specify
	the path names shown above. Passphrases are not
	normally used with host keys. 
	</p>
</ss>

<ss name="SCP - Secure file copy">
	<p>
	The ssh client package is usually bundled with the scp
	(secure copy) program. This allows you to copy files
	between hosts using the secure ssh protocol. To use
	scp, you must have the keys properly configured as
	described in the previous sections.
	</p>
	
	<p>
	The syntax is similar to the regular cp (copy) command,
	but the source and destination path may have an optional
	prefix to denote the host and username associated with
	the access keys.
	</p>

	<p>
	To copy a local file to a remote host where you have
	an account with the same username as your local session:
	</p>
	
	<code><![CDATA[
	scp localfile.txt remote.host.com: ]]></code>
	
	<p>
	To copy the file to some other user's account:
	</p>
	
	<code><![CDATA[
	scp localfile.txt username@remote.host.com: ]]></code>

	<p>
	The general syntax is:
	</p>

	<code><![CDATA[
	scp srcUser@srcMachine:srcFilePath destUser@destMachine:destFilePath ]]></code>
	
	<p>
	If the path names are not absolute, they are relative to the login
	directories for the designated users.
	</p>
</ss>

</s>

<!-- ********************************************************************* -->
<s name="Subversion">
<!-- ********************************************************************* -->

<sc name="Create a repository on the server"><![CDATA[
	svnadmin create myproject ]]></sc>

<sc name="Populate the repository with files"><![CDATA[
	svn import [localDirectory] repoURL ]]></sc>

<sc name="Checkout the repository"><![CDATA[
	svn checkout repoURL [localDir] ]]></sc>

<sc name="List changes since last commit"><![CDATA[
	svn status ]]></sc>

<sc name="Show the log"><![CDATA[
	svn log 

	Note: The "svn log" won't list your most recent
	commits until you perform an "svn update". 
	Many subversion GUI clients do this automatically 
	after each commit.]]></sc>

<sc name="Show diff changes for all or selected files"><![CDATA[
	svn diff <optional filename> ]]></sc>

<sc name="Revert the context directory"><![CDATA[
	svn revert ]]></sc>

<sc name="Revert one file or subdirectory"><![CDATA[
	svn revert aFile ]]></sc>

<sc name="Add a file or directory"><![CDATA[
	svn add aFile ]]></sc>

<sc name="Remove a file or directory"><![CDATA[
	svn rm aFile ]]></sc>

<sc name="Move a file or directory"><![CDATA[
	svn mv fromPath toPath ]]></sc>

<sc name="Create a directory"><![CDATA[
	svn mkdir aDirectory ]]></sc>

<sc name="Commit your changes"><![CDATA[
	Each comment bumps the revsion number;

	svn commit -m "This is why I did the deed." ]]></sc> 
	
<sc name="Bring the local files up to date"><![CDATA[
	svn update ]]></sc>

<sc name="Show the branch or tag message on the last commit"><![CDATA[
	svn log --limit 1 http://myserver.com/svn/myproject/tags/myproject-v1.2 ]]></sc>

<sc name="Show the log between dates"><![CDATA[
	svn log -r {2006-11-20}:{2006-11-29} ]]></sc>

<sc name="Show the changes for a file or directory"><![CDATA[
	svn blame aFile ]]></sc>

<sc name="Create a tag"><![CDATA[
	First be sure to update and commit!

	svn copy repoURLFrom repoURLTo

	Usually:

	svn copy http://myserver.com/svn/myproject/truck \
		 http://myserver.com/svn/myproject/tags/myproject-v1.2 \
		 -m "This is the version sent to China" ]]></sc>

<sc name="Create a branch"><![CDATA[
	First be sure to update and commit!

	svn copy repoURLFrom repoURLTo

	Usually:

	svn copy http://myserver.com/svn/myproject/truck \
		 http://myserver.com/svn/myproject/branches/myproject-testThing \
		 -m "BRANCH myproject-testThing *******************************"

	Note the capital letters and stars on the comment: this is to help
	you find the branch version number when reading the log. You need this
	number when you perform a merge. (See below.) ]]></sc>

<sc name="Switch to a branch"><![CDATA[
	svn switch http://myserver.com/svn/myproject/branches/myproject-testThing ]]></sc>

<sc name="Change the local copy to reference a new URL"><![CDATA[
	svn switch --relocate http://old.server.com/svn/myproject http://new.server.com/svn/myproject ]]></sc>

<sc name="Show all tags or branches"><![CDATA[
	svn list http://myserver.com/svn/myproject/branches ]]></sc>

<sc name="Merge a branch back into the trunk"><![CDATA[
	You should be working in the trunk:

	svn merge -r 20:HEAD http://myserver.com/svn/myproject/branch-testThing

	The "20" is the rev number where you created the branch from the trunk. ]]></sc>

<sc name="Use revision keywords"><![CDATA[
	BASE - Version in your working copy as of your last commit.
	HEAD - Most recent version in the remote repository.
	COMMITTED - The most recent revision <= BASE, in which an item changed.
	PREV - (COMMITED - 1)

	Show the last change committed to foo.c

		svn diff -r PREV:COMMITTED foo.c

	Show the log message for the latest repository commit

		svn log -r HEAD

	Compare your working copy to the latest version in the repository

		svn diff -r HEAD

	Compare the unmodified version of foo.c with the latest version of
	foo.c in the repository

		svn diff -r BASE:HEAD foo.c

	Show all commit logs for the current versioned directory since you
	last updated

		svn log -r BASE:HEAD

	Rewind the last change on foo.c, decreasing foo.c's working revision

		svn update -r PREV foo.c

	Compare the unmodified version of foo.c with the way foo.c looked
	in revision 14

		svn diff -r BASE:14 foo.c ]]></sc>

<sc name="Backup the repository"><![CDATA[
	svnadmin dump repositoryTopDirectory > myBackup.svndump ]]></sc>

<sc name="Restore a backup"><![CDATA[
	svnadmin create newRepo
	svnadmin load newRepo < myBackup.svndump ]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Text">
<!-- ********************************************************************* -->

<sc name="Interactive spelling check and correction"><![CDATA[
	aspell -c myFile.txt ]]></sc>
		
<sc name="Check spelling of one word: script version"><![CDATA[
	echo $1 | ispell -a | sed -n -e '/^\&/p' -e '/^\#/p'
	
	Put this expression in a shell script on your PATH. ]]></sc>

<sc name="Cut out part of lines cols n-m"><![CDATA[
	cut -c n-m path ]]></sc>

<sc name="Cut out part of lines n-eol"><![CDATA[
	cut -c n- path ]]></sc>
</s>


<!-- ********************************************************************* -->
<s name="Time">
<!-- ********************************************************************* -->

<sc name="Update the clock from a time server (Three steps)"><![CDATA[
	rdate -u -p -s ns.scruz.net # This gets the time and sets system time
	hwclock --systohc	    # Write system time to cmos
	hwclock --adjust	    # Apply a rate adjustment
	
	# The startup scripts normally take care of this:
	
	hwclock --hctosys <opt>	    # Read system time from cmos
	
	The <opt> may be --localtime or --utc. For localtime, you
	need to have an /etc/localtime file which can be a copy or
	link to zoneinfo file. (These are in /usr/share/zoneinfo) ]]></sc>

<sc name="Schedule a command for later execution"><![CDATA[
	Examples using a specific time:

		at 10:25pm
		at 1am Dec 20
		at 2pm tomorrow
		at midnight tomorrow

	Examples using relative time:

		at now + 10 minutes
		at 4pm + 3 days
		at 4pm + 3 weeks
	
	A prompt will appear for you to enter commands.
	Finish with EOF (control D)

	Show your pending jobs:

		atq
	
	Remove a job:
	
		atrm <job number> 
		
	Send a reminder to your cellphone
	
		at 6am Mar 17
		mail -s "Meeting at 10am in Room 101" 1234567890@attnet.com
		Don't forget to bring the rats!
		^D ]]></sc>

<sc name="Using 'at' from inside a bash script"><![CDATA[
	at 3am <<-EOF
		service tomcat restart
	EOF ]]></sc>

<sc name="Start a timed server as the master clock (put in rc.local)"><![CDATA[
	timed -M -F localhost ]]></sc>

<sc name="Start a timed client"><![CDATA[
	timed ]]></sc>

<sc name="Use cron for periodic script execution"><![CDATA[
	Use a bash script in one of these directories:
	
	cron.daily
	cron.hourly
	cron.monthly
	cron.weekly ]]></sc>

<sc name="Using crontab"><![CDATA[
	Each user has a private crontab file.
	On Redhat/Fedora systems the file is created
	with this path:
		
		/var/spool/cron/username

	The file won't exist until a cron job is scheduled.

	To edit your crontab file:
		
		crontab -e

	Crontab file format:

		Min(0-59) Hour(0-23) Date(1-31) Month(1-12) Day(0-6 Sun-Sat) Command
	
	Use a * character for "every." 
	This command lists the root directory to a a file at 9AM every Monday:

		0 9 * * 1 ls /root > /root/listing.txt ]]></sc>
	
</s>

<!-- ********************************************************************* -->
<s name="Users">
<!-- ********************************************************************* -->

<sc name="Prompt for new password"><![CDATA[
	passwd ]]></sc>

<sc name="Change your login shell program"><![CDATA[
	chsh ]]></sc>

<sc name="Shut down and reboot or halt"><![CDATA[
	shutdown -r now
	shutdown -h now ]]></sc>

<sc name="Adding or removing users"><![CDATA[
	useradd userName
	userdel	name 
	
	In Redhat Land, useradd also creates and adds  the
	new user to a new unique group with the same name.]]></sc>
	
<sc name="Adding or removing groups"><![CDATA[
	groupadd name
	groupdel name ]]></sc>
	
<sc name="Changing passwords"><![CDATA[
	passwd
	passwd user ]]></sc>

<sc name="Adding or removing users from a group"><![CDATA[
	gpasswd -a user group
	gpasswd -d user group ]]></sc>
	

<sc name="Change all sorts of stuff at once"><![CDATA[
	usermod loginName \
		-g newLoginGroup
		-G newGroup1,...,newGroupN
		-l newLoginName
		-d newHomeDirectory
		-u newUID
			
	Using -G, the user will be removed from any group not listed.
	Using -l, the user still has their old home directory.
	You can't change the login name of a user who is currently logged in.
	See man page for more options. ]]></sc>
	
<sc name="Log into a remote system with no password"><![CDATA[
	rlogin remoteIP

	The .rhosts file must be in the remote login directory.
	It contains the ipNames of allowed users. 
	You can add a local username if not the same as remote.
	The .rhosts file must have read privilages only for owner.
	/etc/xinetd.d/rlogin must not be disabled.
	If you want to rlogin from a root account
	/etc/securetty must have an entry for "rlogin". ]]></sc>
	<p indent="4">Update: This method is obsolete and dangerous. Please
	see the <link name="SSH" sec="SSH"/> section for a safe alternative.</p>

<sc name="Forgotten password"><![CDATA[
	Concept: Boot the system using the bash shell as the startup
	application. This will bypass the usual system initialization
	and login process. Then run passwd to set a new root password.
	
	The procedure varies depending on the boot loader.
	Example using Grub:
	
	Hit "e" on the boot menu.
	Select the line that begins with "kernel"
	Hit "e" again.
	Add this string to the end of the line:
	
		init=/bin/bash
	
	Press "Enter", then "b" to boot the system.
	At the bash prompt:
	
		mount /proc
		mount / -o rw,remount
		passwd
	
	At this point, you will be prompted to enter a new password.
	Next, remount the root file system read-only to flush the cache:
	
		mount / -o ro,remount
	
	Now control-alt-delete to reboot.]]></sc>

</s>
				
<!-- ********************************************************************* -->
<s name="Video">
<!-- ********************************************************************* -->

<sc name="Display information about a video"><![CDATA[
	ffmpeg -i myVideo.flv ]]></sc>

<sc name="Extract the audio track and convert to mp3"><![CDATA[
	ffmepg -i myVideo.flv -ab 128k myAudio.mp3 ]]></sc>

<sc name="Extract the audio track and preserve existing encoding"><![CDATA[
	ffmepg -i myVideo.flv -acodec copy myAudio.xxx

	You have to specify "xxx". ]]></sc>

<sc name="Convert a video to (almost any) other format"><![CDATA[
	ffmepg -i myVideo.flv myNewVideo.xxx

	Choosing "xxx" determins the container format. ]]></sc>

<sc name="Display available codecs"><![CDATA[
	ffmepg -codecs ]]></sc>

<sc name="Convert a video and specify the codecs"><![CDATA[
	fffmepg -i myVideo.flv -acodec acodec -vcodec vcodec myNewVideo.xxx ]]></sc>

<sc name="Rotate an AVI movie 90 degrees clockwise"><![CDATA[
	mencoder \
		-vf rotate=1 \
		-ovc lavc -lavcopts vcodec=wmv2 \
		-oac copy \
		INPUT.avi -o OUTPUT.avi]]></sc>

<sc name="Flip a quicktime movie and convert to h264 inside avi"><![CDATA[
	mencoder \
		-vf flip \
		-ovc x264 \
		-oac pcm \
		INPUT.mov -o OUTPUT.avi]]></sc>

</s>

<!-- ********************************************************************* -->
<s name="Wine">
<!-- ********************************************************************* -->

<sc name="Changes in /etc/wine/wine.conf"><![CDATA[
	[Drive C]
	"Path" = "/mnt/win"
	[wine]
	# In this section, change all the paths: substituting
	# winnt for windows if that applies to your windows
	# installation mounted at /mnt/win

	# iPod support for EphPod	
	[Drive G]
	"Path" = "/mnt/ipod"
	"Type" = "hd"
	"Label" = "iPod Drive"
	"Filesystem" = "win95"

	# To share EphPod config file with windows
	# Drive E is where Windows sees the server
	[Drive H]
	"Path" = "/mnt/server"
	"Type" = "network"
	"Label" = "Server"
	"Filesystem" = "win95" ]]></sc>
</s>
	

<!-- ********************************************************************* -->
<s name="X Windows">
<!-- ********************************************************************* -->

<sc name="Start X windows and specify bits per pixel"><![CDATA[
	startx -- -bpp 24 ]]></sc>

<sc name="Start X windows and specify a layout"><![CDATA[
	startx -- -layout myLayout
	
	Layouts are defined in /etc/X11/XF86Config]]></sc>
	
<sc name="Start X with a specific monitor dots-per-inch setting"><![CDATA[
	startx -- -dpi 80	# My Hitachi monitor
	startx -- -dpi 95	# My Tecra flat panel
	
	You can do this with a config file .xserverrc in home dir:
	
		exec X -dpi 80
	
	Then just "startx" as usual. ]]></sc>

<sc name="Start X and record the messages so you can see what happened"><![CDATA[
	The startx messages are automatically recorded in:
		
		/var/log/Xorg.x.y 

	If you want to explicity redirect the messages from startx:

		startx > myXDebug.txt 2>&1 ]]></sc>

<sc name="Display info about the active X display"><![CDATA[
	xdpyinfo ]]></sc>

<sc name="Show properties of an X window"><![CDATA[
	xwininfo
	xprop ]]></sc>

<sc name="Send X output of one program to another machine"><![CDATA[
	<Any X command> -display <targetIP>:0 ]]></sc>

<sc name="Send all X output to another machine"><![CDATA[
	export DISPLAY=targetIPnameOrNumber:0.0 ]]></sc>

<sc name="Set the default cursor"><![CDATA[
	xsetroot -cursor_name left_ptr
	
	Others: draped_box, hand1, hand2, iron_cross,
		plus, top_left_arrow, watch ]]></sc>

<sc name="Show X events (including keys)"><![CDATA[
	xev ]]></sc>

<sc name="Show X user prefs settings"><![CDATA[
	xset -q ]]></sc>

<sc name="Allow some other machine to draw on your x display "><![CDATA[
	xhost +<other machine name or ip number>
	
	Put this command in your .xinitrc to make it permanent ]]></sc>

<sc name="Run xterm on another machine &amp; exec a command"><![CDATA[
	xterm -display <ip>:0 -e <command> ]]></sc>

<sc name="Make XF86Config use the xfs font server"><![CDATA[
	Use FontPath "unix/:-1" (Redhat 6.x)
	Update: "unix/:7100"    (Redhat 7.x and other Linux systems) ]]></sc>

<sc name="Add a TrueType font directory (Requires FreeType package)"><![CDATA[
	cd theFontDirectory
	ttmkfdir > fonts.scale 
	mkfontdir
	chkfontpath --add `pwd`
	service xfs reload
	
	Note: Redhat runs ttmkfdir and mkfontdir on
	every directory known to xfs in the xfs
	startup script. These fonts become known
	when you run chkfontpath. ]]></sc>

<sc name="Add a font to the Redhat anti-aliasing system"><![CDATA[
	Put the new font file in: /usr/share/fonts	
	Or in the per-user directory: ~/.fonts
	Then run:
	
		fc-cache <directory>]]></sc>

<sc name="List the fonts X knows about"><![CDATA[
	xlsfonts ]]></sc>

<sc name="Show local font server info"><![CDATA[
	fsinfo -server unix/:-1 ]]></sc>

<sc name="Example /etc/X11/xdm/Xservers for a one-display system"><![CDATA[
	:0 local /usr/X11R6/bin/X ]]></sc>

<sc name="Show the status of X video support"><![CDATA[
	xvinfo ]]></sc>
	
<sc name="Install the NVIDIA binary drivers"><![CDATA[
	yum install kmod-nvidia ]]></sc>

<sc name="Use kdm to support remote X terminals (or Cygwin)"><![CDATA[
	You need to edit a bunch of files on the server:
	
	File: /etc/X11/xdm/kdmrc

	Make sure access is enabled as shown:
		
		Enable=true
	
	File: /etc/X11/xdm/Xaccess

	Comment out the line:
	
		* CHOOSER BROADCAST #any indirect host can get a chooser
	
	Add lines to the end of the file with the ip name or number of
	each client:

		myclient.my.domain.com
		anotherclient.anotherdomain.com
		etc.

		Note: If you use ip numbers, they must be reversable
		to names. You can do this by adding a definition to
		hosts or by running dns.
	
	File: /etc/X11/xdm/Xservers

	If-and-only-if your server runs headless, comment out this line:

		:0 local /usr/X11R6/bin/X
	
	File: /etc/inittab
	
	If you want automatic startup of kdm or xdm, on the server,
	change the default runlevel:

		id:5:initdefault:
	
	File: /etc/rc.d/rc.local

	If you don't start kdm using inittab, add this entry to rc.local:

		/usr/bin/kdm
		
	File: /etc/sysconfig/desktop
		
	If you have more than one desktop system installed, this
	entry selects the one that will be used for remote and local
	logins: (Use KDM for kde or GDM for Gnome.)

		DISPLAYMANAGER=KDM
	
	In your iptables firewall setup script you must allow xdmcp:

		iptables -A udpChain -p udp --dport xdmcp -j ACCEPT ]]>
</sc>
	
<ss name="Remote access with SSH RSA security">
	<p>
	Newer linux distributions are configured to require SSH
	authorization for remote X clients. In this document,
	see "SSH access with RSA keys" for details about creating 
	and using keys.
	</p>

	<p>
	When using RSA, you still need the ip name or number of each 
	client machine in the server's Xaccess file. 
	</p>

	<p>
	The X server has a file that contains the SSH public keys
	of each user and/or entire client machines that are allowed
	to connect:
	</p>
	
	<code><![CDATA[
	/usr/share/config/kdm/kdmkeys ]]></code>
	
	<p>
	If you create this file, you must set the permissions:
	</p>
	
	<code><![CDATA[
	chmod u+rw,g-rwx,o-rwx /usr/share/config/kdm/kdmkeys ]]></code>
			
	<p>
	You don't need to authorize the whole client if you only
	want to allow selected users on that client.
	</p>

	<p>
	Public keys are copied or mailed from the client machines.
	A special public and private key set may be created for 
	the whole host. It is kept in:
	</p>
	
	<code><![CDATA[
	/etc/ssh/ssh_host_rsa_key.pub ]]></code>
		
	<p>
	You append the contents of this file to the server's
	kdmkeys file to authorized everybody on the whole client.
	</p>

	<p>
	Public key files for individual users are found in:
	</p>
	
	<code><![CDATA[
	/home/someuser/.ssh/id_rsa.pub ]]></code>
		
	<p>
	Simply append the contents of this file to the server's
	kdmkeys file to authorize this user. 
	</p>
	
	<p>
	With all the setup completed, you can login to the
	remote machine using ssh and run X-Windows programs.
	The display will be automagically sent back to your
	machine!
	</p>
	
	<p>
	UPDATE: Newer Redhat/Fedora systems need some additional
	setup on the client side: In the file /etc/ssh/ssh_config
	you must add these directives:
	</p>
	<code><![CDATA[
	FORWARDX11 yes
	FORWARDX11Trusted yes ]]></code>
	
	<p>
	Without these changes, you would have to login to the
	server using ssh with the "-Y" switch to enable access by a
	trusted host.
	</p>
</ss>

</s>

<!-- ********************************************************************* -->
<s name="Vi Text Editor">
<!-- ********************************************************************* -->

<sc name="Cursor motion"><![CDATA[
	In most environments, the arrow keys work.

	j		Down one line.
	k		Up one line.
	h		Cursor left.
	l		Cursor right. (lower case L) 
	<spacebar>	Cursor right.
	<backspace>	Cursor left.
	<control>d	Down one page. 
	<control>u	Up one page. ]]></sc>

<sc name="Going places"><![CDATA[
	$		Go to end of line.
	.		Go to beginning of line.
	G		Go to end of file.
	1G		Go to start of file.
	nG		Go to absolute line number n.
	/pattern/G	Go to next line that contains pattern ]]></sc>

<sc name="Inserting"><![CDATA[
	i		Insert text at cursor.
	a		Insert text after cursor.
	<ESC>		Leave insert mode. 
	P		Insert last thing deleted. ]]></sc>

<sc name="Deleting"><![CDATA[
	dd		Delete current line.
	x		Delete current char at cursor.
	<bs>		Delete previous char.
	J		Delete line break. 
			(Join current line with next line) ]]></sc>

<sc name="Clipboards"><![CDATA[
	Marks are denoted by single letters.
	The "current line" is the line that contains the cursor.
	A selection is a block of lines bounded by a mark and the current line.

	ma		Set a mark "a" at current line.
	d'a		Cut lines from mark "a" to current line.
	y'a		Copy ("Yank")lines from mark "a" to current line.
	P		Paste deleted or yanked lines before the current line. 
	V		Go to visual mode: move cursor to select lines
			then use d or y. ]]></sc>

<sc name="Indenting"><![CDATA[
	Indenting commands operate on selections as described above.

	>'a		Indent right from mark "a" to cursor.
	<'a		Indent left from mark "a" to cursor.

	It's easier to use visual mode followed by < or >. ]]></sc>

<sc name="Files"><![CDATA[
	:r <filename>	Read in a file at current location.
	:w		Write everything to current file.
	:w <filename>	Write everything to selected file. 
	:w! <filename>	Overwrite existing file. ]]></sc>

<sc name="Quitting"><![CDATA[
	:wq		Write current file and quit.
	:wq!		Write current file and quit. Override protections.
	:q		Quit but prompt if changes were made. 
	:q!		Quit and don't save changes. ]]></sc>

<sc name="Bash commands"><![CDATA[
	:!<any cmd>	Show result of Bash command.
	:r !<cmd>	Insert result of Bash command. ]]></sc>

<sc name="Substitution"><![CDATA[
	:s/old/new		First instance on the current line.
	:'a,'bs/old/new		Between marks "a" and "b".
	:'<,'>s/old/new		Inside visual mode selection (V).
	:*s/old/new		Abbreviated visual mode selection.
	:%s/old/new/g		Throughout the whole file

	Add /g to substitute all instances instead of just the first.

	Other line number designations:

	.		Current line.
	$		Last line.
	/pattern/	Next line that contains pattern.
	\?		Next line with previously used pattern. ]]></sc>

</s>

<s name="EOF"/>

</page>


