Home > Geek stuff > Stupid Unix Tricks http://kevininscoe.com/geek/tricks/
Last updated: 935 day(s) ago (Fri Jul 20 11:25:23 2007) Tue Feb 9 06:17:34 2010

Stupid Unix Tricks

Many years ago late night talk show host David Letterman used to offer his
show Late Night With David Letterman a bit called Stupid Pet Tricks.
Well over the years I have collected what I call Stupid Unix tricks.

  • Network

    Understanding Traceroute and How to Use It
    IP Addressing Magic

  • Email

    Determining what version of Sendmail you are running
    Using Pine to read Netscape email archives
    Blocking email with Sendmail

  • vi

    Spellcheck in vi

  • Misc

    chroot jail for ftpd
    Creating a plain text man page

  • Shell

    Embedding AWK/SED programs in shell scripts
    bash shell prompting magic
    Obtaining yesterday's and tomorrow's dates
    Using eval
    Stacking shell commands
    Convert Backspace key to erase
    ksh tricks

  • Linux

    How to get rid of weird binary characters in the man pages for Redhat 8

  • images


  • Solaris

    Two important commands to set up modems and terminal characters
    Making You Own Entries To The System Log File in Solaris
    Obtaining system configuration
    Changing a Solaris hosts name or IP address
    Where things are logged in Solaris

  • Jobs

    Executing cronjobs on a certain day of month
    Adding a job to cron from a script

  • Files

    Traverse a directory tree and change all filenames to lowercase
    Creating temporary files securely
    VMS style searching of files
    Recursive grep
    Clone a filesystem or directory from one host to another
    Locating the largest files in descending order
    Renaming File Types
    Using tar for flexible archives
    Monitoring progress of output files
    Deleting a file by Inode
    Searching for strings in binary files
    Figuring out what's on the archive tape

  • Submit a suggestion


    Understanding Traceroute and How to Use It


    Notes:

    http://www.bah.org/~greg/traceroute.html
    http://students.engr.scu.edu/~dwelch/pig/tech/ping.html

    Definitions:
    ICMP - Internet Control Message Protocol is provided within IP which generates error
    messages to help in diagnosing IP delivery problems.
    TTL - Time to live can be viewed as a hop counter. A datagram starts with 30 hops, if it
    doesn't reach its destination by 30 hops, the sending node gets notified that the node or
    Host is Unreachable.
    Tracert - Windows/NT built-in traceroute utility which is run in the dos window.
    Traceroute Utility - From sled you can type traceroute (ip address or fully qualified node
    name)
    
    Fundamentals of Internet Communications:
    To understand traceroute, you must understand something fundamental about the nature of
    Internet communications. As you may know, the Internet gets data from one place to another
    by formatting it as a "packet," which is simply a chunk of data along with some routing
    information and a few other things attached in a specific format. The pieces of extra
    information pertinent to this discussion are the source IP address, destination IP
    address, and Time-To-Live (TTL), which is simply a number specifying how many "hops" the
    packet is allowed to take during its journey across the Internet. All data is passed
    across the network in the form of packets, and it is the job of the Internet's many
    "routers" to decide how to get packets from one place to another. The way it works is best
    illustrated with a step-by-step walk-through: When one computer has some information to
    send (a web page, perhaps), it puts it in a packet (or multiple packets), and sets the TTL
    to some initial value (typically 30). The computer then sends the packet to a router
    (Router A) which is directly connected, whether it be by Ethernet, PPP (dialup), or some
    other form of network. Router A would be called the "default gateway" for that computer.
    
    Generally, all routers will be connected in some form to one or more OTHER routers. Router
    A will examine the packet to determine the destination IP address and will, based on that
    address, choose one of these other routers which will get the packet closer to the
    destination. This new router (Router B) is referred to as the "Next Hop". There are many
    ways that the router might be able to choose the most appropriate Next Hop intelligently,
    but a discussion of "routing protocols" is beyond the scope of this article. At any rate,
    Router A will then decrement the TTL by one, and forward the packet to the new router,
    Router B.
    
    This process of "hopping" repeats indefinitely, with Router B choosing a new Next Hop,
    decrementing the TTL, and forwarding the packet, etc. until one of two things happens: 1)
    The packet reaches its destination, or 2) the TTL decrements to zero, or "times out." It's
    this last bit that allows traceroute to do its magic. We are now at a point where we can
    explain just what it is that traceroute is supposed to do.
    
    Traceroute's Mission:
    Traceroute's mission in life is to show you the path a packet sent from your machine to
    some other machine on the network takes as it hops from router to router. It will show you
    the IP address (and the actual name, usually) of each router, line-by-line.
    It's time for an example: The time you'd want to use traceroute is when you can't reach
    some remote site. For example, after a bit of searching, we've found that I can't
    currently reach 207.13.21.254, and I want to know why. Using Windows 95/NT's built-in
    traceroute utility (called "tracert"), we can see the following output:
    
    C:\>tracert 207.13.21.254
    
       traceroute to 207.13.21.254 (207.13.21.254), 30 hops max, 40 byte packets
     1  rtr-cne-e.gsfc.nasa.gov (128.183.50.1)  2 ms  1 ms  1 ms
     2  rtr-wan1-cf.gsfc.nasa.gov (128.183.251.1)  2 ms  1 ms  1 ms
     3  rtr-internet-ef.gsfc.nasa.gov (192.43.240.36)  6 ms  4 ms  4 ms
     4  sl-mae-e-f0-0.sprintlink.net (192.41.177.241)  7 ms  25 ms  18 ms
     5  sl-bb5-dc-6-1-0.sprintlink.net (144.232.8.25)  41 ms  47 ms *
     6  sl-bb3-dc-4-0-0-155M.sprintlink.net (144.232.0.6)  29 ms *  48 ms
     7  144.232.8.113 (144.232.8.113)  51 ms  43 ms  40 ms
     8  sl-bb1-atl-4-0-0-155M.sprintlink.net (144.232.1.198)  40 ms *  61 ms
     9  sl-bb5-fw-1-0-0.sprintlink.net (144.232.8.98)  86 ms  84 ms  79 ms
    10  sl-bb1-fw-4-0-0-155M.sprintlink.net (144.232.1.150)  86 ms  85 ms *
    11  * * sl-gw13-fw-0-0.sprintlink.net (144.228.30.17)  87 ms
    12  sl-comp-3-0.sprintlink.net (144.228.137.14)  91 ms  90 ms *
    13  cisco3640-1.cmpu.net (204.96.11.48)  95 ms  88 ms  90 ms
    14  cisco7505-1.cmpu.net (204.96.11.1)  149 ms * *
    15  cisco3640-1.cmpu.net (204.96.11.48)  113 ms  114 ms  113 ms
    .
    .
    28  cisco7505-1.cmpu.net (204.96.11.1)  149 ms * *
    29  cisco3640-1.cmpu.net (204.96.11.48)  113 ms  114 ms  113 ms
    30  * cisco7505-1.cmpu.net (204.96.11.1)  111 ms *       Trace complete.
    
    First of all, please note that we edited out lines 16 through 27. As you can see, for each
    hop, tracert shows us the hop number, three "round-trip" times, the name of the router (if
    available), and the router's IP address. Let's skip the round-trip times for a moment and
    examine the other things tracert is telling us.
    
    It shows us that the first hop my packet takes from my desktop computer is to
    rtr-cne-e.gsfc.nasa.gov (which is one of CNE's routers). Tracert then tells us that for
    this particular destination (207.13.21.254), our router determines that the best Next Hop 
    is rtr-wan1-cf.gsfc.nasa.gov.  That router passes the packet to
    rtr-internet-ef.gsfc.nasa.gov, then it traverses to Sprintnet,
    where it reaches hop 13, cisco3640-1.cmpu.net (204.96.11.48)  , which immediately forwards
    it to  cisco7505-1.cmpu.net (204.96.11.1) , and THIS is where we start to see problems:
    cisco7505-1.cmpu.net (204.96.11.1) passes it BACK to cisco3640-1.cmpu.net (204.96.11.48)
    and again, and again ...! This circular routing continues until the end of the traceroute
    (30 hops), clearly showing us the location of the routing failure (in
    cisco7505-1.cmpu.net), and why the packet is never reaching its destination.
    Unfortunately, there's nothing we at CNE can do to fix this problem, as it is external to
    our network. Internal, yes, we can contact the owner of the offending router.
    
    HOW DOES IT WORK???
    Just a couple more important things about traceroute: First, HOW DOES IT WORK??? You may
    recall ICMP (Internet Control Message Protocol), and also that we said that traceroute
    relies on packet time-outs. To determine the first hop, traceroute simply sends a packet
    to the destination, but instead of setting the TTL to 30, as usual, it sets the TTL to 1,
    meaning the packet is only allowed to take one hop. It takes that hop, arriving at the
    "hop 1" router, which faithfully decrements the TTL and notices that it is now zero.
    Whenever a router sees the TTL go to zero, it does two things: it 1) drops the packet (NOT
    forwarding it at all), and 2) sends an ICMP packet BACK to the source IP address of the
    dropped packet. This ICMP message says that the "TTL Expired in Transit." The source IP
    address of the ICMP message IS the address of the router itself, so traceroute can now see
    the IP address of the router at hop 1. Windows 95/NT's tracert (like most) performs this
    little test three times for each hop (by default), also keeping track of how long it takes
    for each error message to return. This is how it gets the round-trip times (in
    milliseconds), which, like ping, can be used to gauge which routers may be slowing things
    down. These numbers should be taken with a grain of salt, because many routers assign a
    low priority to the ICMP reply, which can cause a short delay. Note also that these times
    are cumulative, so it's really the differences between the average for each router that's
    important. Incidentally, the "*" in hop 5 indicates a packet which received no ICMP
    response at all. This is a result of normal packet-loss on the network.
    
    Example:
    
    So, here is how it works:
     *  Sends IP datagram (TTL=1) to destination host
     *  First router decrements TTL to 0, discards datagram, sends back ICMP "time exceeded"
        message (now first router in path  is identified)
     *  Sends IP datagram (TTL=2) to identify the second router
     *  Process continues until destination host reached
    
    Since hosts do not return ICMP "time exceeded" messages, traceroute needs another method
    for realizing it has reached the final destination. It sends UDP datagrams to a very high
    number port (33434 by default) that is unlikely to have an application running on it. This
    causes the destination host to generate an ICMP "port unreachable" error message, and
    traceroute then interprets this as the signal that it has reached the destination host.
    
    The last caveat we should mention is this: the path BACK from the remote machine to you is
    NOT NECESSARILY the same! This situation is called asymmetric routing, and is usually not
    an issue. In cases where it does exist though, it can make troubleshooting much more
    difficult, because some problem may exist on the reverse path (preventing data from
    getting back to you) which traceroute cannot show you. Some traceroute implementations
    support a feature which allows to do a trick so that you CAN see this information (Hint:
    take a look at tracert's "-j" option).
    
    So, if you encounter a problem with a node on-site, run a traceroute using tracert or some
    other utility. By doing a traceroute you can determine if a node is reachable, the general
    throughput of the network; and if the node is not reachable, where the failure is
    occurring. Additionally, if someone complains they can't get offsite try tracerouting a
    node offsite like 128.8.10.14, which is one of our backup nameservers. Also, try an
    external traceroute if someone complains they can't reach outside our network. Here's anurl to use when doing an external traceroute
    
    http://nucleus.nectec.or.th/pub/info/netinfo/routing.arbiter/tools/trace.html
     
    
    Possible Problems:
    
    Strange thing 1:
    Traceroute Hangs:
    Quick 'n' Dirty: traceroute -n
    
    Normally when you do a traceroute to a domain name or IP address, traceroute will try to
    look up the
    DNS hostnames of the IP address at each hop. If there is any problem with the DNS server,
    your
    traceroute will "hang". This can throw you off track.
    
    Instead, use traceroute -n. This means "IP numbers only", and any hangs or problems that
    show up in the
    traceroute will be entirely due to routing -- which is what you're troubleshooting.
    Here's an example:
    
               _fairy.tlg.net[~]> traceroute -n gw1-sj-tlg
                  traceroute to gw1-sj-tlg.tlg.net (140.174.74.1), 30 hops max, 40 byte
    packets
                   1  140.174.77.5  2.2 ms  2.119 ms  2.257 ms
                   2  140.174.178.1  7.593 ms  4.177 ms  26.672 ms
                   3  140.174.125.5  6.958 ms  49.766 ms  17.813 ms
                   4  140.174.161.2  12.194 ms *  71.78 ms
    
    Here's what the same traceroute looks like with DNS lookups:
    
                  _fairy.tlg.net[~]> traceroute gw1-sj-tlg
                  traceroute to gw1-sj-tlg.tlg.net (140.174.161.2), 30 hops max, 40 byte
    packets
                   1  gw1-ms-tlg (140.174.77.5)  2.354 ms  2.191 ms  4.617 ms
                   2  ln1_gw2-sf-tlg_ms (140.174.178.1)  29.144 ms  4.482 ms  4.305 ms
                   3  border-sf-tlg (140.174.125.5)  5.013 ms  4.663 ms  5.071 ms
                   4  border-sj-tlg (140.174.161.2)  13.748 ms *  12.346 ms
    
    Notice that "border-sj-tlg" and "gw1-sj-tlg" are the same IP address. This is set up in
    the DNS for that IP address.
    
    Strange thing 2:
    Note that lines 2 & 3 are the same.  This is due to a buggy kernel
    on the 2nd hop system that forwards packets with
    a zero ttl (a bug in the distributed version of 4.3BSD).
    
                 1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
                 2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
                 3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
                 4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39
    
    Strange thing 3:
    
    !H, means that the router at that hop doesn't know anything about the target address.
    
    !N, !P, means you got a  host, network or protocol unreachable, respectively.
    
    !S or !F means the source route failed or fragmentation needed - neither of these
         should ever occur and the associated gateway is busted if you see
         one.
    
    One last item:
    
    Sometimes you will see a traceroute that display the following information:
    Sometimes you will see a traceroute that display the following information:
     
     1  rtr-cne-e.gsfc.nasa.gov (128.183.50.1)  2 ms  1 ms  1 ms
     2  rtr-wan1-cf.gsfc.nasa.gov (128.183.251.1)  2 ms  1 ms  1 ms
     3  rtr-internet-ef.gsfc.nasa.gov (192.43.240.36)  6 ms  4 ms  4 ms
     4  sl-mae-e-f0-0.sprintlink.net (192.41.177.241)  7 ms  25 ms  18 ms
     5  sl-bb5-dc-6-1-0.sprintlink.net (144.232.8.25)  41 ms  47 ms *
     6  sl-bb3-dc-4-0-0-155M.sprintlink.net (144.232.0.6)  29 ms *  48 ms
     7  144.232.8.113 (144.232.8.113)  51 ms  43 ms  40 ms
     8  sl-bb1-atl-4-0-0-155M.sprintlink.net (144.232.1.198)  40 ms *  61 ms
     9  sl-bb5-fw-1-0-0.sprintlink.net (144.232.8.98)  86 ms  84 ms  79 ms
    10  sl-bb1-fw-4-0-0-155M.sprintlink.net (144.232.1.150)  86 ms  85 ms *
    11 * * *
    12 * * *
    13 * * *
    14 * * *
    15 sl-comp-3-0.sprintlink.net (144.228.137.14)  91 ms  90 ms *
    16 cisco3640-1.cmpu.net (204.96.11.48)  95 ms  88 ms  90 ms
    
    So, what's happening here. For some reason, probably the machine after sl-bbl-fw, the
    machine is not getting its ICMP packet back to the client requesting the traceroute. The
    traceroute circumvents the problem by bumping the ttl value up 1 hop until it gets a
    response or until the TTL reaches 30 hops.
    


    Back to top

    IP Addressing Magic


    On Thu, 3 Jun 1999, Kevin P. Inscoe wrote:
    
    > Thought I would forward this here as I have seen this a lot 
    > lately and some good info about IP's. BTW: IP's are actually 
    > represented octally which is why zero-padding ip numbers like:
    > 
    > 192.168.200.10 is not the same as 192.168.200.010
    > 
    > 192.168.200.010 is actually intererpreted as 192.168.200.8
    
            Hey, thanks...  That's really neat... 
     Another NEAT thing is that you can do something like:
    
    armispian:~$ ping 0xac.0x10.0x00.0x02
    PING 0xac.0x10.0x00.0x02 (172.16.0.2): 56 data bytes
    64 bytes from 172.16.0.2: icmp_seq=0 ttl=64 time=1.5 ms
    64 bytes from 172.16.0.2: icmp_seq=1 ttl=64 time=0.9 ms
    64 bytes from 172.16.0.2: icmp_seq=2 ttl=64 time=0.8 ms
    64 bytes from 172.16.0.2: icmp_seq=3 ttl=64 time=1.0 ms
    
    --- 0xac.0x10.0x00.0x02 ping statistics ---
    4 packets transmitted, 4 packets received, 0% packet loss
    round-trip min/avg/max = 0.8/1.0/1.5 ms
    
    That is representing the data in hex.  Anyone know how to represent it in
    binary?
    
            Which I see that was actually included.  And, actually I could
    simplify that to:
    
    armispian:~$ ping 0xac100002
    PING 0xac100002 (172.16.0.2): 56 data bytes
    64 bytes from 172.16.0.2: icmp_seq=0 ttl=64 time=1.5 ms
    64 bytes from 172.16.0.2: icmp_seq=1 ttl=64 time=0.9 ms
    64 bytes from 172.16.0.2: icmp_seq=2 ttl=64 time=0.8 ms
    64 bytes from 172.16.0.2: icmp_seq=3 ttl=64 time=1.0 ms
    
    --- 0xac100002 ping statistics ---
    4 packets transmitted, 4 packets received, 0% packet loss
    round-trip min/avg/max = 0.8/1.0/1.5 ms
    
    
    -- 
    Jessica Rasku, Box 270, Rossland, B.C., V0G 1Y0, (250) 362-5701, 
    LinuxBox: (250) 362-9668.
    
    List manager: majordomo@ArmispianSystems.Rossland.bc.ca 
         send command help ---- To get help with majordomo
                   or lists ---- To get a list of all lists on server.
    
    WWW: http://www.geocities.com/RainForest/Andes/8749


    Back to top

    Determining what version of Sendmail you are running


    # /usr/lib/sendmail -d0.1 </dev/null
    Version 8.12.9
     Compiled with: DNSMAP LOG MAP_REGEX MATCHGECOS MILTER MIME7TO8 MIME8TO7
                    NAMED_BIND NDBM NETINET NETINET6 NETUNIX NEWDB NIS NISPLUS
                    PIPELINING SCANF USERDB XDEBUG


    Back to top

    Using Pine to read Netscape email archives


    I archive all of my Netscape and Mozilla email to compact disc. I needed a quick way to read my archives without having to restore the files back into Mozilla.

    This method I have come up with at least partially provides a solution:

    Copy the archived mail to the local directory:

    $ mkdir nsmail
    $ cp "/mnt/cdrom/mail2002_4/Mail/Archived Mail.sbd/Kevin Personal.sbd/cfgeeks" nsmail/ Inbox

    Because the file comes from a read-only file system (cdrom) we will have to make it wr itable.

    $ chmod +w nsmail/Inbox

    Update $HOME/.pinerc

    incoming-folders=NS-inbox nsmail/Inbox

    Unfortunately you have to copy the message file to local storage because the cdrom is read-only.

    If anyone knows a way to get around this please let me
    know!

    Back to top

    Blocking email with Sendmail


    If you're running Sendmail, for example, you can bounce back messages to the sender. Just go into the /etc/mail/access file, and manually enter the email address of the spammer plus the command to reject, as follows:

    spammer@nastysite.com REJECT

    This lets you use the access_db feature in Sendmail to allow a database to be maintained in /etc/mail/access of those nasty sites sending you spam.

    Back to top

    Spellcheck in vi


    After creating a document, save it and return to the command prompt. Issue the command

    spell < filename | pg

    This will output any misspelled words it catches on the screen.

    Or even better write the document out from within vi

    :w [filename]
    :sh spell < filename | pg


    This way you don't even have to leave vi!


    Back to top

    chroot jail for ftpd


    Date: Wed, 10 Apr 2002 15:09:34 -0400
    From: "Kevin P. Inscoe (KE3VIN)" 
    To: Catherine Scott 
    Subject: Re: chroot ftp
    
    I sent that too fast...
    
    here is a link that explains the principles of chrooting (even though
    they use it for Apache)
    
    http://penguin.epfl.ch/chroot.html
    
    also you may want to get this book (it's at my desk)
    
    http://www.amazon.com/exec/obidos/ASIN/1565921488/104-9499867-7043138
    
    Date: Wed, 10 Apr 2002 15:06:22 -0400
    From: "Kevin P. Inscoe (KE3VIN)" 
    To: Catherine Scott 
    Subject: chroot ftp
    
    Have a look at this one:
    
    http://www.pureftpd.org/FAQ
    
    * Directories shared by multiple users.
    
    -> I have a "public" directory. All users can download and upload files
    from/to this directory. Permissions are 777 on it. But user 'john' can
    delete files owned by user 'joe'. How to prevent this?
    
    Put the sticky bit on that directory : chmod 1777 public. That way, the
    directory remains public (read/write), but people can only delete files
    they
    own.
    
    
    
    * Restricting directory visibility.
    
    -> I want that people only see their home directory and their own files.
    I
    don't want them to look at my systems files.
    
    This feature is called "chroot". You can enable this by running
    pure-ftpd
    with the "-A" switch to do this with ALL your users (but root) .
    
    You can alternatively use "-a " to have a "trusted group". Everyone
    will be caged, EXCEPT members of that group.
    
    Don't use -a  and -A together.
    
    Another way is to selectively choose what users you want to chroot. This
    can
    be done with the /./ trick (see the README file about this) or with
    virtual
    users.
    
    
    
    * Shared directories and chroot.
    
    -> I have a directory, say /var/incoming, that I want to be shared by
    every
    user. But I want my users to be chrooted. So /var/incoming should be
    visible
    in 'joe' and 'john' accounts, but those are chrooted. So, how to have
    the
    content of /var/incoming visible in these accounts?
    
    Making a symbolic link won't work, because when you are chrooted, it
    means
    that everything outside a base directory (your user's home directory)
    won't
    be reachable, even though a symbolic link.
    
    But all modern operating systems can mount local directories to several
    locations. To have an exact duplicate of your /var/incoming directory
    available in /home/john/incoming and /home/joe/incoming, use one of
    these
    commands :
    
    * Linux   : mount --bind /var/incoming /home/john/incoming
                mount --bind /var/incoming /home/joe/incoming
    
    * Solaris : mount -t lofs /var/incoming /home/john/incoming
                mount -t lofs /var/incoming /home/joe/incoming
    
    
    http://www.science.uva.nl/pub/solaris/solaris2/Q3.9.html
    
    ftp://ftp.math.fsu.edu/pub/solaris/ftp.anon
    
    http://www.netsys.com/sunmgr/1999-06/msg00022.html
    
    
    for wuftpd:
    
    http://www.wildheart.org/wu-ftpd/


    Back to top

    Creating a plain text man page


    You can use the "col -b" command to create a plain text file
    from a man page. When you use simple output redirection
    (i.e. "man man > man.txt") your text file contains extraneous
    underscores, duplicate characters, and page breaks
    because man formats the text for display on a terminal.
    
    You can remove the unwanted characters and page breaks
    by piping man's output to a "col -b" command like this:
    
    man man | col -b > man.txt
    
    The man.txt created by "col -b" contains plain text without
    extraneous underscores, duplicate characters, and page breaks.
    


    Back to top

    Embedding AWK/SED programs in shell scripts


    Embedding programs for awk or sed directly into their command-lines make 
    scripts hard to read. It's much easier to separate out the definition of 
    the program from the usage. For example,
    
            :
            :
            AWKPROG='
            /^STUFF/        { total += $2}
            END             { printf "The total was %d\n", total}
            '
    
            awk "${AWKPROG}" < data_file > results_file
    
    Note the single quotes surrounding the definition and the double quotes 
    around the usage of AWKPROG. 
    
    Advantages of this technique:
    (i)     Clarity -- the program can be read and understood in isolation from 
            the script that calls it.
    
    (ii)    Reuse  -- the same program can, of course, be re-used at
            several points throughout the enclosing script.
    
    (iii)   Simple debugging/development--just repeat the definition of
    (say)   AWKPROG and use the second as the test version.
    


    Back to top

    bash shell prompting magic


    Notes:

    http://www-106.ibm.com/developerworks/linux/library/l-tip-prompt/
    Enhancing the system prompt
    
    Daniel Robbins (drobbins@gentoo.org)
    President-CEO, Gentoo Technologies, Inc.
    September 2000
    Why stick with the standard boring shell prompt when you can easily make it colorful and more informative? In this tip, Daniel Robbins will show you how to get your shell prompt just the way you like it, as well as how to dynamically update your X terminal's title bar.
    
    As Linux/UNIX people, we spend a lot of time working in the shell, and in many cases, this is what we have staring back at us:
    
    
    bash-2.04$
    
    If you happen to be root, you're entitled to the "prestige" version of this beautiful prompt:
    
    
    bash-2.04#
    
    These prompts are not exactly pretty. It's no wonder that several Linux distributions have upgraded their default prompts that add color and additional information to boot. However, even if you happen to have a modern distribution that comes with a nice, colorful prompt, it may not be perfect. Maybe you'd like to add or change some colors, or add (or remove) information from the prompt itself. It isn't hard to design your own colorized, tricked-out prompt from scratch.
    
    Prompt basics
    Under bash, you can set your prompt by changing the value of the PS1 environment variable, as follows:
    
    
    $ export PS1="> "
    >
    
    Changes take effect immediately, and can be made permanent by placing the "export" definition in your ~/.bashrc file. PS1 can contain any amount of plain text that you'd like:
    
    
    $ export PS1="This is my super prompt > "
    This is my super prompt >
    
    While this is, um, interesting, it's not exactly useful to have a prompt that contains lots of static text. Most custom prompts contain information like the current username, working directory, or hostname. These tidbits of information can help you to navigate in your shell universe. For example, the following prompt will display your username and hostname:
    
    
    $ export PS1="\u@\H > "
    drobbins@freebox >
    
    This prompt is especially handy for people who log in to various machines under various, differently-named accounts, since it acts as a reminder of what machine you're actually on and what privileges you currently have.
    
    In the above example, we told bash to insert the username and hostname into the prompt by using special backslash-escaped character sequences that bash replaces with specific values when they appear in the PS1 variable. We used the sequences "\u" (for username) and "\H" (for the first part of the hostname). Here's a complete list of all special sequences that bash recognizes (you can find this list in the bash man page, in the "PROMPTING" section):
    Sequence Description
    \a The ASCII bell character (you can also type \007)
    \d Date in "Wed Sep 06" format
    \e ASCII escape character (you can also type \033)
    \h First part of hostname (such as "mybox")
    \H Full hostname (such as "mybox.mydomain.com")
    \j The number of processes you've suspended in this shell by hitting ^Z
    \l The name of the shell's terminal device (such as "ttyp4")
    \n Newline
    \r Carriage return
    \s The name of the shell executable (such as "bash")
    \t Time in 24-hour format (such as "23:01:01")
    \T Time in 12-hour format (such as "11:01:01")
    \@ Time in 12-hour format with am/pm
    \u Your username
    \v Version of bash (such as 2.04)
    \V Bash version, including patchlevel
    \w Current working directory (such as "/home/drobbins")
    \W The "basename" of the current working directory (such as "drobbins")
    \! Current command's position in the history buffer
    \# Command number (this will count up at each prompt, as long as you type something)
    \$ If you are not root, inserts a "$"; if you are root, you get a "#"
    \xxx Inserts an ASCII character based on three-digit number xxx (replace unused digits with zeros, such as "\007")
    \\ A backslash
    \[ This sequence should appear before a sequence of characters that don't move the cursor (like color escape sequences). This allows bash to calculate word wrapping correctly.
    \] This sequence should appear after a sequence of non-printing characters.
    
    So, there you have all of bash's special backslashed escape sequences. Play around with them for a bit to get a feel for how they work. After you've done a little testing, it's time to add some color.
    
    Colorization
    Adding color is quite easy; the first step is to design a prompt without color. Then, all we need to do is add special escape sequences that'll be recognized by the terminal (rather than bash) and cause it to display certain parts of the text in color. Standard Linux terminals and X terminals allow you to set the foreground (text) color and the background color, and also enable "bold" characters if so desired. We get eight colors to choose from.
    
    Colors are selected by adding special sequences to PS1 -- basically sandwiching numeric values between a "\e[" (escape open-bracket) and an "m". If we specify more than one numeric code, we separate each code with a semicolon. Here's an example color code:
    
    
    "\e[0m"
    
    When we specify a zero as a numeric code, it tells the terminal to reset foreground, background, and boldness settings to their default values. You'll want to use this code at the end of your prompt, so that the text that you type in is not colorized. Now, let's take a look at the color codes. Check out this screenshot:
    
    Color chart
    Color chart
    
    To use this chart, find the color you'd like to use, and find the corresponding foreground (30-37) and background (40-47) numbers. For example, if you like green on a normal black background, the numbers are 32 and 40. Then, take your prompt definition and add the appropriate color codes. This:
    
    
    export PS1="\w> "
    
    becomes:
    
    
    export PS1="\e[32;40m\w> "
    
    So far, so good, but it's not perfect yet. After bash prints the working directory, we need to set the color back to normal with a "\e[0m" sequence:
    
    
    export PS1="\e[32;40m\w> \e[0m"
    
    This definition will give you a nice, green prompt, but we still need to add a few finishing touches. We don't need to include the background color setting of 40, since that sets the background to black which is the default color anyway. Also, the green color is quite dim; we can fix this by adding a "1" color code, which enables brighter, bold text. In addition to this change, we need to surround all non-printing characters with special bash escape sequences, "\[" and "\]". These sequences will tell bash that the enclosed characters don't take up any space on the line, which will allow word-wrapping to continue to work properly. Without them, you'll end up with a nice-looking prompt that will mess up the screen if you happen to type in a command that approaches the extreme right of the terminal. Here's our final prompt:
    
    
    export PS1="\[\e[32;1m\]\w> \[\e[0m\]"
    
    Don't be afraid to use several colors in the same prompt, like so:
    
    
    export PS1="\[\e[36;1m\]\u@\[\e[32;1m\]\H> \[\e[0m\]"
    
    Xterm fun
    I've shown you how to add information and color to your prompt, but you can do even more. It's possible to add special codes to your prompt that will cause the title bar of your X terminal (such as rxvt or aterm) to be dynamically updated. All you need to do is add the following sequence to your PS1 prompt:
    
    
    "\e]2;titlebar\a"
    
    Simply replace the substring "titlebar" with the text that you'd like to have appear in your xterm's title bar, and you're all set! You don't need to use static text; you can also insert bash escape sequences into your titlebar. Check out this example, which places the username, hostname, and current working directory in the titlebar, as well as defining a short, bright green prompt:
    
    
    export PS1="\[\e]2;\u@\H \w\a\e[32;1m\]>\[\e[0m\] "
    
    This is the particular prompt that I'm using in the colortable screenshot, above. I love this prompt, because it puts all the information in the title bar rather than in the terminal where it limits how much can fit on a line. By the way, make sure you surround your titlebar sequence with "\[" and "\]", since as far as the terminal is concerned, this sequence is non-printing. The problem with putting lots of information in the title bar is that you will not be able to see info if you are using a non-graphical terminal, such as the system console. To fix this, you may want to add something like this to your .bashrc:
    
    
    if [ "$TERM" = "linux" ]
    then
      #we're on the system console or maybe telnetting in
      export PS1="\[\e[32;1m\]\u@\H > \[\e[0m\]"
    else
      #we're not on the console, assume an xterm
      export PS1="\[\e]2;\u@\H \w\a\e[32;1m\]>\[\e[0m\] " 
    fi
    
    This bash conditional statement will dynamically set your prompt based on your current terminal settings. For consistency, you'll want to configure your ~/.bash_profile so that it sources your ~/.bashrc on startup. Make sure the following line is in your ~/.bash_profile:
    
    
    source ~/.bashrc
    
    This way, you'll get the same prompt setting whether you start a login or non-login shell.
    
    Well, there you have it. Now, have some fun and whip up some nifty colorized prompts!
    
    Resources
    
        * rxvt is a great little xterm that happens to have a good amount of documentation related to escape sequences tucked in the "doc" directory included in the source tarball.
    
        * aterm is another terminal program, based on rxvt. It supports several nice visual features, like transparency and tinting.
    
        * bashish is a theme engine for all different kinds of terminals. Check out some great screenshots of bashish in action!
    
    About the author
    Residing in Albuquerque, New Mexico, Daniel Robbins is the President/CEO of Gentoo Technologies, Inc., the creator of Gentoo Linux, an advanced Linux for the PC, and the Portage system, a next-generation ports system for Linux. He has also served as a contributing author for the Macmillan books Caldera OpenLinux Unleashed, SuSE Linux Unleashed, and Samba Unleashed. Daniel has been involved with computers in some fashion since the second grade, when he was first exposed to the Logo programming language as well as a potentially dangerous dose of Pac Man. This probably explains why he has since served as a Lead Graphic Artist at SONY Electronic Publishing/Psygnosis. Daniel enjoys spending time with his wife, Mary, and his new baby daughter, Hadassah. You can contact Daniel at drobbins@gentoo.org.


    Back to top

    Obtaining yesterday's and tomorrow's dates


    This is a very short script for obtaining the date one day back
    and forward from today. The trick is in setting the internal
    time zone variable TZ 24 hours backward and forward before
    obtaining the date.
    
    #!/bin/sh
    Yesterday=`TZ=PST+24 date +%D`
    echo "Yesterday is:" $Yesterday
    
    Tomorrow=`TZ=PST-24 date +%D`
    echo "Tomorrow is:" $Tomorrow
    
    Today=^Date +%D
    echo "Today is:" $Today
    


    Back to top

    Using eval


    When you capture the result of a command by writing:
    
            result=`somecommand`
    
    the result is normally a single value.  If, however, somecommand needs
    to return multiple values you need to use some other program (e.g. awk
    or sed) to split the combined result into its parts. 
    
    Alternatively, you could pass an argument to somecommand to say which 
    result should be returned.
    
    A much neater solution is to use the power of the shell's eval command. 
    For example, say you wanted to return day, month and year from the date 
    command. You'd have to write either:
                    
    day=`date +%d`
    month=`date +%m`
    year=`date +%Y`
    
    or:
    
    result=`date '+%d %m %Y'`
    
    and then break up "result".  Instead you can write:
    
    eval `date '+day=%d month=%m year=%Y'`
    
    The command within the backticks returns:
    
    day=23 month=02 year=2000
    
    and the "eval" command then treats this as normal shell input and 
    performs the variable assignments.


    Back to top

    Stacking shell commands


    From: Kevin Korb [mailto:kkorb@maxcess.net]
    Sent: Tuesday, April 24, 2001 18:21
    To: Brett Mueller; George Mendonca
    Cc: kinscoe@maxcess.net; gyoung@maxcess.net; mach@maxcess.net
    Subject: Shell script trick
    
    
    I don't know if you guys know this or not but you can do some cool things
    with '&&' and '||' in shell scripts (csh or sh).  && is a logical and, || is
    a logical or.
    
    command1 || command2  means run command2 if command1 fails
    command1 && command2  means run command2 if command1 succeeds
    command1 && command2 || command3  means run 3 if 1 fails or 2 if 1 succeeds
    
    I sometimes use something like this:
    ping $host && ping $host && ping $host && echo $host is up || echo host is
    $down
    This will give host 3 times to answer.
    
    Just thougt you might could use something like this in your Oracle backup
    scripts.
    
    
    Here is a good way to see if your internet connection works:
    ping yahoo && ping google && ping ibm && ping microsoft || echo Internet
    DOWN
    If any site responds the Internet link must be OK!
    


    Back to top

    Convert Backspace key to erase


    When you connect to a machine and the backspace key turns into extra unwanted characters similar to:

    $ lss^[[2~^[[2~^[[2~?

    $ stty erase


    Then hit the backspace key.

    To make this permanent edit your .profile or .login file and put in the following line:

    stty erase '^H'


    Back to top

    ksh tricks


    One alternative/method to doing the command recall is by adding 
    "set -o vi" to your .kshrc file or executing it at the command line. 
    This allows to use the vi  sequence with keys h, j, k, and l and 
    the -,+, =, and \ in useful ways.
    
    "-" to recall previous command. Keep using "-" to keep going through 
    the previous commands.
    
    "+" to go forward through the command list
    
    "\" to do file name completion
    
    "=" to show all possible file name matches. ex.
         $> ls
           abc123
           defghijkl
           defghijkm
           xyz
    
         $> cat d{ \}          will yield       $> cat defghijk
    
    You can then add the "l" or "m" to the file name and it will cat the 
    file. You can use the vi editing commands on the command line like "i" 
    for insert, "a" for append, "$" to go to end of line along with the 
    cursor commands to move left and right. Get out the vi command list and 
    experiment to test the possibilities.
    
    Korn shell behaviors
    
    To change the Korn shell's behaviors, you can turn options on or off. 
    Turn an option on with the syntax:
    
    set -o [option name]
    
    Turn an option off with the syntax:
    
    set +o [option name]
    
    You might expect a minus (-) to mean off, but the Korn shell reads it as on, and it reads the
    plus (+) as off.


    Back to top

    How to get rid of weird binary characters in the man pages for Redhat 8


    In bash/sh:

    set export LANG=en_US

    In ksh:

    export LANG=en_US

    In csh:

    setenv LANG=en_US



    Back to top

    Two important commands to set up modems and terminal characters


    Notes:

    http://www.stokely.com/unix.serial.port.resources/index.html

    If you're going to set up a character terminal or modem with Solaris, there are two important
    commands you need to learn.
    
    1. To add a port monitor, you'll need to use the 
    casadm command--that is, if it isn't configured on 
    your machine.
     
    2. To Define a service to be specified with the new 
    port monitor, you'll use the pmadm command


    Back to top

    Making You Own Entries To The System Log File in Solaris


    Have you ever wanted your script to report trouble
    to the system log file? Use the logger command:
    
    logger  -p user.alert -t Error "Script Failed"
    
    This will make a time-stamped entry to the system
    log file defined in /etc/syslog.conf.
    
    This tip was contributed by Tod Borkman.


    Back to top

    Obtaining system configuration


    $ prtdiag -v

    System Configuration:  Sun Microsystems  sun4u 8-slot Sun Enterprise
    E4500/E5500
    System clock frequency: 100 MHz
    Memory size: 6144Mb
    
    ========================= CPUs =========================
    
                        Run   Ecache   CPU    CPU
    Brd  CPU   Module   MHz     MB    Impl.   Mask
    ---  ---  -------  -----  ------  ------  ----
     0     0     0      400     8.0   US-II    10.0
     0     1     1      400     8.0   US-II    10.0
     2     4     0      400     8.0   US-II    10.0
     2     5     1      400     8.0   US-II    10.0
     4     8     0      400     8.0   US-II    10.0
     4     9     1      400     8.0   US-II    10.0
    
    
    ========================= Memory =========================
    
                                                  Intrlv.  Intrlv.
    Brd   Bank   MB    Status   Condition  Speed   Factor   With
    ---  -----  ----  -------  ----------  -----  -------  -------
     0     0    2048   Active      OK       60ns    2-way     A
     2     0    2048   Active      OK       60ns    2-way     A
     4     0    2048   Active      OK       60ns    1-way  
    
    ========================= IO Cards =========================
    
         Bus   Freq
    Brd  Type  MHz   Slot  Name                              Model
    ---  ----  ----  ----  --------------------------------
    ----------------------
     1   SBus   25     2   QLGC,isp/sd (block)               QLGC,ISP1000U
    
     1   SBus   25     3   SUNW,hme
    
     1   SBus   25     3   SUNW,fas/sd (block)
    
     1   SBus   25    13   SUNW,socal/sf (scsi-3)            501-3060
    
     3   PCI    33     0   SUNW,qfe-pci108e,1001             SUNW,pci-qfe
    
     3   PCI    33     1   SUNW,hme-pci108e,1001             SUNW,cheerio
    
     3   PCI    33     1   SUNW,qfe-pci108e,1001             SUNW,pci-qfe
    
     3   PCI    33     2   SUNW,qfe-pci108e,1001             SUNW,pci-qfe
    
     3   PCI    33     3   SUNW,qfe-pci108e,1001             SUNW,pci-qfe
    
     5   SBus   25     2   QLGC,isp/sd (block)               QLGC,ISP1000U
    
     5   SBus   25     3   SUNW,hme
    
     5   SBus   25     3   SUNW,fas/sd (block)
    
     5   SBus   25    13   SUNW,socal/sf (scsi-3)            501-3060
    
     7   PCI    33     1   SUNW,hme-pci108e,1001             SUNW,cheerio
    
     7   PCI    33     2   fibre-channel-pci1242,4643
    
     7   PCI    33     3   SUNW,isptwo/sd (block)            QLGC,ISP1040B
    
    
    No failures found in System
    ===========================
    No System Faults found
    ======================
    
    
    ========================= Environmental Status =========================
    Keyswitch position is in Normal Mode
    System Power Status: Redundant
    System LED Status:    GREEN     YELLOW     GREEN
    Normal                 ON        OFF       BLINKING
    
    
    Fans:
    -----
    Unit   Status
    ----   ------
    Rack    OK
    Key     OK
    AC      OK
    
    System Temperatures (Celsius):
    ------------------------------
    Brd   State   Current  Min  Max  Trend
    ---  -------  -------  ---  ---  -----
     0      OK       41     40   43  stable
     1      OK       39     38   41  stable
     2      OK       40     39   42  stable
     3      OK       39     39   42  stable
     4      OK       37     35   41  stable
     5      OK       39     39   42  stable
     7      OK       38     38   41  stable
    CLK     OK       29     28   30  stable
    
    Power Supplies:
    ---------------
    Supply                        Status
    ---------                     ------
    0                                OK
    1                                OK
    2                                OK
    3                                OK
    PPS                              OK
        System 3.3v                  OK
        System 5.0v                  OK
        Peripheral 5.0v              OK
        Peripheral 12v               OK
        Auxilary 5.0v                OK
        Peripheral 5.0v precharge    OK
        Peripheral 12v precharge     OK
        System 3.3v precharge        OK
        System 5.0v precharge        OK
    AC Power                         OK
    
    
    ========================= HW Revisions =========================
    
    ASIC Revisions:
    ---------------
    Brd  FHC  AC  SBus0  SBus1  PCI0  PCI1  FEPS  Board Type      Attributes
    ---  ---  --  -----  -----  ----  ----  ----  ----------      ----------
     0    1    5                                  CPU             100MHz Capable
     1    1    5    1      1                 22   Dual-SBus-SOC+  100MHz Capable
     2    1    5                                  CPU             100MHz Capable
     3    1    5                 4           c1   Dual-PCI        100MHz Capable
     4    1    5                                  CPU             100MHz Capable
     5    1    5    1      1                 22   Dual-SBus-SOC+  100MHz Capable
     7    1    5                 4     4     c1   Dual-PCI        100MHz Capable
    
    System Board PROM revisions:
    ----------------------------
    Board  0:   OBP   3.2.26 2000/05/09 19:07   POST  3.9.26 2000/05/09 19:13
    Board  1:   FCODE 1.8.26 2000/05/09 19:05   iPOST 3.4.26 2000/05/09 19:11
    Board  2:   OBP   3.2.26 2000/05/09 19:07   POST  3.9.26 2000/05/09 19:13
    Board  3:   FCODE 1.8.26 2000/05/09 19:05   iPOST 3.0.26 2000/05/09 19:12
    Board  4:   OBP   3.2.26 2000/05/09 19:07   POST  3.9.26 2000/05/09 19:13
    Board  5:   FCODE 1.8.26 2000/05/09 19:05   iPOST 3.4.26 2000/05/09 19:11
    Board  7:   FCODE 1.8.26 2000/05/09 19:05   iPOST 3.0.26 2000/05/09 19:12
    
    Analysis of most recent Fatal Hardware Watchdog:
    ======================================================
    Log Date: Sun Nov 26 02:35:36 2000
    
    
    Analysis for Board 0
    --------------------
    AC: Timeout on a UPA Master Port
            The error could be caused by:
                    Undetermined Address Controller in system
                    Undetermined Board in system
    


    Back to top

    Changing a Solaris hosts name or IP address


    Changing just the hostname:

    Edit

    /etc/hosts
    /etc/hostname.hme0
    (or interface)
    /etc/nodename
    /etc/net/ticlts/hosts
    /etc/net/ticots/hosts
    /etc/net/ticotsord/hosts

    Change IP:

    /etc/defaultrouter
    /etc/hosts
    /etc/inet/netmasks


    Back to top

    Where things are logged in Solaris


    /var/adm/messages The messages file holds information that prints to the console. They might include root logins and su attempts.

    /var/adm/lastlog This file holds the most recent login time for each user in the system.

    /var/adm/utmp and /var/adm/utmpx The utmp database file contains user access and accounting information for commands such as who, write, and login. The utmpx file is where information such as the terminal line and login time are stored for access by the who command.

    /var/adm/wtmp and /var/adm/wtmpx The wtmp file contains the history of user access and accounting information for the utmp database. The wtmp file keeps track of logins and logouts since reboot. The last command reads that file and processes the information.

    /var/adm/acct This is the system accounting file. If enabled, the accounting file records a record for every process listing the following information: the name of the user who ran the command, the name of the command, the CPU time used, the completion timestamp of the process, and a flag indicating completion status.

    Also be sure to consult /etc/syslog.conf as other logging files and host may be defined.


    Back to top

    Executing cronjobs on a certain day of month


    Example to run on last Sunday of each month:
    
    If you want a job to run on the last
    sunday of every month, you can use
    the following syntax from within cron:
    

    18 * * * 0 [`date "+%d"` -gt 24] && /path/to/script
    i.e. on sundays at 18:00 check if
    the day of the month is greater than
    24 - if so run the job (if 23 is
    specified the job will run on the last
    2 sundays of the month)
    
    NOTE: There back-ticks around the date
    command, not single quotes.
    


    Back to top

    Adding a job to cron from a script


    $ echo "0 3 * * 1-5 /home/kinscoe/updates.sh" >> /var/spool/cron/crontabs/root
    $ /etc/init.d/cron stop
    $ sleep 5
    $ /etc/init.d/cron start


    Back to top

    Traverse a directory tree and change all filenames to lowercase


    for i in `find thedir/ -type f -print`; do
            mv $i `echo $i | perl -e '$thing = ;print lc($thing);'`
    done


    Back to top

    Creating temporary files securely


    http://lwn.net/2000/1221/a/sec-tmp.php3

    
     Date:         Fri, 15 Dec 2000 21:12:58 -0800
    From: Kris Kennaway 
    Subject:      Re: /tmp topic
    To: BUGTRAQ@SECURITYFOCUS.COM
    
    --SUOF0GtieIMvvwua
    Content-Type: text/plain; charset=us-ascii
    Content-Disposition: inline
    
    On Thu, Dec 14, 2000 at 10:10:07PM -0800, Octavio / Super wrote:
    
    > Is there a standard or a guide or a "HOWTO"  on using tmp
    > directories safely? About using mkstemp(), assigning correct
    > permissions, erasing the file at program termination, etc.
    
    Use mkstemp() for making temporary files. If you can't use mkstemp()
    then make yourself a directory using mkdtemp(), which is protected
    from the outside world and you can be as insecure as you like within
    it. If you really have to use the insecure mktemp() then use lots of
    X's - I suggest 10 (if your libc allows it) so that the filename can't
    easily be guessed (using only 6 X's means that 5 are taken up by the
    PID, leaving only one random character and allowing an attacker to
    mount an easy race condition) [1]
    
    Never "roll your own" temporary file creation routine. Chances are you
    don't know what you're doing and will get it wrong. Use the interfaces
    helpfully provided to you by your libc vendor (described above). If
    they don't provide these interfaces then yell at your vendor until
    they do, or port the functions from a freely available libc such as
    the FreeBSD/NetBSD/OpenBSD libc. Beware of deprecated, insecure
    interfaces like mktemp() or tmpnam() which should be documented as
    being insecure by your vendor.
    
    Don't ever reuse a temporary filename (i.e. remove and recreate it) -
    no matter how you obtained that "secure" temporary filename in the
    first place (e.g. mkstemp()). An attacker can observe the original
    filename and hijack it before you recreate it the second time.
    
    If you ever want to make a file in /tmp or a world-writable directory
    (or group-writable, if you don't trust the group) and don't want to
    use mk*temp() (e.g. you intend for the file to be predictably named),
    then ALWAYS use the O_EXCL flag to open() and CHECK THE RETURN
    VALUE. If you fail the open() call, then recover gracefully
    (e.g. exit).
    
    Always use appropriate permissions - e.g. only allow world/group
    access if you need the world or a group to access the file, otherwise
    keep it mode 600.
    
    Clean up after yourself, either by using an exit handler, or making
    use of UNIX filesystem semantics and unlink()ing the file immediately
    after creation so the directory entry goes away but the file itself
    remains accessible until the last file descriptor pointing to it is
    closed. You can then continue to access it within your program by
    passing around the file descriptor.
    
    Kris
    
    [1] FreeBSD has recently changed the mk*temp() family to get rid of
    the PID component of the filename and replace the entire thing with
    base-62 encoded randomness. This drastically raises the number of
    possible temporary files for the "default" usage of 6 X's, meaning
    that even mktemp() with 6 X's is reasonably (probabilistically) secure
    against guessing, except under very frequent usage.
    
    http://www.FreeBSD.org/cgi/cvsweb.cgi/src/lib/libc/stdio/mktemp.c.diff?r1=1.19&r2=1.20
    
    --SUOF0GtieIMvvwua
    Content-Type: application/pgp-signature
    Content-Disposition: inline
    
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.0.4 (GNU/Linux)
    Comment: For info see http://www.gnupg.org
    
    iD8DBQE6OvnUWry0BWjoQKURAt2wAKC+SY7UIwt8uR3HPuhM6lIYvlR0ZQCgjr+g
    a1yH9FXtYDtjGWHjoR1U+Dc=
    =Ucxe
    -----END PGP SIGNATURE-----
    
    --SUOF0GtieIMvvwua--
    


    Back to top

    VMS style searching of files


    Date: Mon, 10 Jul 2000 13:52:29 -0400
    From: SGauthier@domainpharma.com
    To: sun-managers@sunmanagers.ececs.uc.edu
    Subject: SUMMARY: searching for a string
    
    Why did I forget to check GNU's version of grep....
    
    Here's the basic answer taken from Christophe Colle message:
    
    >
    >use gnu grep ... it has the -A and -B switches you can use to
    >implement that behavior... gnu grep can be found as a package from
    >http://smc.vnet.net or you can compile it from any decent gnu mirror
    >
    
    Also added by others (many others) was the -C option and the -# shortcut.
    
    In case anyone wanted the Perl code, Karl Vogel shared a nifty script:
    #!/usr/local/bin/perl
    # Usage: cgrep [-lines] pattern [files]
    
    $context = 3;
    
    # They might want more or less context.
    
    if ($ARGV[0] =~ /^-(\d+)$/) {
        $context = $1;
        shift;
    }
    
    # Get the pattern and protect the delimiter.
    
    $pat = shift;
    $pat =~ s#/#\\/#g;
    # First line of input will be middle of array.
    # In the eval below, it will be $ary[$context].
    
    $_ = <>;
    push(@ary,$_);
    
    # Add blank lines before, more input after first line.
    
    for (1 .. $context) {
        unshift(@ary,'');
        $_ = <>;
        push(@ary,$_) if $_;
    }
    
    # Now use @ary as a silo, shifting and pushing.
    
    eval < if \$_;
         shift(\@ary);
         push(\@ary,\$_);
        }
    LOOP_END
    
    Thanks to the following:
    John Leadeham
    Peter Gutmann
    Bernhard Sadlowski
    Jed Dobson
    Thomas Wardman
    Gabriel Rosenkoetter
    Paul J. Bell
    Sun System Admin ???
    Bandried ???
    Sid Shapiro
    John T. Douglass
    Kevin P. Inscoe
    Christophe Colle
    Karl Vogel
    John Saalwaechter
    Julie L Baumler
    
    ----- Forwarded by Steve Gauthier/PHA/Domain on 07/10/00 01:20 PM -----
                                                                                                     
                        SGauthier@domainpharma.com                                                   
                        Sent by:                                 To:    
                        
                        owner-sun-managers@sunmanagers.ec        cc:                                 
                        ecs.uc.edu                               Subject:     searching for a string 
                                                                                                     
                                                                                                     
                        07/10/00 12:20 PM                                                            
                                                                                                     
                                                                                                     
    
    
    
    
    Okay, anyone out there familiar with OpenVMS?   If so, you'll remember the
    SEARCH command which would allow you to search for occurrences of strings
    (just like grep) but also allow you do list X number of lines before and
    after the found occurrences.
    
    Anyone know of a command/program or switch to an existing command that will
    do that same thing?
    I'm not a wiz at C but I can whip the program up in a day or so... just
    wanted to check to make sure I wasn't re-inventing the wheel.    Seems like
    a useful feature to me so I figured it probably already exists in some or
    all flavors of UNIX.
    
    If you can't see why it would be a useful feature, take this example which
    I end up running into all the time:
    
    You have a software package installed but you can't remember the stupid
    name of the package (as if they were named using meaningful names most of
    the time).   Typically what I do is type 'pkginfo -l > /tmp/pkgs.txt' then
    'view /tmp/pkgs.txt' and do a search in vi for the string.     But since
    the 'pkginfo -l' output is a fairly regular structure, then if I could
    search for a string that I think would appear in the output of the 'pkginfo
    -l' command and then print out enough lines before the found string to see
    the package name, it would be less steps to take to get the desired
    results.
    
                                \\|//
                                (0~0)
    ------------------------oooO-(_)-Oooo-----------------------------
    Steve Gauthier                           Domain Pharma Corporation
    UNIX/VMS/Macintosh Systems Administrator           10 Maguire Road
    PHONE: (781) 778 - 3953                        Lexington, MA 02421
    FAX: (781) 778 - 3800           E-mail: sgauthier@domainpharma.com
    ______________________________Oooo._______________________________
                           .oooO  (___)
    


    Back to top

    Recursive grep


    This is my biggest unix annoyance of all time. But no longer!

    Notes:

    http://magnonel.guild.net/~schwern/talks/Refactoring/slides/slide043.html
    http://www.joegrossberg.com/archives/000386.html - Linux Recursive Grep scripts

    The old ways of doing it:

    $ grep -r
    $ find . -type f -print | xargs grep -i [PATTERN]
    $ grep foo * */* */*/* */*/*/* ...
    $ find /path/dir -type f -name '*.sql' -exec grep 'searched expression'{} /dev/null \;

    But now I use rgrep! rgrep comes with Jed.
    Why use rgrep instead of more traditional Unix tools?
    ------------------------------------------------------
    
    Unlike grep and egrep, rgrep has the ability to recursively descend
    directories. The traditional way of performing this kind of search on Unix
    systems utilizes the `find' command in conjunction with `grep'.  However,
    this results in very poor performance.  Consider the tradional approach
    where one wants to search the /usr/include directory for the string `FD_SET':
    For this, one would use:
    
    % find /usr/include -exec grep -l FD_SET \{\} \; -print
    
    Ignoring the fact that the above expression looks complex, it failed to find
    any occurence of FD_SET under the /usr/include directory of my Ultrix
    system.  
    
    Now, if rgrep is used, one types:
    
    % rgrep -lFr FD_SET /usr/include
    
    which yielded: /usr/include/sys/types.h
    
    The reason that `find' failed is that /usr/include/sys is a symbolic link to
    /sys/h.  `rgrep' was able to succeed because of the `-F' flag which telles
    it to follow links.  I looked in the man page for a similar option for
    `find' but nothing turned up.

    A perl script to perform a recursive grep:

    From: Bill Campbell 
    Subject: Re: how to recursively search for text string in files?
    Date: Sat, 2 Feb 2002 21:47:49 GMT
    References: <3c5abd57@news1.warwick.net> <3C5BD461.5080709@aplawrence.com>
    
    
    --/9DWx/yDrRhgMJTb
    Content-Type: text/plain; charset=us-ascii
    
    On Sat, Feb 02, 2002 at 11:56:40AM +0000, Tony Lawrence wrote:
    ...
    >Typically, the answer is to use find, xargs, and grep.  That's horribly 
    >slow for a full filesystem search (John Dubois made a helpful suggestion 
    >on that part), and it's painfully difficult to properly construct a 
    >pipeline that will avoid searching binaries if you don't want to, won't 
    >get stuck on named pipes or blow up on funky filenames (beginning with 
    >-, or sometimes spaces, punctuation etc).  There are ways around all 
    >these things, but I don't think I've ever seen anyone even attempt it. 
    >I'll bet a virtual round of beers that no solution posted here even 
    >comes close.
    
    I have a perlscript I call ``textfiles'' that I use for many
    things like this:
    	textfiles dirname [dirname... ] | xargs ...
    
    Essentially it runs ``gfind @ARGV -type f'', then uses perl's -T
    option on each file to determine whether it's a text file.
    
    My textfiles script also has options to add options to the gnu
    find command like -xdev, -mindepth, and -maxdepth.
    
    Hell, it's short so I'm attaching it for anybody who wants to use
    it.  It does assume that the gnu version of find is in your PATH
    named gfind (I make a symlink to /usr/bin/find on Linux systems
    so that it works there as well).
    
    Bill
    --
    INTERNET:   bill@Celestial.COM  Bill Campbell; Celestial Software LLC
    UUCP:               camco!bill  PO Box 820; 6641 E. Mercer Way
    FAX:            (206) 232-9186  Mercer Island, WA 98040-0820; (206) 236-1676
    URL: http://www.celestial.com/
    
    ``I don't care how little your country is, you got a right to run it like
    you want to.  When the big nations quit meddling, then the world will have
    peace.''
        Will Rogers
    
    --/9DWx/yDrRhgMJTb
    Content-Type: text/plain; charset=us-ascii
    Content-Description: /usr/local/bin/textfiles
    Content-Disposition: attachment; filename=textfiles
    
    #!/usr/local/bin/perl
    eval ' exec /usr/local/bin/perl -S $0 "$@" '
    	if $running_under_some_shell;
    
    # $Header: /u/usr/cvs/lbin/textfiles,v 1.7 2000/06/22 18:29:08 bill Exp $
    # $Date: 2000/06/22 18:29:08 $
    # @(#) $Id: textfiles,v 1.7 2000/06/22 18:29:08 bill Exp $
    # 
    #	find text files
    
    ( $progname = $0 ) =~ s!.*/!!; # save this very early
    
    $USAGE = "
    # Find text files
    #
    #   Usage: $progname [-v] [file [file...]]
    #
    # Options   Argument    Description
    #   -f                  Follow symlinks
    #   -M      maxdepth    maxdepth argument to gfind
    #   -m      mindepth    mindepth argument to gfind
    #   -x                  Don't cross device boundaries
    #   -v                  Verbose
    #
    ";
    
    sub usage {
    	die join("\n",@_) .
    	"\n$USAGE\n";
    }
    
    do "getopts.pl";
    
    &usage("Invalid Option") unless do Getopts("fM:m:xvV");
    
    $verbose = '-v' if $opt_v;
    $suffix = $$ unless $opt_v;
    
    $\ = "\n";	# use newlines as separators.
    
    # use current directory if there aren't any arguments
    push(@ARGV, '.') unless defined($ARGV[0]);
    
    $args = join(" ", @ARGV);
    $xdev = '-xdev' if $opt_x;
    $opt_f = '-follow' if $opt_f;
    $opt_m = "-mindepth $opt_m" if $opt_m;
    $opt_M = "-maxdepth $opt_M" if $opt_M;
    $cmd = "gfind @ARGV -type f $xdev $opt_f $opt_m $opt_M |";
    print STDERR "cmd = >$cmd<" if $verbose;
    
    open(INPUT, $cmd);
    while() {
    	chop($name = $_);
    	print STDERR "testing $name..." if $verbose;
    	print $name if -T $name;
    }
    
    --/9DWx/yDrRhgMJTb--
    


    Back to top

    Clone a filesystem or directory from one host to another


    # find /dir -follow -print -depth | cpio -oavucB | ssh -c blowfish -C host.com "cpio -icBdumv"

    Back to top

    Locating the largest files in descending order



    $ ls -laR | awk '{print $5 " " $9}' | sort -nr | more
    127926272 kinsco1.nsf
    13437770 setupex.exe
    8253351 mwinfaxt.exe
    7464855 load.log
    7114825 PalmDesktop_40_ENG.zip
    7067027 arpos_winv20deu.exe
    6809481 dtmac261.sit
    6809481 dtmac261.sit


    Back to top

    Renaming File Types


    Date: Tue, 23 Jul 2002 12:14:18 -0400
    From: "Kevin P. Inscoe (KE3VIN)" 
    Subject: renaming file types
    
    Excerpted from Unix Power Tools, O'Reilly
    [ Reproduced without permission]
    
    18.09 
    If you have a group of files whose names end with .new and you want 
    to rename them to end with .old, this _won't_ work:
    
    % mv *.new *.old       (Wrong!)
    
    because the shell can't match *.old and because the mv command just 
    doesn't work that way. Here's how to do it:
    
    % ls -d *.new | sed "s/\(.*\)\.new$/mv '&' '\1.old'/" | sh
    
    That outputs a seris of mv commands, one per file, and pipes them to 
    a shell.  The quotes help make sure that special characters aren't 
    touched by the shell -- this isn't always needed, but it's a good 
    idea if you aren't sure what files you'll be renaming:
    
      mv 'afile.new' 'afile.old'
      mv 'bfile.new' 'bfile.old'
         ...
    
    (To see the commands that will be generated rather than executing 
    them, leave off the | sh or use sh - v .)  Top copy, change mv to cp. 
     For safety, use mv -i or cp -i if your versions have th -i option.
    
    This method works for any UNIX command that takes a pair of 
    filenames.  For instance, to compare a set of files in the current 
    directory with the original files in the /usr/local/src directory, 
    use diff:
    
    % ls -d *.c *.h | sed 's@.*@diff -c & /usr/local/src/&@' | sh
    
    ~kevin


    Back to top

    Using tar for flexible archives


    Because of the number of switches, the syntax used for tar is often
    complicated especially when you would like to use it for something
    that you normally do not. For instance, you can use find to tar
    a certain type of file under a directory and sub-directories with
    the following steps:
    
    First, cd to the directory:
    
    $ cd /directory
    
    Next, do a tar with find:
    
    $ tar home/files.tar `find . -name pattern -print`
    
    This creates a tar archive of the files found in the search.


    Back to top

    Monitoring progress of output files


    If you've ever used the tail command, you know how helpful it can be when working in files.
    Here's a demonstration:
    
    First, create a file to monitor. For example, open the terminal window and use the touch
    command:
    
    $ touch /tmp/bogus
    
    Second, start monitoring the file for special entries, using the tail command with the -f option
    and pipe it to the egrep command with the -i option with entries. For example:
    
    $ tail -f/tmp/bogus | egrep -I 'fred|bruce'
    
    Third, start adding entries to the file, for the tail command to identify. For example:
    
    $ echo ginger >> /tmpbogus
    $ echo fred >> /tmpbogus
    $ echo Fred >> /tmpbogus
    $ echo ginger >> /tmpbogus
    $ echo bruce >> /tmpbogus
    $ echo bruce >> /tmpbogus
    $ echo fred >> /tmpbogus
    $ echo ginger >> /tmpbogus
    
    Finally, you check the output. For example:
    
    $ tail -f/tmp/bogus | egrep -I 'fred|bruce'
    fred 
    Fred 
    bruce 
    bruce 
    fred
    
    Contributor: Mark McManus, GeoQuest Systems


    Back to top

    Deleting a file by Inode


    It is often unsafe to delete long files names with spaces or other weird characters. Here is a safer method.

    ls -i [filename] will give you the inode
    find . -inum -exec rm -i {} \;


    Back to top

    Searching for strings in binary files


    $ strings /usr/bin/perl | head -10 DynaLoader::boot_DynaLoader
    perlmain.c
    PERL_DL_NONLAZY
    Usage: DynaLoader::dl_load_file(filename, flags=0)
    Usage: DynaLoader::dl_unload_file(libref)
    Usage: DynaLoader::dl_find_symbol(libhandle, symbolname)
    Usage: DynaLoader::dl_undef_symbols()
    Usage: DynaLoader::dl_install_xsub(perl_name, symref, filename="$Package")
    DynaLoader
    Usage: DynaLoader::dl_error()



    Back to top

    Figuring out what's on the archive tape


    You've backed up your file system on an archive tape. But let's say you forgot to label what's on the tape? You can get a listing of the files on an archive tape using Solaris. Once you insert the tape into the tape drive, go to the terminal window and enter:

    cpio -civt < /dev/rmt/n

    This command has four options. The c option writes header information in ASCII character form. The i option reads in the contents of the tape. The v option prints output in a format like the output from an ls -l command. The t option displays the tape table of contents (for files).

    When you issue this command, you have to replace the n with the drive number.

    Back to top

    Sitemap:

    [ Home | My professional site | Sig | Blogs | Podcasts | Where is Kevin? | Contact | Resume | More about Kevin ]
    [ Geek | Weather | Radio | Aero | Electronics | Trains | GPS | Music | Travel | Movies | For sale | Photos ]
    [ Mailing Lists | Quotes | Looking for a job? | Cheap gas? | Public files | Links | Changes ]
    [ Inscoe Family | The Volt Company | Yellow Twister Hosting | Refuge Software ]
    [ Central Florida Geeks | Central Florida Unix Professionals ]

    Why are these pages black?

    This site is Lynx friendly!

    Current time in Deltona, Florida, United States [28.9002N 81.2419W | Grid: EL98jv] is Tue Feb 9 06:17:34 2010


    Copyright © 1995-2005 Kevin P. Inscoe Viewable With Any Browser

    This website and all original artwork and material is © copyright 2009 Kevin P. Inscoe. Other material is used under the "Fair Use" provisions of United States of America Copyright law, and all rights remain with the original copyright holders.