Saturday, March 15, 2008

Burn CDs and DVDs under FreeBSD

This howto explain how to burn CDs and DVDs under FreeBSD

1. Compile the FreeBSD kernel with the following options:
-------------------------------------------------------------------
device atapicam
device ata
device scbus
device cd
device pass


2. Install cdrtools package
-------------------------------
You will need to install cdrtools package (cdrecord and mkisofs are included in cdrtools)


3. Find dev parameters
--------------------------------
To see the name of device for burning CDs and DVD use the the command:
cdrecord -scanbus

If after issuing this command no device ids will appear that means the kernel is not compiled with cd burning support.

To blancd / dvd rw
---------------------
cdrecord -v dev=1,0,0 -blank=fast

To burn a cd or dvd
-----------------------
cdrecord -v dev=1,0,0 speed=8 image_file.iso

To create an ISO with mkisofs
----------------------------------
mkisofs -R -J -o "image_file.iso" /pat_to_files_that_will_be burned

To create an bootable ISO with mkisofs
---------------------------------------------
mkisofs -b "boot/cdboot" -no-emul-boot -c "boot/boot.catalog" -R -J -o "image_file.iso" /pat_to_files_that_will_be burned

(assuming that boot/cdboot is where the boot files are located)

Burning DVDs
-----------------
Version of burncd included on cdrtools package does not support burning DVDs so
for burning DVDs we will use growisofs(1) which is a frontend to mkisofs.

Add in /boot/loader.conf:
hw.ata.atapi_dma="1"
You will need this to activate DMA for atapi devices in order to properly burn DVDs. This option is recommended for burning CDs too.

How to burn a DVD:
# growisofs -dvd-compat -Z /dev/cd0 -J -R /pat_to_files_that_will_be burned

How to burn an ISO to DVD
# growisofs -dvd-compat -Z /dev/cd0=image_file.iso

Managing FreeBSD packages

FreeBSD system have a flexible and easy to use system for package management. 
Tools for managing FreeBSD packages are pkg_add, pkg_delete, pkg_info, pkg_version and pkg_create.

 

 
1. Adding a package with pkg_add
----------------------------------------------
To add a package with pkg_add:

 
# pkg_add package_name

 
To add a package from FreeBSD ftp site (notice -r option, what means remote fetching:

 
# pkg_add -r package_name
(package_name will be written without version number, for example pkg_add -r apache).

 
Package will be fetched from Latest packages of the FreeBSD version installed on our server. If that package is not in Latest dir we can add package from distribution package directory:

 
# pkg_add -r ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-6-stable/All/apache-2.2.4_2.tbz

 
In case you add a package from local drive, if that package will need other packages (dependencies) it will search on the same directory where you've issued the pkg_add command. If it will not find other dependencies packages there, it will abort installation returning an error message. If you add a package using remote fetching feature, all dependencies will be installed from FreeBSD ftp server too.

 

 
2. Getting info about installed packages
 
-----------------------------------------------------
Info about installed packages and versions can be obtain with pkg_info.

 
# pkg_info | grep apache

 
To show all installed packages:

 
# pkg_info -a

 
To show a list of all files from a package:

 
# pkg_info -L package_name

 
To show a list of packages on which the package depends (dependencies):

 
# pkg_info -r package_name

 
If you want to know to whom belongs a packages:

 
# pkg_info -R package_name

 

 
3. Deleting packages with pkg_delete
-------------------------------------------------
To delete a package:

 
# pkg_delete package_name

 
Sometimes you will not be able to delete because deleting that particular package will break dependencies (that packages is needed by other packages). In that case if you still want to delete that packages, use -f (force deleting).

 
# pkg_delete -f package_name

 

 
4. Find package name for a binary installed file
--------------------------------------------------------------

 
# pkg_info -W filename

 
If this is not working, use the path+file name instead of filename

 

 
5. Create a new package from an installed one
 
-------------------------------------------------------------
The easyest way to create a package from an installed one is with pkg_create.

 
# pkg_create -jb package_name

 
For this command to work, package_name must be an installed package on the system. "-j" option will help you to create bzip2 instead of gzip, bzip2 being compression for FreeBSD versions 5.x and higher.

Practical threaded programming with Python

Threaded programming in Python can be done with a minimal amount of complexity by combining threads with Queues. This article explores using threads and queues together to create simple yet effective patterns for solving problems that require concurrency.

Introduction

With Python, there is no shortage of options for concurrency, the standard library includes support for threading, processes, and asynchronous I/O. In many cases Python has removed much of the difficulty in using these various methods of concurrency by creating high-level modules such as asynchronous, threading, and subprocess. Outside of the standard library, there are third solutions such as twisted, stackless, and the processing module, to name a few. This article focuses exclusively on threading in Python, using practicle examples. There are many great resources online that document the threading API, but this article attempts to provide practicle examples of common threading usage patterns.

It is important to first define the differences between processes and threads. Threads are different than processes in that they share state, memory, and resources. This simple difference is both a strength and a weakness for threads. On one hand, threads are lightweight and easy to communicate with, but on the other hand, they bring up a whole host of problems including deadlocks, race conditions, and sheer complexity. Fortunately, due to both the GIL and the queuing module, threading in Python is much less complex to implement than in other languages.

Hello Python threads

To follow along, I assume that you have Python 2.5 or greater installed, as many examples will be using newer features of the Python language that only appear in at least Python2.5. To get started with threads in Python, we will start with a simple "Hello World" example:


hello_threads_example
 
                
        
        import threading
        import datetime
        
        class ThreadClass(threading.Thread):
          def run(self):
            now = datetime.datetime.now()
            print "%s says Hello World at time: %s" % 
            (self.getName(), now)
        
        for i in range(2):
          t = ThreadClass()
          t.start()
      

 

If you run this example, you get the following output:

      # python hello_threads.py 
      Thread-1 says Hello World at time: 2008-05-13 13:22:50.252069
      Thread-2 says Hello World at time: 2008-05-13 13:22:50.252576
      

 

Looking at this output, you can see that you received a Hello World statement from two threads with date stamps. If you look at the actual code, there are two import statements; one imports the datetime module and the other imports the threading module. The class ThreadClass inherits from threading.Thread and because of this, you need to define a run method that executes the code you run inside of the thread. The only thing of importance to note in the run method is that self.getName() is a method that will identify the name of the thread.

The last three lines of code actually call the class and start the threads. If you notice, t.start() is what actually starts the threads. The threading module was designed with inheritance in mind, and was actually built on top of a lower-level thread module. For most situations, it would be considered a best practice to inherit from threading.Thread, as it creates a very natural API for threaded programming.

Using queues with threads

As I referred to earlier, threading can be complicated when threads need to share data or resources. The threading module does provide many synchronization primatives, including semaphores, condition variables, events, and locks. While these options exist, it is considered a best practice to instead concentrate on using queues. Queues are much easier to deal with, and make threaded programming considerably safer, as they effectively funnel all access to a resource to a single thread, and allow a cleaner and more readible design pattern.

In the next example, you will first create a program that will serially, or one after the other, grab a URL of a website, and print out the first 1024 bytes of the page. This is a classic example of something that could be done quicker using threads. First, let's use the urllib2 module to grab these pages one at a time, and time the code:


URL fetch serial
 
                
        import urllib2
        import time
        
        hosts = ["http://yahoo.com", "http://google.com", "http://amazon.com",
        "http://ibm.com", "http://apple.com"]
        
        start = time.time()
        #grabs urls of hosts and prints first 1024 bytes of page
        for host in hosts:
          url = urllib2.urlopen(host)
          print url.read(1024)
        
        print "Elapsed Time: %s" % (time.time() - start)
      

 

When you run this, you get a lot of output to standard out, as the pages are being partially printed. But you get this at the finish:

        Elapsed Time: 2.40353488922  
        

 

Let's look a little at this code. You import only two modules. First, the urllib2 module is what does the heavy lifting and grabs the Web pages. Second, you create a start time value by calling time.time(), and then call it again and subtract the initial value to determine how long the program takes to execute. Finally, in looking at the speed of the program, the result of "Two and a half seconds" isn't horrible, but if you had hundreds of Web pages to retrieve, it would take approximately 50 seconds, given the current average. Look at how creating a threaded version speeds things up:


URL fetch threaded
 
                
          #!/usr/bin/env python
          import Queue
          import threading
          import urllib2
          import time
          
          hosts = ["http://yahoo.com", "http://google.com", "http://amazon.com",
          "http://ibm.com", "http://apple.com"]
          
          queue = Queue.Queue()
          
          class ThreadUrl(threading.Thread):
          """Threaded Url Grab"""
            def __init__(self, queue):
              threading.Thread.__init__(self)
              self.queue = queue
          
            def run(self):
              while True:
                #grabs host from queue
                host = self.queue.get()
            
                #grabs urls of hosts and prints first 1024 bytes of page
                url = urllib2.urlopen(host)
                print url.read(1024)
            
                #signals to queue job is done
                self.queue.task_done()
          
          start = time.time()
          def main():
          
            #spawn a pool of threads, and pass them queue instance 
            for i in range(5):
              t = ThreadUrl(queue)
              t.setDaemon(True)
              t.start()
              
           #populate queue with data   
              for host in hosts:
                queue.put(host)
           
           #wait on the queue until everything has been processed     
           queue.join()
          
          main()
          print "Elapsed Time: %s" % (time.time() - start)
      

 

This example has a bit more code to explain, but it isn't that much more complicated than the first threading example, thanks to the use of the queuing module. This pattern is a very common and recommended way to use threads with Python. The steps are described as follows:

  1. Create an instance of Queue.Queue() and then populate it with data.
  2. Pass that instance of populated data into the threading class that you created from inheriting from threading.Thread.
  3. Spawn a pool of daemon threads.
  4. Pull one item out of the queue at a time, and use that data inside of the thread, the run method, to do the work.
  5. After the work is done, send a signal to the queue with queue.task_done() that the task has been completed.
  6. Join on the queue, which really means to wait until the queue is empty, and then exit the main program.

Just a note about this pattern: By setting daemonic threads to true, it allows the main thread, or program, to exit if only daemonic threads are alive. This creates a simple way to control the flow of the program, because you can then join on the queue, or wait until the queue is empty, before exiting. The exact process is best described in the documentation for the queue module, as seen in the Resources:

join()
"Blocks until all items in the queue have been gotten and processed. The count of unfinished tasks goes up whenever an item is added to the queue. The count goes down whenever a consumer thread calls task_done() to indicate that the item was retrieved and all work on it is complete. When the count of unfinished tasks drops to zero, join() unblocks.

Working with multiple queues

Because the pattern demonstrated above is so effective, it is relatively simple to extend it by chaining additional thread pools with queues. In the above example, you simply printed out the first portion of a Web page. This next example instead returns the whole Web page that each thread grabs, and then places it into another queue. Then set up another pool of threads that join on the second queue, and then do work on the Web page. The work performed in this example involves parsing the Web page using a third-party Python module called Beautiful Soup. Using just a couple of lines of code, with this module, you will extract the title tag and print it out for each page you visit.


Multiple queues data mining websites
 
                
import Queue
import threading
import urllib2
import time
from BeautifulSoup import BeautifulSoup

hosts = ["http://yahoo.com", "http://google.com", "http://amazon.com",
        "http://ibm.com", "http://apple.com"]

queue = Queue.Queue()
out_queue = Queue.Queue()

class ThreadUrl(threading.Thread):
    """Threaded Url Grab"""
    def __init__(self, queue, out_queue):
        threading.Thread.__init__(self)
        self.queue = queue
        self.out_queue = out_queue

    def run(self):
        while True:
            #grabs host from queue
            host = self.queue.get()

            #grabs urls of hosts and then grabs chunk of webpage
            url = urllib2.urlopen(host)
            chunk = url.read()

            #place chunk into out queue
            self.out_queue.put(chunk)

            #signals to queue job is done
            self.queue.task_done()

class DatamineThread(threading.Thread):
    """Threaded Url Grab"""
    def __init__(self, out_queue):
        threading.Thread.__init__(self)
        self.out_queue = out_queue

    def run(self):
        while True:
            #grabs host from queue
            chunk = self.out_queue.get()

            #parse the chunk
            soup = BeautifulSoup(chunk)
            print soup.findAll(['title'])

            #signals to queue job is done
            self.out_queue.task_done()

start = time.time()
def main():

    #spawn a pool of threads, and pass them queue instance
    for i in range(5):
        t = ThreadUrl(queue, out_queue)
        t.setDaemon(True)
        t.start()

    #populate queue with data
    for host in hosts:
        queue.put(host)

    for i in range(5):
        dt = DatamineThread(out_queue)
        dt.setDaemon(True)
        dt.start()


    #wait on the queue until everything has been processed
    queue.join()
    out_queue.join()

main()
print "Elapsed Time: %s" % (time.time() - start)


 

If you run this version of the script, you get the following output:

  # python url_fetch_threaded_part2.py 

  [<title>Google</title>]
  [<title>Yahoo!</title>]
  [<title>Apple</title>]
  [<title>IBM United States</title>]
  [<title>Amazon.com: Online Shopping for Electronics, Apparel,
 Computers, Books, DVDs & more</title>]
  Elapsed Time: 3.75387597084

  

In looking at the code, you can see that we added another instance of a queue, and then passed that queue into the first thread pool class, ThreadURL. Next , you almost copy the exact same structure for the next thread pool class, DatamineThread. In the run method of this class, grab the Web page, chunk, from off of the queue in each thread, and then process this chunk with Beautiful Soup. In this case, you use Beautiful Soup to simply extract the title tags from each page and print them out. This example could quite easily be turned into something more useful, as you have the core for a basic search engine or data mining tool. One idea is to extract the links from each page using Beautiful Soup and then follow them.



 

Summary

This article explored threads in Python and demonstrated the best practice of using queues to allieviate complexity and subtle errors, and to promote readable code. While this basic pattern is relatively simple, it can be used to solve a wide number of problems by chaining queues and thread pools together. In the final section, you began to explore creating a more complex processing pipeline that can serve as a model for future projects. There are quite a few excellent resources on both concurrency in general and threads in the Resources section.

In closing, it is important to point out that threads are not the solution to every problem, and that processes can be quite suitable for many situations. The standard library subprocess module in particular can be much simpler to deal with if you only require forking many processes and listening for a response. Please consult the Resources section for the official documentation on this.

Linux Tar-ing and un-tar-ing tarballs, gz, and bz2 archives Tutorial

What Is A Tarball?

A tarball is an archive of files and/or directories. If a tarball is gzip'd or bz2'd, then it has been compressed.


 

"Untar" A File

If you are dealing with a tarball (example.tar) file, you can extract the files from it using:

tar xvf example.tar

If the tarball has been gzipped(example.tar.gz), you can extract the files from it using:

tar xvfz example.tar.gz

If the tarball has been gzipped(example.tgz), you can extract the files from it using:

tar xzvf example.tgz

If the tarball has been compressed with bzip2(example.tar.bz2), then you will need to have bzip2 installed. ( Most servers will have this, but if yours does not, visit <a href="http://www.bzip.org/">http://www.bzip.org/</a> ) If all is well and bzip2 is installed, you can extract the files from it using:

tar yxf example.tar.bz2

Sometimes you only want to extract certain directories from the tarball. An example of doing so would be:

tar xvzf example.tar.gz */DIRECTORY_YOU_WANT_REPLACES_THIS_TEXT/*


 

List The Contents

If you would like to see what is inside a tarball, you can use the command:

tar tvf example.tar

If you would like to see what is inside a gzip'd tarball, you can use the command:

tar tzf example.tar.gz


 

Tar It Up!

If you would like to tarball some files, you can do so by using the command:

tar cvf filename.tar files/directories

If you would like to tarball some files AND compress them (with gzip), you can do so by using the command:

tar cfz blah.tar.gz files/directories


 

man tar

NAME
       tar - The GNU version of the tar archiving utility

SYNOPSIS
       tar <operation> [options]

       Operations:
       [-]A --catenate --concatenate
       [-]c --create
       [-]d --diff --compare
       [-]r --append
       [-]t --list
       [-]u --update
       [-]x --extract --get
       --delete

       Common Options:
       -C, --directory DIR
       -f, --file F
       -j, --bzip2
       -p, --preserve-permissions
       -v, --verbose
       -z, --gzip

       All Options:
       [  --atime-preserve  ]  [ -b, --blocking-factor N ] 
       [ -B, --read-full-records ] [ --backup BACKUP-TYPE ]
       [ --block-compress ] [ -C, --directory DIR ] [ --check-links ] 
       [ --checkpoint ] [ -f, --file [HOSTNAME:]F  ]
       [  -F,  --info-script  F  --new-volume-script  F  ]
       [  --force-local   ] [ --format FORMAT ]
       [ -g, --listed-incremental F ] [ -G, --incremental ]
       [ --group GROUP ] [ -h, --dereference ] [ --help ]
       [ -i,  --ignore-zeros  ]  [  --ignore-case  ]
       [ --ignore-failed-read  ]  [ --index-file FILE ] [ -j, --bzip2 ]
       [ -k, --keep-old-files ] [ -K, --starting-file F ]
       [ --keep-newer-files ] [ -l, --one-file-system ]
       [ -L, --tape-length N ] [ -m, --touch, --modification-time ]
       [  -M, --multi-volume  ]  [  --mode  PERMISSIONS  ]
       [ -N, --after-date DATE, --newer DATE ] [ --newer-mtime DATE ]
       [ --no-anchored ] [ --no-ignore-case ] [ --no-recursion ]
       [ --no-same-permissions ] [ --no-wildcards ]
       [  --no-wildcards-match-slash  ] [ --null     ] [ --numeric-owner ]
       [ -o, --old-archive, --portability, --no-same-owner ]
       [ -O, --to-stdout ] [ --occurrence NUM ] [ --overwrite ]
       [ --overwrite-dir ] [ --owner USER ]
       [ -p, --same-permissions, --pre-serve-permissions  ]
       [  -P,  --absolute-names  ]  [  --pax-option  KEYWORD-LIST ]
       [ --posix ] [ --preserve ] [ -R, --block-number ]
       [ --record-size SIZE ] [ --recursion ] [ --recursive-unlink ]
       [ --remove-files ]  [  --rmt-command CMD  ]
       [  --rsh-command  CMD  ] [ -s, --same-order, --preserve-order ]
       [ -S, --sparse ] [ --same-owner ] [ --show-defaults ]
       [ --show-omitted-dirs ]
    [ --strip-components NUMBER, --strip-path NUMBER (1) ]
       [ --suffix SUFFIX ] [ -T, --files-from  F ] [ --totals   ]
    [ -U, --unlink-first ] [ --use-compress-program PROG ] [ --utc ]
    [ -v, --verbose ] [ -V, --label NAME ] [ --version  ] [ --volno-file F ]
       [ -w, --interactive, --confirmation ] [  -W,  --verify  ]
    [ --wildcards  ] [  --wildcards-match-slash  ]  [  --exclude PATTERN ]
       [ -X, --exclude-from FILE ] [ -Z, --compress, --uncompress ]
       [ -z, --gzip, --gunzip, --ungzip ] [ -[0-7][lmh] ]

       (1) tar-1.14 uses --strip-path, tar-1.14.90+ uses --strip-components

DESCRIPTION
       This manual page documents the GNU version of tar, an archiving program 
    designed to store and extract files from an archive  file  known  as  a
    tarfile.  A tarfile may be made on a tape drive, however, it is also
    common to write a tarfile to a normal file.  The first argument to tar
    must be one of the options Acdrtux, followed by any optional functions.
    The final arguments to tar are the names of the files or directories 
    which should be archived.  The use of a directory name always implies 
    that the subdirectories below should be included in the archive.

EXAMPLES
       tar -xvf foo.tar
              verbosely extract foo.tar

       tar -xzf foo.tar.gz
              extract gzipped foo.tar.gz

       tar -cjf foo.tar.bz2 bar/
              create bzipped tar archive of the directory bar called foo.tar.bz2

       tar -xjf foo.tar.bz2 -C bar/
              extract bzipped foo.tar.bz2 after changing directory to bar

       tar -xzf foo.tar.gz blah.txt
              extract the file blah.txt from foo.tar.bz2

FUNCTION LETTERS
       One of the following options must be used:

       -A, --catenate, --concatenate
              append tar files to an archive

       -c, --create
              create a new archive

       -d, --diff, --compare
              find differences between archive and file system

       -r, --append
              append files to the end of an archive

       -t, --list
              list the contents of an archive

       -u, --update
              only append files that are newer than the existing in archive

       -x, --extract, --get
              extract files from an archive

       --delete
              delete from the archive (not for use on mag tapes!)

COMMON OPTIONS
       -C, --directory DIR
              change to directory DIR

       -f, --file [HOSTNAME:]F
              use archive file or device F (default "-", meaning stdin/stdout)

       -j, --bzip2
              filter archive through bzip2, use to decompress .bz2 files

       -p, --preserve-permissions
              extract all protection information

       -v, --verbose
              verbosely list files processed

       -z, --gzip, --ungzip
              filter the archive through gzip

ALL OPTIONS
       --atime-preserve
              donât change access times on dumped files

       -b, --blocking-factor N
              block size of Nx512 bytes (default N=20)

       -B, --read-full-blocks
              reblock as we read (for reading 4.2BSD pipes)

       --backup BACKUP-TYPE
              backup files instead of deleting them using BACKUP-TYPE simple or numbered
       --block-compress
              block the output of compression program for tapes

       -C, --directory DIR
              change to directory DIR

       --check-links
              warn if number of hard links to the file on the filesystem mismatch the 
     number of links recorded in the archive

       --checkpoint
              print directory names while reading the archive

       -f, --file [HOSTNAME:]F
              use archive file or device F (default "-", meaning stdin/stdout)

       -F, --info-script F --new-volume-script F
              run script at end of each tape (implies --multi-volume)

       --force-local
              archive file is local even if has a colon

       --format FORMAT
              selects output archive format
              v7 - Unix V7
              oldgnu - GNU tar <=1.12
              gnu - GNU tar 1.13
              ustar - POSIX.1-1988
              posix - POSIX.1-2001

       -g, --listed-incremental F
              create/list/extract new GNU-format incremental backup

       -G, --incremental
              create/list/extract old GNU-format incremental backup

       -h, --dereference
              donât dump symlinks; dump the files they point to

       --help like this manpage, but not as cool

       -i, --ignore-zeros
              ignore blocks of zeros in archive (normally mean EOF)

       --ignore-case
              ignore case when excluding files

       --ignore-failed-read
              donât exit with non-zero status on unreadable files

       --index-file FILE
              send verbose output to FILE instead of stdout

       -j, --bzip2
              filter archive through bzip2, use to decompress .bz2 files

       -k, --keep-old-files
              keep existing files; donât overwrite them from archive

       -K, --starting-file F
              begin at file F in the archive

       --keep-newer-files
              do not overwrite files which are newer than the archive

       -l, --one-file-system
              stay in local file system when creating an archive

       -L, --tape-length N
              change tapes after writing N*1024 bytes

       -m, --touch, --modification-time
              donât extract file modified time

       -M, --multi-volume
              create/list/extract multi-volume archive

       --mode PERMISSIONS
              apply PERMISSIONS while adding files (see chmod(1))

       -N, --after-date DATE, --newer DATE
              only store files newer than DATE

       --newer-mtime DATE
              like --newer, but with a DATE
       --no-anchored
              match any subsequenceof the nameâs components with --exclude

       --no-ignore-case
              use case-sensitive matching with --exclude

       --no-recursion
              donât recurse into directories

       --no-same-permissions
              apply userâs umask when extracting files instead of recorded permissions

       --no-wildcards
              donât use wildcards with --exclude

       --no-wildcards-match-slash
              wildcards do not match slashes (/) with --exclude

       --null --files-from reads null-terminated names, disable --directory

       --numeric-owner
              always use numbers for user/group names

       -o, --old-archive, --portability
              like --format=v7; -o exhibits this behavior when creating an 
     archive (deprecated behavior)

       -o, --no-same-owner
              do not attempt to restore ownership when extracting; -o exhibits 
     this behavior when extracting an archive

       -O, --to-stdout
              extract files to standard output

       --occurrence NUM
              process only NUM occurrences of each named file; used with --delete, 
     --diff, --extract, or --list

       --overwrite
              overwrite existing files and directory metadata when extracting

       --overwrite-dir
              overwrite directory metadata when extracting

       --owner USER
              change owner of extraced files to USER

       -p, --same-permissions, --preserve-permissions
              extract all protection information

       -P, --absolute-names
              donât strip leading â/âs from file names

       --pax-option KEYWORD-LIST
              used only with POSIX.1-2001 archives to modify the way tar handles 
     extended header keywords

       --posix
              like --format=posix

       --preserve
              like --preserve-permissions --same-order

       -R, --record-number
              show record number within archive with each message

       --record-size SIZE
              use SIZE bytes per record when accessing archives

       --recursion
              recurse into directories

       --recursive-unlink
              remove existing directories before extracting directories of the 
     same name

       --remove-files
              remove files after adding them to the archive

       --rmt-command CMD
              use CMD instead of the default /usr/sbin/rmt

       --rsh-command CMD
              use remote CMD instead of rsh(1)

       -s, --same-order, --preserve-order
              list of names to extract is sorted to match archive

       -S, --sparse
              handle sparse files efficiently
       --same-owner
              create extracted files with the same ownership

       --show-defaults
              display the default options used by tar

       --show-omitted-dirs
              print directories tar skips while operating on an archive

       --strip-components NUMBER, --strip-path NUMBER
              strip NUMBER of leading components from file names before extraction

              (1) tar-1.14 uses --strip-path, tar-1.14.90+ uses --strip-components

       --suffix SUFFIX
              use SUFFIX instead of default â~â when backing up files

       -T, --files-from F
              get names to extract or create from file F

       --totals
              print total bytes written with --create

       -U, --unlink-first
              remove existing files before extracting files of the same name

       --use-compress-program PROG
              access the archive through PROG which is generally a compression 
     program

       --utc  display file modification dates in UTC

       -v, --verbose
              verbosely list files processed

       -V, --label NAME
              create archive with volume name NAME

       --version
              print tar program version number

       --volno-file F
              keep track of which volume of a multi-volume archive its working 
     in FILE; used with --multi-volume 

       -w, --interactive, --confirmation
              ask for confirmation for every action

       -W, --verify
              attempt to verify the archive after writing it

       --wildcards
              use wildcards with --exclude

       --wildcards-match-slash
              wildcards match slashes (/) with --exclude

       --exclude PATTERN
              exclude files based upon PATTERN

       -X, --exclude-from FILE
              exclude files listed in FILE

       -Z, --compress, --uncompress
              filter the archive through compress

       -z, --gzip, --gunzip, --ungzip
              filter the archive through gzip

       --use-compress-program PROG
              filter the archive through PROG (which must accept -d)

       -[0-7][lmh]
              specify drive and density

BUGS
       The  GNU  folks,  in general, abhor man pages, and create info documents 
    instead.  The maintainer of tar falls into this category.  Thus this man 
    page may not be complete, nor current, and was included in the Red Hat CVS 
    tree because  man  is  a  great  tool  :).   This man page was first taken 
    from Debian Linux and has since been lovingly updated here.

REPORTING BUGS
       Please report bugs via https://bugzilla.redhat.com

SEE ALSO
       The full documentation for tar is maintained as a Texinfo manual.  If 
    the info and tar programs are properly installed at your site, the command

              info tar

       should give you access to the complete manual.

AUTHORS
       Debian Linux http://www.debian.org/
       Mike Frysinger <vapier@gentoo.org>

GNU                                                      Oct 2004                                                   TAR(1)


 

Moving FreeBSD to a New Hard Drive

This tutorial explain how to move a FreeBSD operating system and data to a new hard drive. This is useful if your hard drive is old/slow or too small. Also this can be used if you experience problems with your hard drive and you want to make sure the hard drive will not crash.

Warning! before doing this saves your data! We are not responsable if you use wrong commands and lose your data!

In this tutorial ad0 is old hard drive and ad1 is the new hard drive. Depending on your configurations your drives might have other names, for example da for SCSI, or ad4 and ad5 for SATA drives (depending on how bios is configured, for SATA you might have ad0 too), so replace ad0 and ad1 with your drives. Make sure you know exactly what are your drives name otherwise you might run command on the wrong hard drives and loose data.

Use "dmesg" command to find your hard drives names, that will also tell you the drive size and manufacturer.


Step 1. Add your second hard drive
-------------------------------------------------
Add your new hard drive to the system as a second hard drive.
If you use an IDE drive make sure your new added drive is on secondary IDE, still setup as master.


Step 2. Boot to single mode
--------------------------------------
Boot to single mode, by pressing SPACE at boot time, when loader starts and then type:

boot -s

This will boot the system in single mode. You could also choose "single mode" from menu that appears when FreeBSD starts.


Step 3. Check all partitions for errors
---------------------------------------------------

fsck -p


Step 4. Mount all partitions and activate swap
--------------------------------------------------------------
First, we will mount root partition with read/write support:

mount -u /

Then mount all partitions:

mount -a


Activate swap:

swapon -a

If the computer is set to local time we will also need to run:

adjkerntz -i


Step 5. Create directories where we will mount the new hard drive
--------------------------------------------------------------------------------------------
Next we must create directories where we will then mount partitions from the new hard drive that, of course must be created too.

mkdir /mnt/backup/ /mnt/backup/root /mnt/backup/usr /mnt/backup/var


Step 6. Create slice and partitions for the new hard drive
------------------------------------------------------------------------------

To create slice and then partitions for the new drive you have two options: to do that from sysinstall or from command line. Either will work. To create partitions from sysinstall tool is trivial so we will show how to create partitions from command line.

Clear boot and disklabel (sector0):

dd if=/dev/zero of=/dev/ad1 bs=1k count=1

Initialize sector 0 of the disk.  Existing slice entries will be cleared. Then reinitialize the boot code contained in sector 0 of the disk.

fdisk -BI ad1

Label the disk. Bootstrap code will be read from the file /boot/boot and written to the disk. Also a standard label will be written (-w option).

disklabel -B -w ad1s1 auto

Edit disklabel and add new partitions:

disklabel -e ad1s1

Last command will enter an text editor where you can add partitions. For a default/generic/usual FreeBSD system we will have
ad1s1a - / (root partition)
ad1s1b - swap
ad1s1d - /tmp
ad1s1e - /var
ad1s1f - /usr

Letter at the end of ad1s1 are partition identifiers and can have values from a to h. By convention, 'c' is reserved for describing entire disk.

The partition table list partitions on multiple rows, with every partition on a single row. We can have up to 8 entries (values) for a
partition - partition identifier, size, offset, fstype, fsize, bsize, bps/cpg.
Example:
# /dev/ad1s1:
8 partitions:
#        size   offset    fstype   [fsize bsize bps/cpg]
  a:  2097152        0    4.2BSD     2048 16384 28552
  b:  1024000  2097152      swap
  c: 156296322        0    unused        0     0         # "raw" part, don't edit
  d: 10485760  3121152    4.2BSD     2048 16384 28552
  e:  2097152 13606912    4.2BSD     2048 16384 28552
  f: 140592258 15704064    4.2BSD     2048 16384 28552

size - is the size of partition and can be in sectors (of 512 bytes in size), K bytes, M bytes or G bytes.

offset
- is the offset of the start of partition from begining of drive in sectors. Also you can add instead * to let disklabel calculate the offset for you.

fstype - partition type: for UFS is 4.2BSD, for vinum drives is vinum. Other types could be swap or unused.

fsize - the fragment size

bsize - block size

bps/cpg - number of cylinders in a cylinder group.

For more info: man disklabel and man newfs.

After you've created all partitions you need save and exit with :wq (vi commands).


Step 7. Create filesystem for all newly created partitions
------------------------------------------------------------------------------
We will create file systems for partition we've setup with disklabel:

newfs /dev/ad1s1a
newfs /dev/ad1s1e
newfs /dev/ad1s1f


Step 8. Mount newly created partitions
------------------------------------------------------
We will create directories in /mnt on current system, where we will mount the newly created partitions from second hard drive:

mkdir /backup/root
mkdir /backup/var
mkdir /backup/usr

Now we will mount the newly created partitions from second hard drive:

mount /dev/ad1s1a /backup/root
mount /dev/ad1s1e /backup/var
mount /dev/ad1s1f /backup/usr


Step 9. Dump data from old drive
----------------------------------------------
We will move everything from root, var and usr partitions to newly created partitions on new hard drive:

(dump -0f - /) | ( cd /backup/root; restore -rf - )
(dump -0f - /var) | ( cd /backup/var; restore -rf - )
(dump -0f - /usr) | ( cd /backup/usr; restore -rf - )


Step 10. Umount the new drive partitions
---------------------------------------------------------
umount /backup/root
umount /backup/var
umount /backup/usr


Step 11. Enable soft updates for partitions on new drive
-----------------------------------------------------------------------------

tunefs -n enable /dev/ad1s1a
tunefs -n enable /dev/ad1s1e
tunefs -n enable /dev/ad1s1f

Now you should have a new hard drive with all your old info. Replace the old hard drive and make sure it is connected on the same device. If it has different drive name, for example instead of ad0 it is on SATA and is named ad4, edit /etc/fstab and change partition names from ad0 to ad4, for example for root will be /dev/ad4s1a.
 

Speaking UNIX: It is all about the inode

Have you ever wondered what Iused and %Iused mean in UNIX® commands like df or what people are talking about when the say inode? UNIX and Linux® systems both use inodes, and IBM® AIX® is no different. Discover what an inode is and why inodes are important to UNIX, the structure of an inode, and commands for working with inodes.

An inode is a data structure in UNIX operating systems that contains important information pertaining to files within a file system. When a file system is created in UNIX, a set amount of inodes is created, as well. Usually, about 1 percent of the total file system disk space is allocated to the inode table.

Sometimes, people interchange the terms inode and inumber. The terms are similar and do correspond to each other, but they don't refer to the same things. Inode refers to the data structure; the inumber is actually the identification number of the inode—hence the term inode number, or inumber. The inumber is only one important item of information for a file. Some of the other attributes in an inode are discussed in the next section.

The inode table contains a listing of all inode numbers for the respective file system. When users search for or access a file, the UNIX system searches through the inode table for the correct inode number. When the inode number is found, the command in question can access the inode and make the appropriate changes if applicable.

Take, for example, editing a file with vi. When you type vi <filename>, the inode number is found in the inode table, allowing you to open the inode. Some attributes are changed during the edit session of vi, and when you have finished and typed :wq, the inode is closed and released. This way, if two users were to try to edit the same file, the inode would already have been assigned to another user ID (UID) in the edit session, and the second editor would have to wait for the inode to be released.

The inode structure

The inode structure is relatively straightforward for seasoned UNIX developers or administrators, but there may still be some surprising information you don't already know about the insides of the inode. The following definitions provide just some of the important information contained in the inode that UNIX users employ constantly:

  • Inode number
  • Mode information to discern file type and also for the stat C function
  • Number of links to the file
  • UID of the owner
  • Group ID (GID) of the owner
  • Size of the file
  • Actual number of blocks that the file uses
  • Time last modified
  • Time last accessed
  • Time last changed

Basically, the inode contains all information about a file outside of the actual name of the file and the actual data content of the file. The full inode structure can be found in the header file /usr/include/jfs/ino.h in AIX or on the Web at http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.files/doc/aixfiles/inode.h.htm.

The information listed above is important to files and is used heavily in UNIX. Without with this information, a file would appear corrupt and unusable.

Directories and files may appear different on UNIX systems compared to other operating systems, but they aren't. In UNIX, directories are actually files that have a few additional settings in their inodes. A directory is basically a file containing other files. Also, the mode information has flags set to inform the system that the file is actually a directory.


 

Working with inodes

Knowing how to work with inodes in UNIX can save a lot of time and frustration. You can use the following commands to alleviate some of the headaches you may have when you don't know about inodes.

The df command

As mentioned earlier, when you create a file system in UNIX, about 1 percent of the total disk space is allocated to the inode table. Every time you create a file in the file system, an inode is allocated to the file. Typically, there is an adequate number of inodes associated with a file system, but running out of inodes is always a possibility. To monitor this, you can view the output of the df.

Using the df command, you can look at all mounted file systems or specific file systems. In this view, you can see the number of inodes used already in the respective file system as well as the percentage used overall in the file system, as Listing 1 shows.


Listing 1. Using df to monitor inode use
 
                
# df -k|head -6

Filesystem    1024-blocks      Free %Used    Iused %Iused Mounted on
/dev/hd4           229376    138436   40%     4730    13% /
/dev/hd2          8028160    962692   89%   110034    33% /usr
/dev/hd9var       1835008    366400   81%    25829    24% /var
/dev/hd3           524288    523564    1%       98     1% /tmp
/dev/hd1            32768     32416    2%        5     1% /home

 

If for some reason a file system did reach 100 percent of its inodes used, you won't be able to create additional files, devices, directories, and so on in the file system. One solution is to add more space to the file system through the smitty chfs command, as shown in Figure 1. Another solution is to create smaller inode extents. IBM AIX 5L now allows for inode extends smaller than the default size of 16KB on enhanced journal file systems. Please keep in mind, though, that if you use this option in AIX 5L, the file system will not be accessible from previous versions of AIX.


Figure 1. The result of the smitty chfs command
smitty chfs
 

istat and stat

A quick way to examine an inode in AIX is by using the istat command. With this command, you can find the inumber of the specific file as well as other inode items like permissions; file type; UID; GID; number of links (not symbolic links); file size; and time stamps for last updated, last modified, and last accessed.

Listing 2 shows inode information for the file /usr/bin/ksh in AIX.


Listing 2. Inode information for /usr/bin/ksh
 
                
                # istat /usr/bin/ksh

Inode 18150 on device 10/8      File
Protection: r-xr-xr-x
Owner: 2(bin)           Group: 2(bin)
Link count:   5         Length 237804 bytes

Last updated:   Wed Oct 24 17:37:10 EDT 2007
Last modified:  Wed Apr 18 23:58:06 EDT 2007
Last accessed:  Mon Apr 28 11:25:35 EDT 2008

 

In addition to showing the standard information from istat, you now know what the inumber is for /usr/bin/ksh. If you also find the logical volume in which the file resides, you can display even more information. One way to find this information is by looking at the mounted file system in which the file resides with the df command:

                # df /usr/bin

Filesystem    512-blocks      Free %Used    Iused %Iused Mounted on
/dev/hd2        16056320   1925384   89%   110034    33% /usr

 

The file /usr/bin/ksh resides in the directory /usr/bin. Looking at the output of the df command, you can tell that the directory /usr/bin is contained in the /usr file system and that the /usr file system is inside the logical volume /dev/hd2. Now that you know both the inumber and the logical volume name, using istat with both items of information as arguments, you can determine the hexadecimal addresses of the disk blocks that make up the file, as shown in Listing 3.


Listing 3. Determining the hexadecimal addresses of the file blocks
 
                
                # istat 18150 /dev/hd2

Inode 18150 on device 10/8      File
Protection: r-xr-xr-x
Owner: 2(bin)           Group: 2(bin)
Link count:   5         Length 237804 bytes

Last updated:   Wed Oct 24 17:37:10 EDT 2007
Last modified:  Wed Apr 18 23:58:06 EDT 2007
Last accessed:  Mon Apr 28 11:44:20 EDT 2008

Block pointers (hexadecimal):
11620     ef8c0
            

 

Linux has its own version of istat: stat. The Linux stat command shows similar information and also includes some switches not available in the AIX istat command:

                # stat /bin/bash

  File: `/bin/bash'
  Size: 722684          Blocks: 1432       IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 12799859    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2008-04-06 19:13:50.000000000 -0400
Modify: 2006-07-12 03:11:53.000000000 -0400
Change: 2007-11-22 04:05:30.000000000 -0500

 

The ls command

At one time or another in your career, you've had to worry about removing or managing files with dashes or other special characters in the file name or file names that appear not to have a file name at all. Most likely, someone mistakenly named the respective file.

Because most commands in UNIX include switches, or options, that begin either with a hyphen (-) or a double hyphen (--), it can be difficult to manipulate these files with commonly used commands such as rm, mv, and cp. Thankfully, there are options in commands to show the inumber of the inode associated with the file in question. The ls command has such an option:

                # ls

       -      --     -p     fileA  fileB  fileC  fileD
fileE  fileF  fileG  fileH  fileI  fileJ  fileK  fileL

 

Using the ls -i command, you can view the inumber next to the file name, as shown in Listing 4. Now that you know the inumber, you can easily manipulate the file.


Listing 4. Viewing the inumber of the file
 
                
                # ls –i

38988        38991 -p     38984 fileC  38982 fileF  38977 fileI  38978 fileL
38989 -      38980 fileA  38986 fileD  38983 fileG  38987 fileJ
38990 --     38979 fileB  38976 fileE  38985 fileH  38981 fileK

 

The find command

Using the UNIX find command, you can finish what you started with the ls command. Now that you know the inumber for the respective files that you must manipulate, you can start!

To remove the file that looks like it has no name, simply use find with the -inum switch to locate the inumber and file. Then, when the file has been found, use find with the -exec switch to remove the file:

# find . -inum 38988 -exec rm {} \;

 

To rename the file, do the same again, but this time use mv rather than rm:

# find . -inum 38989 -exec mv {} fileM \;

 

To verify that you're getting the expected results, simply use the ls -i command again:

                # ls -i

38990 --     38979 fileB  38976 fileE  38985 fileH  38981 fileK
38991 -p     38984 fileC  38982 fileF  38977 fileI  38978 fileL
38980 fileA  38986 fileD  38983 fileG  38987 fileJ  38989 fileM

 

The fsck command

Unfortunately, hardware doesn't last forever, and systems can fail over years of continued use. When this happens and the operating system shuts down abnormally because of a power failure or another issue, you may encounter files when you bring the system back up that were open during the crash and now need assistance. During times like this, you may run into messages that inodes need to be repaired or that an error exists. If this happens, the fsck command can be a lifesaver! Rather than restoring the system or even rebuilding the operating system, you can use fsck to repair file systems or correct damaged inodes.

The following command attempts to repair the logical volume /dev/hd1:

# fsck –p /dev/hd1 –y

 

By using the fsck command, you can narrow the search for damaged inodes, as well. If you're searching for a specific inode, you can use the -ii-NodeNumber switch with fsck.



 

Conclusion

Files and directories would be nearly useless in UNIX without the helping hand of the inode. Hopefully, after reading this article, you understand inodes better, their importance to AIX, and also how to manage them. You may never look at df the same way again.

Linux Firewall: IPTables Tutorial

iptables is a tool used in linux distributions to control kernel's netfilter's firewall. Here is a tutorial on iptables.

iptables firewall contains 3 tables, every table contains chains. Those chains are default. User is able to define new chains and link from default chains to those user defined chains.


1. iptables tables
--------------------

iptables contains 3 tables:
a. filter table
b. nat table
c. mangling table


a. filter table
This table is used to filter packets that pass the firewall. Its purpose is only packet filtering, and will filter packets that comes to the machine (incoming), packets that goes out (outgoing) and packets that are forwarded between network cards (filtering), in case that machine has two or more network cards.

That table contains 3 chains: INPUT chain, OUTPUT chain and FORWARD chain.

INPUT chain -
used to filter incoming packets
OUTPUT chain - used to filter outgoing packets
FORWARD chain - used to filter forwarded packets (between network cards).

b. nat table
This table is used to change source of the IP.
PREROUTING chain - used to change IP before forwarding take place
POSTROUTING chain - used to change IP after forwarding take place
OUTPUT chain - used to filter on outgoing

c. mangle
This tables is used to modify packets.


2. Syntax of a iptables rule:

------------------------------------
iptables name_of_table name_of_chain layer3_object layer4_object jump_target

Notes:
- by default if name of table is not specify (with "-t nat" for example, for nat table, or "-t mangle" for mangle table), default table is used: filter table;
- layer4_object is not mandatory;

iptables Examples:
iptables -A INPUT -s 192.168.0.1 -j DROP       # will drop all packets that comes from IP 192.168.0.1


3. Chain management
-----------------------------
List tables and chains:
iptables -L                                   # will list all rules from all chains from filter table
iptables -L -v #                            # will list all rules from all chains from filtering table, in verbose mode,
                                                    # showing also packets and bytes that matched that rules
iptables -L -v --line-numbers       # will show above and also rule numbers

iptables -L INPUT                        # will show all rules from INPUT chain from filter table

iptables -L -t nat                          # will show all rules from all chains from nat table
iptables -t nat -L PREROUTING   # will show all rules from PREROUTING chain from nat table

iptables -L -t mangle                   # will show all rules from all chains from mangle table


Adding rules to chains:
To add a rule to a chain use:
iptables -A INPUT -s 192.168.0.1 -j ACCEPT     # will allow traffic from source IP 192.168.0.1
iptables -A INPUT -p tcp --dport 22 -j DROP      # will drop all traffic to destination port 22 (our ssh port)

iptables -A will append rule at the end of rules list  in your specified chain. if you want to insert a rule on a specific position in your chain, then you must use -I.

iptables -I INPUT 1 -s 192.168.0.1 -j ACCEPT    # will add rule in position 1 in your INPUT chain
iptables -I INPUT 10 -p tcp --dport 22 -j DROP   # will add a rule in position 10 of your INPUT chain.

Rules are evaluated from first to last rule. On ACCEPT or DROP rules, if a rule is matched, it will not be evaluated to next rules.

Note 1:  if you want to block traffic that comes to your machine you must add rule on INPUT chain. If you want to block traffic to a destination IP from your machine you must add rule in OUTPUT chain. Also you must have networking knowledge and you must understand how firewall works.

Note 2:
Each chain have a default policy. Policy can be ACCEPT or DROP, by default all CHAIN have ACCEPT policy.

Note 3: When adding a rule -j parameter (jump) can have the following values: ACCEPT, DROP, REJECT, DENY, LOG.

Delete all rules from all chains:
iptables -F                                 # will delete all rules from filter table
iptables -F -t nat                       # will delete all rules from nat table
iptables -F -t mangle                 # will delete all rules from mangle table


Deleting a rule from a chain:
To delete a rule from a chain you have two posibilities: to delete a rule using rule number or to delete using syntax used when rule was added:

iptables -D INPUT 10                          # will delete rule 10 from INPUT chain
iptables -D PREROUTING 10 -t nat     # will delete rule 10 from PREROUTING chain from nat table

iptables -D INPUT -s 192.168.0.1 -j ACCEPT      # will delete rule that was added with iptables -A INPUT -s 192.168.0.1 -j ACCEPT

Note: On our previous example, the first rule that match that syntax will be deleted. If are many similar rules, only first will be deleted. To delete all rules that match that syntax, you must use previous command multiple times until you delete all rules.

To delete all rules you can also use (on some old versions of linux, it will not work with -F but with --flush, because of some bugs):
iptables --flush

Saving / Restoring iptables rules:
iptables-save >rules.txt
iptables-restore <rules.txt

(If iptables is not in your path, you can use absolute paths: /sbin/iptables-save, and /sbin/iptables-restore).
Running iptables-save will output rules on standard output (usualy this is screen, so because of that you must use redirections).

4. Chain policy

As I said previously, each chain have a default policy that can be ACCEPT or DROP and by default all CHAIN have ACCEPT policy.
To change chain policy use:

iptables -P INPUT DROP

Note 1: If you are logged to your machine remotely via SSH (and you are not at console) be careful when you change default policy to drop, to not lock you out. Usualy when sysadmins tests firewall remotely it is a good practice to add to your CRON service a rule that will open the firewall, and you enable that script to run every half an hour or 15 minutes, so if you will lock out of your box, after 15 minutes the firewall will be opened.

Note 2: When you design firewall rules to allo access to your machine and block everything else, take in consideration that traffic goes both ways. If you allow traffic on INPUT chaing but your OUTPUT chain block everything, your rule will not work. Usualy is a good practice when you protect your machine to allow everything on OUTPUT ( you want to be able from your machine to do anything), and block everything on INPUT (incoming) for connections that are not initiated from your machine. If your machine run public services, like for example a web server, or a mail server then you must allow connections from outside on INPUT only on ports used by those services (for example allow incoming on port 80 - http, port 25 - smtp, port 110 - pop3 and 143 -imap, mail services.) So as a conclusion when you design your firewall, setup your default policy on INPUT to drop all packets and on OUTPUT leave it default, to allow everything. And then design your firewall.

Note 3: If your machine is not only connected to Internet, but is also a router for your LAN clients, then you must also filter connections from LAN. It is recommended to change policy on FORWARD chain to DROP and then allow only IPs you want from LAN to be able to access Internet.