Advanced Bash-Scripting Guide: An in-depth exploration of the art of shell scripting
Prev | Chapter 16. External Filters, Programs and Commands | Next

# 16.6. Communications Commands

Certain of the following commands find use in network data transfer and analysis, as well as in chasing spammers.

Information and Statistics

host

  Searches for information about an Internet host by name or IP address, using DNS.

       bash$ host surfacemail.com
       surfacemail.com. has address 202.92.42.236

ipcalc

  Displays IP information for a host. With the `-h` option, ipcalc does a reverse DNS lookup, finding the name of the host (server) from the IP address.

       bash$ ipcalc -h 202.92.42.236
       HOSTNAME=surfacemail.com

nslookup

  Do an Internet "name server lookup" on a host by IP address. This is essentially equivalent to ipcalc -h or dig -x . The command may be run either interactively or noninteractively, i.e., from within a script.

  The nslookup command has allegedly been "deprecated," but it is still useful.

       bash$ nslookup -sil 66.97.104.180
       nslookup kuhleersparnis.ch
       Server:         135.116.137.2
       Address:        135.116.137.2#53

       Non-authoritative answer:
       Name:   kuhleersparnis.ch

dig

  Domain Information Groper. Similar to nslookup, dig does an Internet name server lookup on a host. May be run from the command-line or from within a script.

  Some interesting options to dig are `+time=N` for setting a query timeout to `N` seconds, `+nofail` for continuing to query servers until a reply is received, and `-x` for doing a reverse address lookup.

  Compare the output of dig -x with ipcalc -h and nslookup.

       bash$ dig -x 81.9.6.2
       ;; Got answer:
       ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 11649
       ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

       ;; QUESTION SECTION:
       ;2.6.9.81.in-addr.arpa.         IN      PTR

       ;; AUTHORITY SECTION:
       6.9.81.in-addr.arpa.    3600    IN      SOA     ns.eltel.net. noc.eltel.net.
       2002031705 900 600 86400 3600

       ;; Query time: 537 msec
       ;; SERVER: 135.116.137.2#53(135.116.137.2)
       ;; WHEN: Wed Jun 26 08:35:24 2002
       ;; MSG SIZE  rcvd: 91

  Example 16-40. Finding out where to report a spammer

         1 #!/bin/bash
         2 # spam-lookup.sh: Look up abuse contact to report a spammer.
         3 # Thanks, Michael Zick.
         4
         5 # Check for command-line arg.
         6 ARGCOUNT=1
         7 E_WRONGARGS=85
         8 if [ $# -ne "$ARGCOUNT" ]
         9 then
        10   echo "Usage: `basename $0` domain-name"
        11   exit $E_WRONGARGS
        12 fi
        13
        14
        15 dig +short $1.contacts.abuse.net -c in -t txt
        16 # Also try:
        17 #     dig +nssearch $1
        18 #     Tries to find "authoritative name servers" and display SOA records.
        19
        20 # The following also works:
        21 #     whois -h whois.abuse.net $1
        22 #           ^^ ^^^^^^^^^^^^^^^  Specify host.
        23 #     Can even lookup multiple spammers with this, i.e."
        24 #     whois -h whois.abuse.net $spamdomain1 $spamdomain2 . . .
        25
        26
        27 #  Exercise:
        28 #  --------
        29 #  Expand the functionality of this script
        30 #+ so that it automatically e-mails a notification
        31 #+ to the responsible ISP's contact address(es).
        32 #  Hint: use the "mail" command.
        33
        34 exit $?
        35
        36 # spam-lookup.sh chinatietong.com
        37 #                A known spam domain.
        38
        39 # "crnet_mgr@chinatietong.com"
        40 # "crnet_tec@chinatietong.com"
        41 # "postmaster@chinatietong.com"
        42
        43
        44 #  For a more elaborate version of this script,
        45 #+ see the SpamViz home page, http://www.spamviz.net/index.html.

  Example 16-41. Analyzing a spam domain

         1 #! /bin/bash
         2 # is-spammer.sh: Identifying spam domains
         3
         4 # $Id: is-spammer, v 1.4 2004/09/01 19:37:52 mszick Exp $
         5 # Above line is RCS ID info.
         6 #
         7 #  This is a simplified version of the "is_spammer.bash
         8 #+ script in the Contributed Scripts appendix.
         9
        10 # is-spammer <domain.name>
        11
        12 # Uses an external program: 'dig'
        13 # Tested with version: 9.2.4rc5
        14
        15 # Uses functions.
        16 # Uses IFS to parse strings by assignment into arrays.
        17 # And even does something useful: checks e-mail blacklists.
        18
        19 # Use the domain.name(s) from the text body:
        20 # http://www.good_stuff.spammer.biz/just_ignore_everything_else
        21 #                       ^^^^^^^^^^^
        22 # Or the domain.name(s) from any e-mail address:
        23 # Really_Good_Offer@spammer.biz
        24 #
        25 # as the only argument to this script.
        26 #(PS: have your Inet connection running)
        27 #
        28 # So, to invoke this script in the above two instances:
        29 #       is-spammer.sh spammer.biz
        30
        31
        32 # Whitespace == :Space:Tab:Line Feed:Carriage Return:
        33 WSP_IFS=$'\x20'$'\x09'$'\x0A'$'\x0D'
        34
        35 # No Whitespace == Line Feed:Carriage Return
        36 No_WSP=$'\x0A'$'\x0D'
        37
        38 # Field separator for dotted decimal ip addresses
        39 ADR_IFS=${No_WSP}'.'
        40
        41 # Get the dns text resource record.
        42 # get_txt <error_code> <list_query>
        43 get_txt() {
        44
        45     # Parse $1 by assignment at the dots.
        46     local -a dns
        47     IFS=$ADR_IFS
        48     dns=( $1 )
        49     IFS=$WSP_IFS
        50     if [ "${dns[0]}" == '127' ]
        51     then
        52         # See if there is a reason.
        53         echo $(dig +short $2 -t txt)
        54     fi
        55 }
        56
        57 # Get the dns address resource record.
        58 # chk_adr <rev_dns> <list_server>
        59 chk_adr() {
        60     local reply
        61     local server
        62     local reason
        63
        64     server=${1}${2}
        65     reply=$( dig +short ${server} )
        66
        67     # If reply might be an error code . . .
        68     if [ ${#reply} -gt 6 ]
        69     then
        70         reason=$(get_txt ${reply} ${server} )
        71         reason=${reason:-${reply}}
        72     fi
        73     echo ${reason:-' not blacklisted.'}
        74 }
        75
        76 # Need to get the IP address from the name.
        77 echo 'Get address of: '$1
        78 ip_adr=$(dig +short $1)
        79 dns_reply=${ip_adr:-' no answer '}
        80 echo ' Found address: '${dns_reply}
        81
        82 # A valid reply is at least 4 digits plus 3 dots.
        83 if [ ${#ip_adr} -gt 6 ]
        84 then
        85     echo
        86     declare query
        87
        88     # Parse by assignment at the dots.
        89     declare -a dns
        90     IFS=$ADR_IFS
        91     dns=( ${ip_adr} )
        92     IFS=$WSP_IFS
        93
        94     # Reorder octets into dns query order.
        95     rev_dns="${dns[3]}"'.'"${dns[2]}"'.'"${dns[1]}"'.'"${dns[0]}"'.'
        96
        97 # See: http://www.spamhaus.org (Conservative, well maintained)
        98     echo -n 'spamhaus.org says: '
        99     echo $(chk_adr ${rev_dns} 'sbl-xbl.spamhaus.org')
       100
       101 # See: http://ordb.org (Open mail relays)
       102     echo -n '   ordb.org  says: '
       103     echo $(chk_adr ${rev_dns} 'relays.ordb.org')
       104
       105 # See: http://www.spamcop.net/ (You can report spammers here)
       106     echo -n ' spamcop.net says: '
       107     echo $(chk_adr ${rev_dns} 'bl.spamcop.net')
       108
       109 # # # other blacklist operations # # #
       110
       111 # See: http://cbl.abuseat.org.
       112     echo -n ' abuseat.org says: '
       113     echo $(chk_adr ${rev_dns} 'cbl.abuseat.org')
       114
       115 # See: http://dsbl.org/usage (Various mail relays)
       116     echo
       117     echo 'Distributed Server Listings'
       118     echo -n '       list.dsbl.org says: '
       119     echo $(chk_adr ${rev_dns} 'list.dsbl.org')
       120
       121     echo -n '   multihop.dsbl.org says: '
       122     echo $(chk_adr ${rev_dns} 'multihop.dsbl.org')
       123
       124     echo -n 'unconfirmed.dsbl.org says: '
       125     echo $(chk_adr ${rev_dns} 'unconfirmed.dsbl.org')
       126
       127 else
       128     echo
       129     echo 'Could not use that address.'
       130 fi
       131
       132 exit 0
       133
       134 # Exercises:
       135 # --------
       136
       137 # 1) Check arguments to script,
       138 #    and exit with appropriate error message if necessary.
       139
       140 # 2) Check if on-line at invocation of script,
       141 #    and exit with appropriate error message if necessary.
       142
       143 # 3) Substitute generic variables for "hard-coded" BHL domains.
       144
       145 # 4) Set a time-out for the script using the "+time=" option
       146      to the 'dig' command.

  For a much more elaborate version of the above script, see Example A-28.

traceroute

  Trace the route taken by packets sent to a remote host. This command works within a LAN, WAN, or over the Internet. The remote host may be specified by an IP address. The output of this command may be filtered by grep or sed in a pipe.

       bash$ traceroute 81.9.6.2
       traceroute to 81.9.6.2 (81.9.6.2), 30 hops max, 38 byte packets
       1  tc43.xjbnnbrb.com (136.30.178.8)  191.303 ms  179.400 ms  179.767 ms
       2  or0.xjbnnbrb.com (136.30.178.1)  179.536 ms  179.534 ms  169.685 ms
       3  192.168.11.101 (192.168.11.101)  189.471 ms  189.556 ms *
       ...

ping

  Broadcast an `ICMP ECHO_REQUEST` packet to another machine, either on a local or remote network. This is a diagnostic tool for testing network connections, and it should be used with caution.

       bash$ ping localhost
       PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
       64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=709 usec
       64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=255 time=286 usec

       --- localhost.localdomain ping statistics ---
       2 packets transmitted, 2 packets received, 0% packet loss
       round-trip min/avg/max/mdev = 0.286/0.497/0.709/0.212 ms

  A successful ping returns an exit status of 0. This can be tested for in a script.

         1   HNAME=news-15.net  # Notorious spammer.
         2 # HNAME=$HOST     # Debug: test for localhost.
         3   count=2  # Send only two pings.
         4
         5 if [[ `ping -c $count "$HNAME"` ]]
         6 then
         7   echo ""$HNAME" still up and broadcasting spam your way."
         8 else
         9   echo ""$HNAME" seems to be down. Pity."
        10 fi

whois

  Perform a DNS (Domain Name System) lookup. The `-h` option permits specifying which particular whois server to query. See Example 4-6 and Example 16-40.

finger

  Retrieve information about users on a network. Optionally, this command can display a user's `~/.plan`, `~/.project`, and `~/.forward` files, if present.

       bash$ finger
       Login  Name           Tty      Idle  Login Time   Office     Office Phone
       bozo   Bozo Bozeman   tty1        8  Jun 25 16:59                (:0)
       bozo   Bozo Bozeman   ttyp0          Jun 25 16:59                (:0.0)
       bozo   Bozo Bozeman   ttyp1          Jun 25 17:07                (:0.0)

       bash$ finger bozo
       Login: bozo                             Name: Bozo Bozeman
       Directory: /home/bozo                   Shell: /bin/bash
       Office: 2355 Clown St., 543-1234
       On since Fri Aug 31 20:13 (MST) on tty1    1 hour 38 minutes idle
       On since Fri Aug 31 20:13 (MST) on pts/0   12 seconds idle
       On since Fri Aug 31 20:13 (MST) on pts/1
       On since Fri Aug 31 20:31 (MST) on pts/2   1 hour 16 minutes idle
       Mail last read Tue Jul  3 10:08 2007 (MST)
       No Plan.

  Out of security considerations, many networks disable finger and its associated daemon. [1]

chfn

  Change information disclosed by the finger command.

vrfy

  Verify an Internet e-mail address.

  This command seems to be missing from newer Linux distros.

Remote Host Access

sx, rx

  The sx and rx command set serves to transfer files to and from a remote host using the xmodem protocol. These are generally part of a communications package, such as minicom.

sz, rz

  The sz and rz command set serves to transfer files to and from a remote host using the zmodem protocol. Zmodem has certain advantages over xmodem, such as faster transmission rate and resumption of interrupted file transfers. Like sx and rx, these are generally part of a communications package.

ftp

  Utility and protocol for uploading / downloading files to or from a remote host. An ftp session can be automated in a script (see Example 19-6 and Example A-4).

uucp, uux, cu

  uucp: UNIX to UNIX copy. This is a communications package for transferring files between UNIX servers. A shell script is an effective way to handle a uucp command sequence.

  Since the advent of the Internet and e-mail, uucp seems to have faded into obscurity, but it still exists and remains perfectly workable in situations where an Internet connection is not available or appropriate. The advantage of uucp is that it is fault-tolerant, so even if there is a service interruption the copy operation will resume where it left off when the connection is restored.

  ---

  uux: UNIX to UNIX execute. Execute a command on a remote system. This command is part of the uucp package.

  ---

  cu: Call Up a remote system and connect as a simple terminal. It is a sort of dumbed-down version of telnet. This command is part of the uucp package.

telnet

  Utility and protocol for connecting to a remote host.

  | The telnet protocol contains security holes and should therefore probably be avoided. Its use within a shell script is not recommended.

wget

  The wget utility noninteractively retrieves or downloads files from a Web or ftp site. It works well in a script.

         1 wget -p http://www.xyz23.com/file01.html
         2 #  The -p or --page-requisite option causes wget to fetch all files
         3 #+ required to display the specified page.
         4
         5 wget -r ftp://ftp.xyz24.net/~bozo/project_files/ -O $SAVEFILE
         6 #  The -r option recursively follows and retrieves all links
         7 #+ on the specified site.
         8
         9 wget -c ftp://ftp.xyz25.net/bozofiles/filename.tar.bz2
        10 #  The -c option lets wget resume an interrupted download.
        11 #  This works with ftp servers and many HTTP sites.

  Example 16-42. Getting a stock quote

         1 #!/bin/bash
         2 # quote-fetch.sh: Download a stock quote.
         3
         4
         5 E_NOPARAMS=86
         6
         7 if [ -z "$1" ]  # Must specify a stock (symbol) to fetch.
         8   then echo "Usage: `basename $0` stock-symbol"
         9   exit $E_NOPARAMS
        10 fi
        11
        12 stock_symbol=$1
        13
        14 file_suffix=.html
        15 # Fetches an HTML file, so name it appropriately.
        16 URL='http://finance.yahoo.com/q?s='
        17 # Yahoo finance board, with stock query suffix.
        18
        19 # -----------------------------------------------------------
        20 wget -O ${stock_symbol}${file_suffix} "${URL}${stock_symbol}"
        21 # -----------------------------------------------------------
        22
        23
        24 # To look up stuff on http://search.yahoo.com:
        25 # -----------------------------------------------------------
        26 # URL="http://search.yahoo.com/search?fr=ush-news&p=${query}"
        27 # wget -O "$savefilename" "${URL}"
        28 # -----------------------------------------------------------
        29 # Saves a list of relevant URLs.
        30
        31 exit $?
        32
        33 # Exercises:
        34 # ---------
        35 #
        36 # 1) Add a test to ensure the user running the script is on-line.
        37 #    (Hint: parse the output of 'ps -ax' for "ppp" or "connect."
        38 #
        39 # 2) Modify this script to fetch the local weather report,
        40 #+   taking the user's zip code as an argument.

  See also Example A-30 and Example A-31.

lynx

  The lynx Web and file browser can be used inside a script (with the `-dump` option) to retrieve a file from a Web or ftp site noninteractively.

         1 lynx -dump http://www.xyz23.com/file01.html >$SAVEFILE

  With the `-traversal` option, lynx starts at the HTTP URL specified as an argument, then "crawls" through all links located on that particular server. Used together with the `-crawl` option, outputs page text to a log file.

rlogin

  `Remote login`, initates a session on a remote host. This command has security issues, so use ssh instead.

rsh

  `Remote shell`, executes command(s) on a remote host. This has security issues, so use ssh instead.

rcp

  `Remote copy`, copies files between two different networked machines.

rsync

  `Remote synchronize`, updates (synchronizes) files between two different networked machines.

       bash$ rsync -a ~/sourcedir/*txt /node1/subdirectory/

  Example 16-43. Updating FC4

         1 #!/bin/bash
         2 # fc4upd.sh
         3
         4 # Script author: Frank Wang.
         5 # Slight stylistic modifications by ABS Guide author.
         6 # Used in ABS Guide with permission.
         7
         8
         9 #  Download Fedora Core 4 update from mirror site using rsync.
        10 #  Should also work for newer Fedora Cores -- 5, 6, . . .
        11 #  Only download latest package if multiple versions exist,
        12 #+ to save space.
        13
        14 URL=rsync://distro.ibiblio.org/fedora-linux-core/updates/
        15 # URL=rsync://ftp.kddilabs.jp/fedora/core/updates/
        16 # URL=rsync://rsync.planetmirror.com/fedora-linux-core/updates/
        17
        18 DEST=${1:-/var/www/html/fedora/updates/}
        19 LOG=/tmp/repo-update-$(/bin/date +%Y-%m-%d).txt
        20 PID_FILE=/var/run/${0##*/}.pid
        21
        22 E_RETURN=85        # Something unexpected happened.
        23
        24
        25 # General rsync options
        26 # -r: recursive download
        27 # -t: reserve time
        28 # -v: verbose
        29
        30 OPTS="-rtv --delete-excluded --delete-after --partial"
        31
        32 # rsync include pattern
        33 # Leading slash causes absolute path name match.
        34 INCLUDE=(
        35     "/4/i386/kde-i18n-Chinese*"
        36 #   ^                         ^
        37 # Quoting is necessary to prevent globbing.
        38 )
        39
        40
        41 # rsync exclude pattern
        42 # Temporarily comment out unwanted pkgs using "#" . . .
        43 EXCLUDE=(
        44     /1
        45     /2
        46     /3
        47     /testing
        48     /4/SRPMS
        49     /4/ppc
        50     /4/x86_64
        51     /4/i386/debug
        52    "/4/i386/kde-i18n-*"
        53    "/4/i386/openoffice.org-langpack-*"
        54    "/4/i386/*i586.rpm"
        55    "/4/i386/GFS-*"
        56    "/4/i386/cman-*"
        57    "/4/i386/dlm-*"
        58    "/4/i386/gnbd-*"
        59    "/4/i386/kernel-smp*"
        60 #  "/4/i386/kernel-xen*"
        61 #  "/4/i386/xen-*"
        62 )
        63
        64
        65 init () {
        66     # Let pipe command return possible rsync error, e.g., stalled network.
        67     set -o pipefail                  # Newly introduced in Bash, version 3.
        68
        69     TMP=${TMPDIR:-/tmp}/${0##*/}.$$  # Store refined download list.
        70     trap "{
        71         rm -f $TMP 2>/dev/null
        72     }" EXIT                          # Clear temporary file on exit.
        73 }
        74
        75
        76 check_pid () {
        77 # Check if process exists.
        78     if [ -s "$PID_FILE" ]; then
        79         echo "PID file exists. Checking ..."
        80         PID=$(/bin/egrep -o "^[[:digit:]]+" $PID_FILE)
        81         if /bin/ps --pid $PID &>/dev/null; then
        82             echo "Process $PID found. ${0##*/} seems to be running!"
        83            /usr/bin/logger -t ${0##*/} \
        84                  "Process $PID found. ${0##*/} seems to be running!"
        85             exit $E_RETURN
        86         fi
        87         echo "Process $PID not found. Start new process . . ."
        88     fi
        89 }
        90
        91
        92 #  Set overall file update range starting from root or $URL,
        93 #+ according to above patterns.
        94 set_range () {
        95     include=
        96     exclude=
        97     for p in "${INCLUDE[@]}"; do
        98         include="$include --include \"$p\""
        99     done
       100
       101     for p in "${EXCLUDE[@]}"; do
       102         exclude="$exclude --exclude \"$p\""
       103     done
       104 }
       105
       106
       107 # Retrieve and refine rsync update list.
       108 get_list () {
       109     echo $$ > $PID_FILE || {
       110         echo "Can't write to pid file $PID_FILE"
       111         exit $E_RETURN
       112     }
       113
       114     echo -n "Retrieving and refining update list . . ."
       115
       116     # Retrieve list -- 'eval' is needed to run rsync as a single command.
       117     # $3 and $4 is the date and time of file creation.
       118     # $5 is the full package name.
       119     previous=
       120     pre_file=
       121     pre_date=0
       122     eval /bin/nice /usr/bin/rsync \
       123         -r $include $exclude $URL | \
       124         egrep '^dr.x|^-r' | \
       125         awk '{print $3, $4, $5}' | \
       126         sort -k3 | \
       127         { while read line; do
       128             # Get seconds since epoch, to filter out obsolete pkgs.
       129             cur_date=$(date -d "$(echo $line | awk '{print $1, $2}')" +%s)
       130             #  echo $cur_date
       131
       132             # Get file name.
       133             cur_file=$(echo $line | awk '{print $3}')
       134             #  echo $cur_file
       135
       136             # Get rpm pkg name from file name, if possible.
       137             if [[ $cur_file == *rpm ]]; then
       138                 pkg_name=$(echo $cur_file | sed -r -e \
       139                     's/(^([^_-]+[_-])+)[[:digit:]]+\..*[_-].*$/\1/')
       140             else
       141                 pkg_name=
       142             fi
       143             # echo $pkg_name
       144
       145             if [ -z "$pkg_name" ]; then   #  If not a rpm file,
       146                 echo $cur_file >> $TMP    #+ then append to download list.
       147             elif [ "$pkg_name" != "$previous" ]; then   # A new pkg found.
       148                 echo $pre_file >> $TMP                  # Output latest file.
       149                 previous=$pkg_name                      # Save current.
       150                 pre_date=$cur_date
       151                 pre_file=$cur_file
       152             elif [ "$cur_date" -gt "$pre_date" ]; then
       153                                                 #  If same pkg, but newer,
       154                 pre_date=$cur_date              #+ then update latest pointer.
       155                 pre_file=$cur_file
       156             fi
       157             done
       158             echo $pre_file >> $TMP              #  TMP contains ALL
       159                                                 #+ of refined list now.
       160             # echo "subshell=$BASH_SUBSHELL"
       161
       162     }       # Bracket required here to let final "echo $pre_file >> $TMP"
       163             # Remained in the same subshell ( 1 ) with the entire loop.
       164
       165     RET=$?  # Get return code of the pipe command.
       166
       167     [ "$RET" -ne 0 ] && {
       168         echo "List retrieving failed with code $RET"
       169         exit $E_RETURN
       170     }
       171
       172     echo "done"; echo
       173 }
       174
       175 # Real rsync download part.
       176 get_file () {
       177
       178     echo "Downloading..."
       179     /bin/nice /usr/bin/rsync \
       180         $OPTS \
       181         --filter "merge,+/ $TMP" \
       182         --exclude '*'  \
       183         $URL $DEST     \
       184         | /usr/bin/tee $LOG
       185
       186     RET=$?
       187
       188    #  --filter merge,+/ is crucial for the intention.
       189    #  + modifier means include and / means absolute path.
       190    #  Then sorted list in $TMP will contain ascending dir name and
       191    #+ prevent the following --exclude '*' from "shortcutting the circuit."
       192
       193     echo "Done"
       194
       195     rm -f $PID_FILE 2>/dev/null
       196
       197     return $RET
       198 }
       199
       200 # -------
       201 # Main
       202 init
       203 check_pid
       204 set_range
       205 get_list
       206 get_file
       207 RET=$?
       208 # -------
       209
       210 if [ "$RET" -eq 0 ]; then
       211     /usr/bin/logger -t ${0##*/} "Fedora update mirrored successfully."
       212 else
       213     /usr/bin/logger -t ${0##*/} \
       214     "Fedora update mirrored with failure code: $RET"
       215 fi
       216
       217 exit $RET

  See also Example A-32.

  | Using rcp, rsync, and similar utilities with security implications in a shell script may not be advisable. Consider, instead, using ssh, scp, or an expect script.

ssh

  `Secure shell`, logs onto a remote host and executes commands there. This secure replacement for telnet, rlogin, rcp, and rsh uses identity authentication and encryption. See its manpage for details.

  Example 16-44. Using ssh

         1 #!/bin/bash
         2 # remote.bash: Using ssh.
         3
         4 # This example by Michael Zick.
         5 # Used with permission.
         6
         7
         8 #   Presumptions:
         9 #   ------------
        10 #   fd-2 isn't being captured ( '2>/dev/null' ).
        11 #   ssh/sshd presumes stderr ('2') will display to user.
        12 #
        13 #   sshd is running on your machine.
        14 #   For any 'standard' distribution, it probably is,
        15 #+  and without any funky ssh-keygen having been done.
        16
        17 # Try ssh to your machine from the command-line:
        18 #
        19 # $ ssh $HOSTNAME
        20 # Without extra set-up you'll be asked for your password.
        21 #   enter password
        22 #   when done,  $ exit
        23 #
        24 # Did that work? If so, you're ready for more fun.
        25
        26 # Try ssh to your machine as 'root':
        27 #
        28 #   $  ssh -l root $HOSTNAME
        29 #   When asked for password, enter root's, not yours.
        30 #          Last login: Tue Aug 10 20:25:49 2004 from localhost.localdomain
        31 #   Enter 'exit' when done.
        32
        33 #  The above gives you an interactive shell.
        34 #  It is possible for sshd to be set up in a 'single command' mode,
        35 #+ but that is beyond the scope of this example.
        36 #  The only thing to note is that the following will work in
        37 #+ 'single command' mode.
        38
        39
        40 # A basic, write stdout (local) command.
        41
        42 ls -l
        43
        44 # Now the same basic command on a remote machine.
        45 # Pass a different 'USERNAME' 'HOSTNAME' if desired:
        46 USER=${USERNAME:-$(whoami)}
        47 HOST=${HOSTNAME:-$(hostname)}
        48
        49 #  Now excute the above command-line on the remote host,
        50 #+ with all transmissions encrypted.
        51
        52 ssh -l ${USER} ${HOST} " ls -l "
        53
        54 #  The expected result is a listing of your username's home
        55 #+ directory on the remote machine.
        56 #  To see any difference, run this script from somewhere
        57 #+ other than your home directory.
        58
        59 #  In other words, the Bash command is passed as a quoted line
        60 #+ to the remote shell, which executes it on the remote machine.
        61 #  In this case, sshd does  ' bash -c "ls -l" '   on your behalf.
        62
        63 #  For information on topics such as not having to enter a
        64 #+ password/passphrase for every command-line, see
        65 #+    man ssh
        66 #+    man ssh-keygen
        67 #+    man sshd_config.
        68
        69 exit 0

  | Within a loop, ssh may cause unexpected behavior. According to a Usenet post in the comp.unix shell archives, ssh inherits the loop's `stdin`. To remedy this, pass ssh either the `-n` or `-f` option. Thanks, Jason Bechtel, for pointing this out.

scp

  `Secure copy`, similar in function to rcp, copies files between two different networked machines, but does so using authentication, and with a security level similar to ssh.

Local Network

write

  This is a utility for terminal-to-terminal communication. It allows sending lines from your terminal (console or xterm) to that of another user. The mesg command may, of course, be used to disable write access to a terminal

  Since write is interactive, it would not normally find use in a script.

netconfig

  A command-line utility for configuring a network adapter (using DHCP). This command is native to Red Hat centric Linux distros.

Mail

mail

  Send or read e-mail messages.

  This stripped-down command-line mail client works fine as a command embedded in a script.

  Example 16-45. A script that mails itself

         1 #!/bin/sh
         2 # self-mailer.sh: Self-mailing script
         3
         4 adr=${1:-`whoami`}     # Default to current user, if not specified.
         5 #  Typing 'self-mailer.sh wiseguy@superdupergenius.com'
         6 #+ sends this script to that addressee.
         7 #  Just 'self-mailer.sh' (no argument) sends the script
         8 #+ to the person invoking it, for example, bozo@localhost.localdomain.
         9 #
        10 #  For more on the ${parameter:-default} construct,
        11 #+ see the "Parameter Substitution" section
        12 #+ of the "Variables Revisited" chapter.
        13
        14 # ============================================================================
        15   cat $0 | mail -s "Script \"`basename $0`\" has mailed itself to you." "$adr"
        16 # ============================================================================
        17
        18 # --------------------------------------------
        19 #  Greetings from the self-mailing script.
        20 #  A mischievous person has run this script,
        21 #+ which has caused it to mail itself to you.
        22 #  Apparently, some people have nothing better
        23 #+ to do with their time.
        24 # --------------------------------------------
        25
        26 echo "At `date`, script \"`basename $0`\" mailed to "$adr"."
        27
        28 exit 0
        29
        30 #  Note that the "mailx" command (in "send" mode) may be substituted
        31 #+ for "mail" ... but with somewhat different options.

mailto

  Similar to the mail command, mailto sends e-mail messages from the command-line or in a script. However, mailto also permits sending MIME (multimedia) messages.

mailstats

  Show mail statistics. This command may be invoked only by root.

       root# mailstats
       Statistics from Tue Jan  1 20:32:08 2008
        M   msgsfr  bytes_from   msgsto    bytes_to  msgsrej msgsdis msgsqur  Mailer
        4     1682      24118K        0          0K        0       0       0  esmtp
        9      212        640K     1894      25131K        0       0       0  local
       =====================================================================
        T     1894      24758K     1894      25131K        0       0       0
        C      414                    0

vacation

  This utility automatically replies to e-mails that the intended recipient is on vacation and temporarily unavailable. It runs on a network, in conjunction with sendmail, and is not applicable to a dial-up POPmail account.

### Notes

[1] | A daemon is a background process not attached to a terminal session. Daemons perform designated services either at specified times or explicitly triggered by certain events. The word "daemon" means ghost in Greek, and there is certainly something mysterious, almost supernatural, about the way UNIX daemons wander about behind the scenes, silently carrying out their appointed tasks.

Prev | Home | Next
File and Archiving Commands | Up | Terminal Control Commands