Appendix A. Answers to Exercises

  1. It is good to learn vi and emacs, if only because those editors are available nearly everywhere. Which you choose depends on your preferences. Don't worry if you dislike the choices made by your colleagues. The key is to find an editor that works for you.

    Some criteria that may help choose an editor:

    • Does it work on the platforms you need to use? For example, at a university, does the editor work in the computer labs as well as on the computers you have available where you live?

    • Is the performance good enough? Some editors, especially high-end Java Integrated Development Environments, or IDEs, can run painfully slow on systems without at least 1 GB of RAM.

    • Do you like the "feel" of the editor? This is very subjective but quite important. You may never quite get into the feel of emacs, for example.

  2. Vi can be a real pain in the rear end. It can also be very, very productive. Some of the best features of vi include:

    • Its speed. Vi starts fast and runs fast.

    • The dot command (.), which repeats the previous operation. This can be very powerful.

    • The ability to execute a command a number of times, such as 4yy (yank four lines) or 100dd (delete 100 lines).

    • All the enhancements in vim. Vim really creates a new, and much better, editor.

    Emacs can be a real pain in the rear end. It can also be very, very productive. Some of the best features of emacs include:

    • The multiple buffers. You can really make use of separate buffers when performing complex edits.

    • The integrated shell. You can execute shell commands from within the context of the editor.

    • The directory browser. You can look through directories, selecting files to edit.

    • The ability to edit the same file in multiple places.

    • The ability to program the editor. Anything your computer can do can be done within emacs.

  3. This is just one example of the extreme ugliness you can create with shell scripts:

    # See if you can come up with more statements than this.
    # This is ugly. In case we forget, this script outputs:
    # A man, a plan, a canal, Panama
    
    a=A
    echo -n "$a"
    unset a
    a=" "
    echo -n "$a"
    unset a
    a="m"
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a="n"
    echo -n "$a"
    unset a
    a=","
    echo -n "$a"
    unset a
    a=" "
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a=" "
    echo -n "$a"
    unset a
    a="p"
    echo -n "$a"
    unset a
    a="l"
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a="n"
    echo -n "$a"
    unset a
    a=","
    echo -n "$a"
    unset a
    a=" "
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a=" "
    echo -n "$a"
    unset a
    a="c"
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a="n"
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a="l"
    echo -n "$a"
    unset a
    a=","
    echo -n "$a"
    unset a
    a=" "
    echo -n "$a"
    unset a
    a="P"
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a="n"
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a="m"
    echo -n "$a"
    unset a
    a="a"
    echo -n "$a"
    unset a
    a="."
    echo -n "$a"
    unset a
    
    echo
  4. The following scripts show how you can create commands, store those commands within a variable, and then access the variable to execute the command:

    # Starting script.
    DIRECTORY=/usr/local
    LS=ls
    CMD="$LS $DIRECTORY"
    $CMD     # Note how the command is executed indirectly.
    
    
    # Add a −1 (one) command-line option.
    DIRECTORY=/usr/local
    LS=ls
    LS_OPTS="-1"
    CMD="$LS $LS_OPTS $DIRECTORY"
    $CMD
    
    
    # Even more indirect script.
    DIRECTORY=/usr/local
    LS=ls
    LS_OPTS="-1"
    LS_CMD="$LS $LS_OPTS"
    CMD="$LS_CMD $DIRECTORY"
    $CMD
  5. This is about the smallest change to make the script apply to Canadian users:

    echo -n "Please enter your first name: "
    read FIRSTNAME
    echo -n "Please enter your last name: "
    read LASTNAME
    echo -n "Please enter the name of the province where you live: "
    read PROVINCE
    
    FULLNAME="$FIRSTNAME $LASTNAME"
    MESSAGE="Well, $FULLNAME of $PROVINCE, welcome to our huge"
    MESSAGE="$MESSAGE impersonal company."
    
    echo "$MESSAGE"
    echo "You will now be known as Worker Unit 10236."
  6. You don't need to be a guru. You don't have to show off. Just pick an editor that works for you.

  7. There is a reason modern keyboards have Page Up, Page Down, Home, End, arrows, and other keys: these keys have proved useful.

  1. Do it. Really. You may want to discuss why many applications allow you to click on long choices like this or provide some other means to quickly make selections. Any script that interacts with the user has a user interface, and it behooves you to make an interface that at least isn't difficult to understand.

  2. This example extends the myls script. You can use the same technique for the myls2 script:

    # This example extends the myls script.
    
    # Change to the directory
    # so the file listing is all relative file names.
    cd /usr/local
    
    # List the files.
    for filename in *
    do
        echo $filename
    done

    Note how this script uses the cd command to change to the target directory. This means that the for loop will list all relative file names, such as bin, and not absolute file names, such as /usr/local/bin.

    You can also take an approach such as the following:

    for filename in /usr/local/*
    do
        echo $filename
    done

    This example will output absolute file names, however.

  3. These scripts extend the ones from the previous question:

    # This example extends the myls script.
    
    DIRECTORY=/usr/local
    
    # Change to this directory
    # so the file listing is all relative file names.
    
    cd $DIRECTORY
    
    # List the files.
    echo "Listing $DIRECTORY"
    
    for filename in *
    do
        echo $filename
    done

    The second approach that outputs absolute file names looks like the following:

    DIRECTORY=/usr/local
    
    for filename in $DIRECTORY/*
    do
        echo $filename
    done
  4. This problem is solved by adding a read command to read in the directory name, rather than setting the name to a fixed directory:

    # This example extends the myls script.
    
    echo -n "Please enter the directory to list: "
    read DIRECTORY
    
    # Change to this directory
    # so the file listing is all relative file names.
    
    cd $DIRECTORY
    
    # List the files.
    echo "Listing $DIRECTORY"
    
    for filename in *
    do
        echo $filename
    done
  5. Try the ls -CF1 (C, F, one) command to get an idea how this output should look. To do this, use the file-specific test options of the test command:

    # This example extends the myls script.
    
    echo -n "Please enter the directory to list: "
    read DIRECTORY
    
    # Change to this directory
    # so the file listing is all relative file names.
    
    cd $DIRECTORY
    
    # List the files.
    echo "Listing $DIRECTORY"
    
    for filename in *
    do
        if [ -d $filename ]
        then
            echo "$filename/"
        elif [ -x $filename ]
        then
            echo "$filename*"
        else
            echo $filename
        fi
    done
  1. #unset SHELL
    
    if [ "$SHELL" == "" ]
    then
        echo "SHELL not set."
        echo "Bailing out."
        exit −1
    fi

    Uncomment the unset SHELL line to run the script with the SHELL environment variable not set, and verify the script works with both cases.

  2. for arg in $*
    do
        if [ "$arg" != "" ]
        then
            echo "Arg: $arg"
        fi
    done
    
    echo "Total args: $#"

    This exercise combines the for loop and if statement from Chapter 3 with the command-line arguments introduced in this chapter.

  3. This may seem like a total cheat:

    echo "All arguments [$*]"

    The crucial point here is that while the C shell uses a different variable to hold the number of command-line arguments, the variable $* works in all of the listed shells and, conveniently enough, holds all the command-line arguments.

  4. This exercise requires one loop to iterate over the command-line arguments, each of which names a directory, and a second, nested loop to iterate over the files within each directory:

    # Assumes each command-line argument
    # names a directory to list.
    
    for directory in $*
    do
        echo "$directory:"
        cd $directory
        for filename in *
        do
            echo $filename
        done
        echo
    done
  1. # Locks down file permissions.
    
    for filename in *
    do
    
        # Lock down the file permissions.
        chmod g-rwx,o-rwx $filename
    
    done
  2. Add the following text to the first line of the script:

    #! /bin/sh
    Then, mark the script with execute permissions.
    $ chmod a+x lockdown
    The full script then appears as follows:
    #!/bin/sh
    
    # Locks down file permissions.
    
    for filename in *
    do
        # Initialize all permissions.
        r=""
        w=""
        x=""
    
        # Check to preserve existing permissions.
    
        if [ -r $filename ]
        then
            r="r"
        fi
    
        if [ -w $filename ]
        then
            w="w"
        fi
    
        if [ -x $filename ]
        then
            x="x"
        fi
    
        # Lock down the file permissions.
        chmod u+$r$w$x,g-rwx,o-rwx $filename
    
    done
  3. There are a number of ways to do this, but one of the simplest is to reverse the tests from less-than comparisons to greater-than or equal checks. For example:

    # If the user forgets to pass the command-line
    # arguments, fill in defaults.
    
    pithy_statement="Action, urgency, excellence"
    
    if [ $# -ge 1 ]
    then
        date_required=$1
    
        if [ $# -ge 2 ]
        then
            pithy_statement=$2
        fi
    else
        date_required=today
    fi
    
    
    wall <<EndOfText
    Please complete all TPS reports and have them
    on my desk by EOB $date_required.
    Your cooperation in this matter helps the smooth
    flow of our departmental structure.
    
    $pithy_statement!
    -Dick
    EndOfText
    
    echo "Message sent"
  4. Again, there are a number of ways to approach this. Here is the most straightforward:

    # If the user forgets to pass the command-line
    # arguments, fill in defaults.
    
    case $# in
    0)
        pithy_statement="Action, urgency, excellence"
        date_required=today
        ;;
    1)
        pithy_statement="Action, urgency, excellence"
        date_required=$1
        ;;
    *)
        pithy_statement=$2
        date_required=$1
        ;;
    esac
    
    
    wall <<EndOfText
    Please complete all TPS reports and have them
    on my desk by EOB $date_required.
    
    Your cooperation in this matter helps the smooth
    flow of our departmental structure.
    
    $pithy_statement!
    -Dick
    EndOfText
    
    echo "Message sent"
  5. Here is one such script:

    # First script, outputs a second, that in turn, outputs a third.
    
    cat <<'End1'
    
        # This is a comment in a script.
        cat <<'End2'
            echo "This is the next output script."
            echo "It doesn't do anything."
    End2
    
    End1

    Note that the end markers must start at the beginning of a line.

    When you run this script, it outputs the following:

    # This is a comment in a script.
        cat <<'End2'
            echo "This is the next output script."
            echo "It doesn't do anything."
    End2

    Save this text to a file, and run this script. When run, it outputs the following:

    echo "This is the next output script."
            echo "It doesn't do anything."

    Save this text to a file, and run this script. When run, it outputs the following:

    This is the next output script.
    It doesn't do anything.
  1. cat /etc/passwd | sed '5!d'
  2. cat /etc/passwd | sed -n '10∼5d'
  3. cat /etc/passwd | sed '10∼d' or cat /etc/passwd | sed '10∼0d'
  4. ls -l $HOME | sed 's/micah/hacim/'
  5. ls -l $HOME | sed '1,10s/micah/hacim'
  6. #! /bin/sed -f
    
    1 i
    <html>
    <head><title>Converted with sed</title></head>
    <body bgcolor="#ffffff">
    <pre>
    
    s/&/&amp;/g
    s/</&lt;/g
    s/>/&gt;/g
    
    $ a
    </pre>
    </body>
    </html>
  7. #! /bin/sed -f
    
    1 i
    <html>
    <head><title>Converted with sed</title></head>
    <body bgcolor="#ffffff">
    <pre>
    
    s/&/&amp;/g
    s/</&lt;/g
    s/>/&gt;/g
    s/trout/trout</b>/g
    s/^$/<p>/g
    
    $ a
    </pre>
    </body>
    </html>
  8. You can do this in many different ways, but one of the easiest solutions is to put the dash outside of the backreference:

    cat nums.txt | sed 's/(.*))(.*)-(.*$)/Area code: 1 Second: 2 Third: 3/'
  9. #!/bin/sed -f
    
    1!G
    h
    $!d
  1. $ cat /etc/passwd | awk -F: '{print $6}'
  2. awk '{ print "Number of cell phones in use in " $1 ": " $6 }' countries.txt
  3. Note that many different answers are possible. Here's one possibility:

    BEGIN { myformat="%-15s %3s %16s %11s %12s %15s
    "
            printf myformat,
                    "Country", "TLD", "Area in sq. km", 
                    "Population", "Land lines", "Cell phones"
            printf myformat,
                    "-------", "---", "--------------", 
                    "----------", "----------", "-----------" }
          { printf myformat, $1, $2, $3, $4, $5, $6 }
  4. Note that many different answers are possible. Here's one possibility:

    {celltotal += $6; landtotal += $5 }
    END { print "Cell phones make up " landtotal/celltotal "% of landlines" }
  5. There are many different ways to do this. Here's one method:

    BEGIN { myformat="%-15s %3s %16s %11s %12s %12s
    "
            printf myformat,
                    "Country", "TLD", "Area in sq. km", 
                    "Population", "Land lines", "Cell phones"
            printf myformat,
                    "-------", "---", "--------------", 
                    "----------", "----------", "-----------" }
          { printf myformat,
                    $1, $2, $3, $4, $5, $6
            areatot += $3
            poptot += $4
            landtot += $5
            celltot += $6 }
    
    END { printf myformat,
                    "
    Totals:", NR, areatot, poptot, landtot, celltot "
    "  }
  1. The key points come from the focus on shell scripts. These include:

    • Sending data to stdout

    • Sending data to stderr

    • The exit code, or value a command can return (used in if statements)

    In addition, of course, you can add:

    • Writing to network sockets.

    • Writing UDP datagrams.

    • Creating a device driver to output directly to a device.

    • Outputting graphics. Note that with the X Window System on Unix and Linux, this is a networking operation.

    • Printing.

    Going more esoteric, you can add:

    • System V Unix shared memory

    • System V Unix message queues

    • FIFOs and named pipes

    • The Windows Event system

    Can you name any more?

  2. You can do this simply by using the following command:

    $ tail -f filename.txt >>  filename.txt

    Make sure there are a few lines in the file filename.txt at the start. Press Ctrl-C to kill the command line.

  3. cut -d: -f1,5,6,7 /etc/passwd |
        grep -v sbin |
        grep home    |
        grep sh      |
        sort         |
        cut -d: -f1,2,4 > users.txt
    
    
    awk -F':' ' { printf( "%-12s %-40s
    ", $1, $2 )   } ' users.txt
    
    # Clean up the temporary file.
    /bin/rm -rf users.txt

    In this example, the grep home filter passes only those lines that have the text home. This is another assumption, that users have home directories in /home or something similar.

  1. Note: This will work on Linux only.

    The following script shows the current process ID and then waits for you to press the Enter or Return key:

    echo "The current process ID is $$."
    echo "Press return to continue."
    read var
    When you run this script, you should see output like the following:
    $ sh exercise_09_01
    The current process ID is 12048.
    Press return to continue.

    While the script awaits the Enter or Return key, you can switch to another shell window and view /proc/12048 (the number will differ on your system).

  2. This script outputs the same data as the tick_for example script:

    echo "Using a wildcard glob in a for loop."
    cd /usr/local
    for filename in *
    do
        echo $filename
    done

    A big difference is that this script changes the directory to the /usr/local directory. The original script did not. You can get around this by saving the current directory and then using the cd command to return to that directory.

  3. Here is a script that comes out close:

    # Using expr for math.
    # Calculates sales tax.
    
    echo -n "Please enter the amount of purchase: "
    read amount
    echo
    
    echo -n "Please enter the total sales tax: "
    read rate
    echo
    
    tax_base=`expr $amount * $rate`
    
    
    tax=`expr $tax_base / 100`
    
    total=`expr $amount + $tax`
    
    result=$total
    
    echo "The total with sales tax is: $ $result."
    When you run this script, you'll see:
    $ sh exercise_09_03
    Please enter the amount of purchase: 107
    Please enter the total sales tax: 7
    
    The total with sales tax is: $ 114.
    Compare this with the math2 script:
    $ sh math2
    Please enter the amount of purchase: 107
    
    Please enter the total sales tax: 7
    
    The total with sales tax is: $ 114.49.
  1. The more you experiment, the more familiar you will become with the way functions work.

  2. While it is possible to create a function called ls, it isn't recommended, because this is an existing command and you would create an infinite loop when you ran it. The function ls would look something like this:

    $ ls () {
    ls -F --color=auto
    }

    You would call this function by typing ls on the command line. This would then execute the code block that contains ls, the shell would call the ls function, this would execute the code block in the function, and this would be repeated over and over very quickly and could cause your system to no longer respond properly.

  3. At first glance, shell functions appear to be very similar to shell aliases. However, on closer inspection you can see many differences. The most basic difference is that aliases are defined using the alias built-in command. Another difference is that you can redefine a command with an alias and you will not have an infinite-loop problem, as you did in Exercise 2. Some other differences are that aliases are simply name substitutions for existing single commands; they also do not contain multiple commands like functions can; and they do not contain logic or positional arguments. This means you cannot manipulate the $@ argument list. In shell scripts, because aliases are very limited, they are not typically used.

    Aliases were first introduced in csh and then later adopted by ksh, bash, and zsh. Most implementations of the Bourne shell do not support aliases.

  4. Here's one possible answer:

    #!/bin/sh
    #
    # This script takes at minimum one argument: the time that the alarm should go off
    # using the format hh:mm, it does only rudimentary checks that the format is
    # specified is correct. An optional second argument specifies what should be done
    # when the alarm goes off. If no second argument is supplied, a simple shell bell
    # is used.
    #
    # Be sure this bell works before you go to sleep!
    #
    # If the second argument is included and the alarm method is more than one command,
    # it will need to be enclosed in quotes.
    # First check that the required minimum arguments have been supplied, and that
    # the time is of the format hh:mm. If not exit with the proper usage.
    
    if [ $# -eq 0 ]
    then
            echo "Usage: $0 hh:mm [alarm-method]"
            echo "eg. $0 13:30 "mplayer /media/music/dr_octagon/01.mp3" "
            exit 1
    else
            alarm_time="$1"
    
            # Check that the format for the alarm time is correct, the first digit
            # should be a number between 0-2, followed by a colon, and ending with a
            # number between zero and 60. NB: This check is not perfect.
    
            if [ ! `echo "$alarm_time" | sed -n '/[0-2][[:digit:]]:[0-60]/p'` ]
            then
                    echo "Incorrect time specified, please use format hh:mm"
                    exit 1
            fi
    
    fi
    
    # Set the number of seconds in a minute
    seconds=1
    
    # Test to see if a second argument is supplied, if it is not then set the
    # bell to a shell bell. The -e argument to echo specifies that echo should
    # enable interpretation of the backslash character, and a is defined in
    # the echo(1) man page as a bell.
    
    if [ ! $2 ]
    then
            bell="echo -e a"
    else
    
            bell=$2
    fi
    
    # The wait_between_checks function sleeps for the specified number of
    # seconds and then calls the check_time function when it is done sleeping.
    # This makes the script only check the time once a minute, instead of constantly.
    
    wait_between_checks ()
  5. {
            sleep $seconds
            check_time
    }
    
    # The check_time function looks at the current time (in hh:mm format) and
    # compares it to the $alarm_time, if they match, then it calls the wakeup function
    # otherwise it goes back to sleep by calling the wait_between_checks function
    again.
    check_time ()
    {
            current_time=`date +%H:%M`
    
            if [ "$current_time" = "$alarm_time" ]
            then
                    wakeup
            else
                    wait_between_checks
            fi
    
    }
    
    # The wakeup function simply rings the bell over and over until the script
    # is interrupted.
    
    wakeup ()
    {
            echo -n "Wake up! Hit control-c to stop the madness"
            $bell
            sleep 1
            wakeup
    }
    
    # Finally the main body of the script simply starts things up by calling the
    # wait_between_checks function
    
    wait_between_checks
    #!/bin/sh
    
    recurarrg () {
      if [ $# -gt 0 ] ; then
       echo $1
       shift
       recurarrg "$@"
      fi
    }
    
    recurarrg one two three four
  1. This script runs, which makes it appear to be correct. It is not. It appears to be a script that acts similarly to the ls command. It should change to the given directory (passed as the first positional variable on the command line, $1) and then list the files in that directory. If a file is executable, it should append a *. If the file is a directory, it should append a /. This output is similar to the ls -CF command.

    This script, however, has a few things wrong, including the following:

    • The first if statement should be negated with a !. That is, if the passed-in directory does not exist, then use /usr/local. The way it reads, if the directory exists, it will execute the then-fi block. This script really should output an error message if the directory does not exist, not silently list another directory.

    • The then-fi block sets the variable directroy, not directory.

    • The cd command changes to the directory held in the variable directroy.

    • The elif condition is negated. Remove the exclamation mark.

    The following script is an improvement. The error message could be better:

    # Assumes $1, first command-line argument,
    # names directory to list.
    
    directory=$1
    
    if [ ! -e $directory ]
    then
        echo "Error: You must pass in the name of a directory."
        exit −1
    fi
    
    cd $directory
    for filename in *
    do
        echo -n $filename
    
        if [ -d $filename ]
        then
            echo "/"
        elif [ -x $filename ]
        then
            echo "*"
        else
            echo
        fi
    done
  2. This script is a front-end for a very primitive electronic shopping system. It calculates the sales tax and then checks whether the amount is larger than $200. If so, it offers free shipping.

    This script is missing two double quotes, starting with the first echo statement. The free shipping echo statement is also missing a double quote. The missing quotes should flag an error with the (yes or no) text, as this text appears to be calling a subshell.

    A corrected script follows:

    #!/bin/sh
    
    # Using bc for math,
    # calculates sales tax.
    
    echo -n "Please enter the amount of purchase: "
    read amount
    echo
    echo -n "Please enter the total sales tax rate: "
    read rate
    echo
    
    result=$( echo "
    scale=2; tax=$amount*$rate/100.00;total=$amount+tax;print total" | bc )
    
    if [ $( expr "$result > 200" ) ]
    then
        echo You could qualify for a special free shipping rate.
        echo -n Do you want to? "(yes or no) "
        read shipping_response
        if [ $shipping_response -eq "yes" ]
        then
            echo "Free shipping selected."
        fi
    fi
    
    echo "The total with sales tax = $ $result."
    echo "Thank you for shopping with the Bourne Shell."
  1. Anything that you can monitor externally would be monitored the same if called from any system or run on any system. For example, a web server can be monitored externally, with the monitoring scripts answering the question of how long it takes to retrieve a certain web page.

    As another example, SNMP MIBs are standardized. (A MIB is similar to an XML schema for SNMP data.) If a Windows system or a Unix system provides data via SNMP, you can monitor both types of systems the same way, by reading SNMP values.

  2. The quick answer is to follow the guidelines listed in the chapter:

    • Try out the commands you think will provide the data points you need.

    • Write a script to monitor the data points you need.

    • Test your script.

    • Configure MRTG to run your script and produce the output you want.

    • Test MRTG running your script.

    You may need to repeat a number of steps as you tweak how your script or MRTG should run.

    For a database system such as Oracle or Postgres, you can look into two ways to monitor:

    • Run a database-specific client program and see if it works or how long it takes to perform some operation.

    • Try a remote query of a table in the database and see how long this takes. The advantage of this approach is that you don't have to run MRTG on the same system as the database.

  3. Your answer will depend on the packages you select. Of all these packages, however, mon is very similar to MRTG in that mon is written in Perl and was designed to be extended by your scripts. These two details are very much like MRTG. MRTG focuses on drawing graphs, whereas mon wants to monitor the health of systems. Mon, for example, can page an administrator when a problem occurs.

    HP OpenView is also similar to MRTG, with the focus on using SNMP to gather data and control systems. (OpenView, however, is a whole suite of products.)

    The real goal of this exercise, however, is to see some other packages that are available and start to make choices as to which packages can help in your environment.

  1. Of course, it is more fun to talk about those dimwits. The important thing to remember is to stay focused on a few problems that are solvable. Use the techniques shown in this chapter to help guide the discussion.

  2. Some things you can use ps to do include the following:

    • Determine whether a given process is running at all. This comes from an example, so you should have gotten it.

    • List all processes owned by a given user. Desktop users should have a lot of processes. Users logged in over a network link, using ssh, telnet, and so on, should have far fewer processes running.

    • In tree mode, the ps command can report on a hierarchy of processes, such as which process begat which.

    • List the cumulative CPU time used by each process. You can find the most CPU-intensive processes.

    • List how many copies of a given process are running. Web servers often launch a number of processes.

    • On Linux, ps can output information about threads (essentially subprocesses). Enterprise applications such as Oracle, WebSphere, WebLogic, and so on, use many threads.

    See if you can come up with more.

  3. You can approach this in a number of ways. You can simply run the df command with the name of the given file system. Or you can write a script like the following:

    #!/bin/sh
    
    # Output warnings if a given file system is not mounted.
    # Oftentimes, this could be due to a network issue or
    # a hard disk failure.
    
    # Pass the name of the file system or the mount point
    # as the first command-line argument.
    filesystem=$1
    
    df "$filesystem" > /dev/null 2&>1
    result=$?
    
    if [ "$result" == 0 ]
    then
    entry=`df -k $filesystem | tail −1`
    
        # Split out the amount of space free as well as in-use percentage.
        free=`echo $entry | cut -d' ' -f4`
        in_use=`echo $entry | cut -d' ' -f5 | cut -d'%' -f1 `
    
        echo "Filesystem $filesystem is $in_use% used with $free KB free."
    else
        echo "ERROR: Filesystem $filesystem not found."
    fi
  1. The suite is called OpenOffice.org. The command that launches the suite is ooffice.

  2. A method is a macro, and a subroutine is a function. A module is like a program, and it holds subroutines and functions. A library holds one or more modules.

    Subroutines do not return values. Functions return values. This is the main difference.

  3. Try the following, using the name of your library, module, and subroutine:

    $ ooffice -quickstart 'macro:///library.module.SubroutineName("param1", "param2")'
  4. The Open Scripting Architecture

  5. do shell script

  6. osacompile

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.80.34