install Groovy in RedHat as4

官方网是这样写的:
1,first, Download a binary distribution of Groovy and unpack it into some file on your local file system
2,set your GROOVY_HOME environment variable to the directory you unpacked the distribution
3,add GROOVY_HOME/bin to your PATH environment variable
4,set your JAVA_HOME environment variable to point to your JDK. On OS X this is /Library/Java/Home, on other unixes its often /usr/java etc. If you’ve already installed tools like Ant or Maven you’ve probably already done this step.

但会出现错误:
# groovysh
java.lang.NoClassDefFoundError: org/objectweb/asm/ClassVisitor
        at groovy.lang.GroovySystem.<clinit>(GroovySystem.java:27)
        at org.codehaus.groovy.runtime.Invoker.<init>(Invoker.java:38)
        at org.codehaus.groovy.runtime.InvokerHelper.<clinit>(InvokerHelper.java:44)
        at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeNewN(ScriptBytecodeAdapter.java:225)
        at org.codehaus.groovy.tools.shell.Main.<clinit>(Main.groovy:34)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:101)
        at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:130)


解决办法:
#vi /etc/profile

加入GROOVY_HOME
export GROOVY_HOME=”/home1/software/groovy-1.5.0/”

修改CLASSPATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:”/home1/lib/”:$GROOVY_HOME/lib/ant-1.7.0.jar:$GROOVY_HOME/lib/asm-2.2.jar:$GROOVY_HOME/lib/bsf-2.4.0.jar:$GROOVY_HOME/lib/jline-0.9.93.jar:$GROOVY_HOME/lib/mx4j-3.0.2.jar:$GROOVY_HOME/lib/ant-junit-1.7.0.jar:$GROOVY_HOME/lib/asm-analysis-2.2.jar:$GROOVY_HOME/lib/commons-cli-1.0.jar:$GROOVY_HOME/lib/jsp-api-2.0.jar:$GROOVY_HOME/lib/servlet-api-2.4.jar:$GROOVY_HOME/lib/ant-launcher-1.7.0.jar:$GROOVY_HOME/lib/asm-tree-2.2.jar:$GROOVY_HOME/lib/commons-logging-1.1.jar:$GROOVY_HOME/lib/junit-3.8.2.jar:$GROOVY_HOME/lib/xpp3_min-1.1.3.4.O.jar:$GROOVY_HOME/lib/antlr-2.7.6.jar:$GROOVY_HOME/lib/asm-util-2.2.jar:$GROOVY_HOME/lib/groovy-1.5.0.jar:$GROOVY_HOME/lib/mockobjects-core-0.09.jar:$GROOVY_HOME/lib/xstream-1.2.2.jar

Your First Groovy



Your First Groovy



//hello.groovy
println “hello, world”

for (arg in this.args ) {

println “Argument:” + arg;

}

// this is a comment

/* a block comment, commenting out an alternative to above:

this.args.each{ arg -> println “hello, ${arg}”}

*/

To run it from command line



groovy hello.groovy MyName yourName HisName


Overview


Groovy classes compile down to Java bytecode and so there’s a 1-1 mapping between a Groovy class and a Java class.

Indeed each Groovy class can be used inside normal Java code – since it is a Java class too.


Probably the easiest way to get groovy is to try working with collections. In Groovy List (java.util.List) and Map (java.util.Map) are both first class objects in the syntax. So to create a List of objects you can do the following…



def list = [1, 2, ‘hello’, new java.util.Date()]

assert list.size() == 4

assert list.get(2) == ‘hello’

assert list[2] == ‘hello’

Notice that everything is an object (or that auto-boxing takes place when working with numbers). To create maps…



def map = [‘name’:’James’, ‘location’:’London’]

assert map.size() == 2

assert map.get(‘name’) == ‘James’

assert map[‘name’] == ‘James’

Iterating over collections is easy…



def list = [1, 2, 3]

for (i in list) { println i }

Once you have some collections you can then use some of the new collection helper methods or try working with closures…



Working with closures


Closures are similar to Java’s inner classes, except they are a single method which is invokable, with arbitrary parameters. A closure can have as many parameters as you wish…



def closure = { param -> println(“hello ${param}”) }

closure.call(“world!”)

closure = { greeting, name -> println(greeting + name) }

closure.call(“hello “, “world!”)


If no parameter(s) is(are) specified before -> symbol then a default named parameter, called ‘it’ can be used. e.g.



def closure = { println “hello “ + it }

closure.call(“world!”)

Using closures allows us to process collections (arrays, maps, strings, files, SQL connections and so forth) in a clean way. e.g



[1, 2, 3].each ({ item -> print “${item}-“ })

[“k1”:“v1”, “k2”:“v2”].each {key, value -> println key + “=” + value}

Note: If a given closure is the last parameter of a method, its definition can reside outside of the parentheses. Thus the following code is valid:



def fun(int i, Closure c) {

c.call(i)

}

// put Closure out of ()

[1, 2, 3].each() { item -> print “${item}-“ } // 1-2-3-

fun(123) { i -> println i } // 123

// omit ()



[1, 2, 3].each ({ item -> print “${item}-“ }) // 1-2-3-



// omit enclosing ()
[1, 2, 3].each { item -> print “${item}-“ } // 1-2-3-

// normal
[1, 2, 3].each(({ item -> print “${item}-“ })) // 1-2-3-

// using the fun function to do the same thing
[1,2,3].each {fun(it,{item -> print “${item}-“})} // 1-2-3-

def closure = { i -> println i}

//[1, 2, 3].each() closure // error. closure has been previously defined

Here are a number of helper methods available on collections & strings…



each


iterate via a closure



[1, 2, 3].each { item -> print “${item}-“ }


collect


collect the return value of calling a closure on each item in a collection



def value = [1, 2, 3].collect { it * 2 }

assert value == [2, 4, 6]


find


finds first item matching closure predicate



def value = [1, 2, 3].find { it > 1 }

assert value == 2


findAll


finds all items matching closure predicate



def value = [1, 2, 3].findAll { it > 1 }

assert value == [2, 3]


inject


allows you to pass a value into the first iteration and then pass the result of that iteration into the next iteration and so on. This is ideal for counting and other forms of processing



def value = [1, 2, 3].inject(‘counting: ‘) { str, item -> str + item }

assert value == “counting: 123”

value = [1, 2, 3].inject(0) { count, item -> count + item }

assert value == 6


In addition there’s 2 new methods for doing boolean logic on some collection…



every


returns true if all items match the closure predicate



def value = [1, 2, 3].every { it < 5 }

assert value

value = [1, 2, 3].every { item -> item < 3 }

assert ! value



any


returns true if any item match the closure predicate



def value = [1, 2, 3].any { it > 2 }

assert value

value = [1, 2, 3].any { item -> item > 3 }

assert value == false


Other helper methods include:



max / min


returns the max/min values of the collection – for Comparable objects



value = [9, 4, 2, 10, 5].max()

assert value == 10

value = [9, 4, 2, 10, 5].min()

assert value == 2

value = [‘x’, ‘y’, ‘a’, ‘z’].min()

assert value == ‘a’


join


concatenates the values of the collection together with a string value



def value = [1, 2, 3].join(‘-‘)

assert value == ‘1-2-3’

J2ME Datagram Receiver

import java.io.IOException;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;

public class DatagramReceiver {
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println(“Usage: DatagramReceiver port”);
            System.exit(1);
        }
        
        try {
            DatagramConnection receiver = 
                    (DatagramConnection)Connector.open(“datagram://:” + args[0]);
            byte[] buffer = new byte[256];
            Datagram dgram = receiver.newDatagram(buffer, buffer.length);
            for ($$) {
                dgram.setLength(buffer.length);
                receiver.receive(dgram);
                int length = dgram.getLength();
                System.out.println(“Datagram received. Length is ” + length);

                // Show the content of the datagram.
                for (int i = 0; i < length; i++) {
                    System.out.print(buffer[i” “);
                }
                System.out.println();
                
                // Send it back…
                receiver.send(dgram);
            }
        catch (IOException ex) {
            System.out.println(“IOException: ” + ex);
        }
    }
}


Timer Server

import java.io.InterruptedIOException;
import javax.microedition.io.Connector;
import javax.microedition.io.Datagram;
import javax.microedition.io.DatagramConnection;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

public class TimeMIDlet extends MIDlet
                    implements CommandListener, Runnable {

    private Display display;
    private Form addressForm;
    private Form connectForm;
    private Form displayForm;
    private Command backCommand;
    private Command exitCommand;
    private Command okCommand;
    private StringItem messageLabel;
    private TextField serverName;

    protected void startApp() throws MIDletStateChangeException {
        if (display == null) {
            initialize();
            display.setCurrent(addressForm);
        }
    }

    protected void pauseApp() {
    }

    protected void destroyApp(boolean unconditional)
                        throws MIDletStateChangeException {
    }

    public void commandAction(Command cmd, Displayable d) {
        if (cmd == okCommand) {
            Thread t = new Thread(this);
            t.start();
        else if (cmd == backCommand) {
            display.setCurrent(addressForm);
        else if (cmd == exitCommand) {
            try {
                destroyApp(true);
            catch (MIDletStateChangeException ex) {
            }
            notifyDestroyed();
        }
    }

    public void run() {
        DatagramConnection conn = null;
        display.setCurrent(connectForm);

        try {
            // Build the name string for the Connector open method
            String server = serverName.getString();
            String name = “datagram://” + server + “:” 13;
            conn = (DatagramConnection)Connector.open(name,
                                    Connector.READ_WRITE, false);

            // Build and send an empty datagram
            Datagram dg = conn.newDatagram(10);
            dg.setData(“Hello”.getBytes()05);
            conn.send(dg);

            // Receive the reply
            Datagram rdg = conn.newDatagram(512);
            conn.receive(rdg);
            messageLabel.setText(new String(rdg.getData()0, rdg.getLength()));
            display.setCurrent(displayForm);

        catch (InterruptedIOException iex) {
            display.callSerially(new Runnable() {
                public void run() {
                    Alert alert = new Alert(“No Reply”,
                        “No reply was received.\n” +
                        “Please check the server address and try again.”, null,
                        AlertType.ERROR);
                    alert.setTimeout(Alert.FOREVER);
                    display.setCurrent(alert, addressForm);
                }
            });
            return;
        catch (Exception ex) {
            display.callSerially(new Runnable() {
                public void run() {
                    Alert alert = new Alert(“Invalid Address”,
                        “The supplied address is invalid\n” +
                        “Please correct it and try again.”, null,
                        AlertType.ERROR);
                    alert.setTimeout(Alert.FOREVER);
                    display.setCurrent(alert, addressForm);
                }
            });
            return;
        catch (Error err) {
            System.out.println(err);
            err.printStackTrace();
        }
    }

    private void initialize() {
        display = Display.getDisplay(this);

        // Commands
        exitCommand = new Command(“Exit”, Command.EXIT, 0);
        okCommand = new Command(“OK”, Command.OK, 0);
        backCommand = new Command(“Back”, Command.BACK, 0);

        // The address form
        addressForm = new Form(“Network Time”);
        serverName = new TextField(“Time Server name:”“tock.usno.navy.mil”,
                                            256, TextField.ANY);
        addressForm.append(serverName);
        addressForm.addCommand(okCommand);
        addressForm.addCommand(exitCommand);
        addressForm.setCommandListener(this);

        // The connect form
        connectForm = new Form(“Sending”);
        messageLabel = new StringItem(null,
                    “Sending the datagram…\nPlease wait.”);
        connectForm.append(messageLabel);
        connectForm.addCommand(backCommand);
        connectForm.setCommandListener(this);

        // The display form
        displayForm = new Form(“Server Reply”);
        messageLabel = new StringItem(null, null);
        displayForm.append(messageLabel);
        displayForm.addCommand(backCommand);
        displayForm.setCommandListener(this);
    }
}

Developing Applications with the Java APIs for Bluetooth (JSR-82)

Developing Applications with the Java APIs for Bluetooth (JSR-82)



This paper covers the Java API for Bluetooth (JSR-82) with respect to Sony Ericsson devices. It starts by introducing the Bluetooth technology, followed by the Java APIs for Bluetooth, and how to use them.


Currently, these APIs are currently available in the Sony Ericsson P900/P908 handsets.


Click here to view “Developing Applications with the Java APIs for Bluetooth (JSR-82)”



Click here to view the Training Materials (.zip) associated with this article.


How to write a shell script

How to write a shell script
Introduction
A shell is a command line interpretor. It takes commands and executes them. As such, it implements a programming language. The Bourne shell is used to create shell scripts — ie. programs that are interpreted/executed by the shell. You can write shell scripts with the C-shell; however, this is not covered here.


Creating a Script
Suppose you often type the command
    find . -name file -print


and you’d rather type a simple command, say
    sfind file


Create a shell script
    % cd ~/bin
    % emacs sfind
    % page sfind
    find . -name $1 -print
    % chmod a+x sfind
    % rehash
    % cd /usr/local/bin
    % sfind tcsh
    ./shells/tcsh


Observations
This quick example is far from adequate but some observations:
Shell scripts are simple text files created with an editor.
Shell scripts are marked as executeable
    %chmod a+x sfind


Should be located in your search path and ~/bin should be in your search path.
You likely need to rehash if you’re a Csh (tcsh) user (but not again when you login).
Arguments are passed from the command line and referenced. For example, as $1.
#!/bin/sh
All Bourne Shell scripts should begin with the sequence
    #!/bin/sh


From the man page for exec(2):
“On the first line of an interpreter script, following the “#!”, is the name of a program which should be used to interpret the contents of the file. For instance, if the first line contains “#! /bin/sh”, then the con- tents of the file are executed as a shell script.”


You can get away without this, but you shouldn’t. All good scripts state the interpretor explicitly. Long ago there was just one (the Bourne Shell) but these days there are many interpretors — Csh, Ksh, Bash, and others.


Comments
Comments are any text beginning with the pound (#) sign. A comment can start anywhere on a line and continue until the end of the line.
Search Path
All shell scripts should include a search path specifica- tion:
    PATH=/usr/ucb:/usr/bin:/bin; export PATH


A PATH specification is recommended — often times a script will fail for some people because they have a different or incomplete search path.
The Bourne Shell does not export environment variables to children unless explicitly instructed to do so by using the export command.


Argument Checking
A good shell script should verify that the arguments sup- plied (if any) are correct.


    if [ $# -ne 3 ]; then
         echo 1>&2 Usage: $0 19 Oct 91
         exit 127
    fi


This script requires three arguments and gripes accordingly.


Exit status
All Unix utilities should return an exit status.
    # is the year out of range for me?


    if [ $year -lt 1901  -o  $year -gt 2099 ]; then
         echo 1>&2 Year \”$year\” out of range
         exit 127
    fi


    etc…


    # All done, exit ok


    exit 0


A non-zero exit status indicates an error condition of some sort while a zero exit status indicates things worked as expected.
On BSD systems there’s been an attempt to categorize some of the more common exit status codes. See /usr/include/sysexits.h.


Using exit status
Exit codes are important for those who use your code. Many constructs test on the exit status of a command.
The conditional construct is:


    if command; then
         command
    fi


For example,
    if tty -s; then
         echo Enter text end with \^D
    fi


Your code should be written with the expectation that others will use it. Making sure you return a meaningful exit status will help.
Stdin, Stdout, Stderr
Standard input, output, and error are file descriptors 0, 1, and 2. Each has a particular role and should be used accordingly:
    # is the year out of range for me?


    if [ $year -lt 1901  -o  $year -gt 2099 ]; then
         echo 1>&2 Year \”$year\” out of my range
         exit 127
    fi


    etc…


    # ok, you have the number of days since Jan 1, …


    case `expr $days % 7` in
    0)
         echo Mon$$
    1)
         echo Tue$$


    etc…


Error messages should appear on stderr not on stdout! Output should appear on stdout. As for input/output dialogue:
    # give the fellow a chance to quit


    if tty -s ; then
         echo This will remove all files in $* since …
         echo $n Ok to procede? $c;      read ans
         case “$ans” in
              n*|N*)
    echo File purge abandoned;
    exit 0   $$
         esac
         RM=”rm -rfi”
    else
         RM=”rm -rf”
    fi


Note: this code behaves differently if there’s a user to communicate with (ie. if the standard input is a tty rather than a pipe, or file, or etc. See tty(1)).
Language Constructs
For loop iteration
Substitute values for variable and perform task:


    for variable in word …
    do
         command
    done


For example:
    for i in `cat $LOGS`
    do
            mv $i $i.$TODAY
            cp /dev/null $i
            chmod 664 $i
    done


Alternatively you may see:
    for variable in word …; do command; done


Case
Switch to statements depending on pattern match


    case word in
    [ pattern [ | pattern … ] )
         command $$ ] …
    esac


For example:


    case “$year” in


    [0-9][0-9])
            year=19${year}
            years=`expr $year – 1901`
            $$
    [0-9][0-9][0-9][0-9])
            years=`expr $year – 1901`
            $$
    *)
            echo 1>&2 Year \”$year\” out of range …
            exit 127
            $$
    esac


Conditional Execution
Test exit status of command and branch


    if command
    then
         command
    [ else
         command ]
    fi


For example:
    if [ $# -ne 3 ]; then
            echo 1>&2 Usage: $0 19 Oct 91
            exit 127
    fi


Alternatively you may see:
    if command; then command; [ else command; ] fi


While/Until Iteration
Repeat task while command returns good exit status.


    {while | until} command
    do
         command
    done


For example:
    # for each argument mentioned, purge that directory


    while [ $# -ge 1 ]; do
            _purge $1
            shift
    done


Alternatively you may see:
    while command; do command; done


Variables
Variables are sequences of letters, digits, or underscores beginning with a letter or underscore. To get the contents of a variable you must prepend the name with a $.


Numeric variables (eg. like $1, etc.) are positional vari- ables for argument communication.



Variable Assignment
Assign a value to a variable by variable=value. For example:


    PATH=/usr/ucb:/usr/bin:/bin; export PATH


or
    TODAY=`(set \`date\`; echo $1)`


Exporting Variables
Variables are not exported to children unless explicitly marked.


    # We MUST have a DISPLAY environment variable


    if [ “$DISPLAY” = “” ]; then
            if tty -s ; then
     echo “DISPLAY (`hostname`:0.0)? \c”;
     read DISPLAY
            fi
            if [ “$DISPLAY” = “” ]; then
     DISPLAY=`hostname`:0.0
            fi
            export DISPLAY
    fi


Likewise, for variables like the PRINTER which you want hon- ored by lpr(1). From a user’s .profile:
    PRINTER=PostScript; export PRINTER


Note: that the Cshell exports all environment variables.


Referencing Variables
Use $variable (or, if necessary, ${variable}) to reference the value.


    # Most user’s have a /bin of their own


    if [ “$USER” != “root” ]; then
            PATH=$HOME/bin:$PATH
    else
            PATH=/etc:/usr/etc:$PATH
    fi


The braces are required for concatenation constructs.
$p_01


The value of the variable “p_01”.
${p}_01


The value of the variable “p” with “_01” pasted onto the end.


Conditional Reference


${variable-word}


If the variable has been set, use it’s value, else use word.
POSTSCRIPT=${POSTSCRIPT-PostScript};
export POSTSCRIPT


${variable:-word}


If the variable has been set and is not null, use it’s value, else use word.
These are useful constructions for honoring the user envi- ronment. Ie. the user of the script can override variable assignments. Cf. programs like lpr(1) honor the PRINTER environment variable, you can do the same trick with your shell scripts.


${variable:?word}


If variable is set use it’s value, else print out word and exit. Useful for bailing out.


Arguments
Command line arguments to shell scripts are positional vari- ables:


$0, $1, …


The command and arguments. With $0 the command and the rest the arguments.
$#


The number of arguments.
$*, $@


All the arguments as a blank separated string. Watch out for “$*” vs. “$@”.
And, some commands:
shift


Shift the postional variables down one and decrement number of arguments.
set arg arg …


Set the positional variables to the argument list.
Command line parsing uses shift:


    # parse argument list


    while [ $# -ge 1 ]; do
            case $1 in
         process arguments…
            esac
            shift
    done


A use of the set command:
    # figure out what day it is


    TODAY=`(set \`date\`; echo $1)`


    cd $SPOOL


    for i in `cat $LOGS`
    do
            mv $i $i.$TODAY
            cp /dev/null $i
            chmod 664 $i
    done


Special Variables
$$


Current process id. This is very useful for constructing temporary files.
         tmp=/tmp/cal0$$
         trap “rm -f $tmp /tmp/cal1$$ /tmp/cal2$$”
         trap exit 1 2 13 15
         /usr/lib/calprog >$tmp


$?


The exit status of the last command.
         $command
         # Run target file if no errors and …


         if [ $? -eq 0 ]
         then
  etc…
         fi



Quotes/Special Characters
Special characters to terminate words:


      ; & ( ) | ^ < > new-line space tab


These are for command sequences, background jobs, etc. To quote any of these use a backslash (\) or bracket with quote marks (“” or ”).
Single Quotes


Within single quotes all characters are quoted — including the backslash. The result is one word.



         grep :${gid}: /etc/group | awk -F: ‘{print $1}’


Double Quotes
Within double quotes you have variable subsitution (ie. the dollar sign is interpreted) but no file name generation (ie. * and ? are quoted). The result is one word.


         if [ ! “${parent}” ]; then
           parent=${people}/${group}/${user}
         fi


Back Quotes
Back quotes mean run the command and substitute the output.



         if [ “`echo -n`” = “-n” ]; then
   n=””
   c=”\c”
         else
   n=”-n”
   c=””
         fi


and
         TODAY=`(set \`date\`; echo $1)`


Functions
Functions are a powerful feature that aren’t used often enough. Syntax is


    name ()
    {
         commands
    }


For example:


    # Purge a directory


    _purge()
    {
            # there had better be a directory


            if [ ! -d $1 ]; then
     echo $1: No such directory 1>&2
     return
            fi


         etc…
    }


Within a function the positional parmeters $0, $1, etc. are the arguments to the function (not the arguments to the script).
Within a function use return instead of exit.


Functions are good for encapsulations. You can pipe, redi- rect input, etc. to functions. For example:


    # deal with a file, add people one at a time


    do_file()
    {
            while parse_one


            etc…
    }


    etc…


    # take standard input (or a specified file) and do it.


    if [ “$1” != “” ]; then
            cat $1 | do_file
    else
            do_file
    fi


Sourcing commands
You can execute shell scripts from within shell scripts. A couple of choices:


sh command


This runs the shell script as a separate shell. For example, on Sun machines in /etc/rc:


         sh /etc/rc.local


. command
This runs the shell script from within the current shell script. For example:


         # Read in configuration information
         .  /etc/hostconfig


What are the virtues of each? What’s the difference? The second form is useful for configuration files where environment variable are set for the script. For example:
    for HOST in $HOSTS; do


      # is there a config file for this host?


      if [ -r ${BACKUPHOME}/${HOST} ]; then
.  ${BACKUPHOME}/${HOST}
      fi
    etc…


Using configuration files in this manner makes it possible to write scripts that are automatically tailored for differ- ent situations.
Some Tricks
Test
The most powerful command is test(1).


    if test expression; then


         etc…


and (note the matching bracket argument)
    if [ expression ]; then


         etc…


On System V machines this is a builtin (check out the com- mand /bin/test).
On BSD systems (like the Suns) compare the command /usr/bin/test with /usr/bin/[.


Useful expressions are:


test { -w, -r, -x, -s, … } filename


is file writeable, readable, executeable, empty, etc?
test n1 { -eq, -ne, -gt, … } n2


are numbers equal, not equal, greater than, etc.?
test s1 { =, != } s2


Are strings the same or different?
test cond1 { -o, -a } cond2


Binary or; binary and; use ! for unary negation.
For example


    if [ $year -lt 1901  -o  $year -gt 2099 ]; then
         echo 1>&2 Year \”$year\” out of range
         exit 127
    fi


Learn this command inside out! It does a lot for you.


String matching
The test command provides limited string matching tests. A more powerful trick is to match strings with the case switch.


    # parse argument list


    while [ $# -ge 1 ]; do
            case $1 in
            -c*)    rate=`echo $1 | cut -c3-`$$
            -c)     shift;  rate=$1 $$
            -p*)    prefix=`echo $1 | cut -c3-`$$
            -p)     shift;  prefix=$1 $$
            -*)     echo $Usage; exit 1 $$
            *)      disks=$*;       break   $$
            esac


            shift


    done


Of course getopt would work much better.


SysV vs BSD echo
On BSD systems to get a prompt you’d say:


    echo -n Ok to procede?;  read ans


On SysV systems you’d say:
    echo Ok to procede? \c; read ans


In an effort to produce portable code we’ve been using:
    # figure out what kind of echo to use


    if [ “`echo -n`” = “-n” ]; then
            n=””;  c=”\c”
    else
            n=”-n”;     c=””
    fi


    etc…


    echo $n Ok to procede? $c; read ans


Is there a person?
The Unix tradition is that programs should execute as qui- etly as possible. Especially for pipelines, cron jobs, etc.


User prompts aren’t required if there’s no user.


    # If there’s a person out there, prod him a bit.


    if tty -s; then
         echo Enter text end with \^D
    fi


The tradition also extends to output.
    # If the output is to a terminal, be verbose


    if tty -s <&1; then
         verbose=true
    else
         verbose=false
    fi


Beware: just because stdin is a tty that doesn’t mean that stdout is too. User prompts should be directed to the user terminal.
    # If there’s a person out there, prod him a bit.


    if tty -s; then
         echo Enter text end with \^D >&0
    fi


Have you ever had a program stop waiting for keyboard input when the output is directed elsewhere?


Creating Input
We’re familiar with redirecting input. For example:


    # take standard input (or a specified file) and do it.


    if [ “$1” != “” ]; then
            cat $1 | do_file
    else
            do_file
    fi


alternatively, redirection from a file:
    # take standard input (or a specified file) and do it.


    if [ “$1” != “” ]; then
            do_file < $1
    else
            do_file
    fi


You can also construct files on the fly.
    rmail bsmtp <
    rcpt to:
    data
    from: <[email protected]>
    to:
    Subject: Signon $2


    subscribe $2 Usenet Feeder at UWO
    .
    quit
    EOF


Note: that variables are expanded in the input.


String Manipulations
One of the more common things you’ll need to do is parse strings. Some tricks



    TIME=`date | cut -c12-19`


    TIME=`date | sed ‘s/.* .* .* \(.*\) .* .*/\1/’`


    TIME=`date | awk ‘{print $4}’`


    TIME=`set \`date\`; echo $4`


    TIME=`date | (read u v w x y z; echo $x)`


With some care, redefining the input field separators can help.


    #!/bin/sh
    # convert IP number to in-addr.arpa name


    name()
    {    set `IFS=”.”;echo $1`
         echo $4.$3.$2.$1.in-addr.arpa
    }


    if [ $# -ne 1 ]; then
         echo 1>&2 Usage: bynum IP-address
         exit 127
    fi


    add=`name $1`


    nslookup < < EOF | grep “$add” | sed ‘s/.*= //’
    set type=any
    $add
    EOF


Debugging
The shell has a number of flags that make debugging easier:


sh -n command


Read the shell script but don’t execute the commands. IE. check syntax.


sh -x command


Display commands and arguments as they’re executed. In a lot of my shell scripts you’ll see


    # Uncomment the next line for testing
    # set -x


 

Open Webmail 安裝流程

Open Webmail 官方網站:http://openwebmail.org/
注意:要架設 Open Webmail 前,請務必先將 sendmail、dovecot 架設好


安裝


cd
yum -y install perl-suidperl perl-Compress-Zlib perl-Text-Iconv
wget http://openwebmail.org/openwebmail/download/redhat/rpm/release/openwebmail-2.52-1.i386.rpm
rpm -ivh openwebmail-2.52-1.i386.rpm
rm -rf openwebmail-2.52-1.i386.rpm
修改 openwebmail.conf


cp /var/www/cgi-bin/openwebmail/etc/openwebmail.conf /var/www/cgi-bin/openwebmail/etc/openwebmail.conf.bak
vi /var/www/cgi-bin/openwebmail/etc/openwebmail.conf
55行 enable_pop3 yes 修改成–> enable_pop3 no
62行 default_language en 修改成–> default_language zh_TW.Big5
85行 default_iconset Cool3D.English 修改成–> default_iconset Cool3D.Chinese.Traditional


 


76行 <default_signature>
77行 —
78行 Open WebMail Project (http://openwebmail.org)
79行 </default_signature>


#此此四行是使用者寄信的預設簽名檔,請自行修改紅字部分


 


202行 webdisk_rootpath /webdisk 修改成–> webdisk_rootpath /


修改 dbm.conf


cp /var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf /var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf.bak
vi /var/www/cgi-bin/openwebmail/etc/defaults/dbm.conf
dbm_ext .db
dbmopen_ext .db
dbmopen_haslock no


使用 Open WebMail 變更密碼的時候,順便修改 samba 密碼


cp /var/www/cgi-bin/openwebmail/etc/auth_unix.conf /var/www/cgi-bin/openwebmail/etc/auth_unix.conf.bak
vi /var/www/cgi-bin/openwebmail/etc/auth_unix.conf
13行 change_smbpasswd no 修改成–> change_smbpasswd yes


初始化


/var/www/cgi-bin/openwebmail/openwebmail-tool.pl –init
測試:https://IP/cgi-bin/openwebmail/openwebmail.pl
縮短 Open WebMail 連結網址:


vi /etc/httpd/conf/httpd.conf
ScriptAlias /mail “/var/www/cgi-bin/openwebmail/openwebmail.pl”


#在設定檔最後面加上這一行


/etc/rc.d/init.d/httpd restart
測試:https://IP/mail/
註:
參考資料:http://turtle.ee.ncku.edu.tw/~tung/openwebmail/
How to install Open WebMail on Fedora Core 3 By Thomas Chung <tchung AT openwebmail.org>
官方安裝說明檔:more /var/www/data/openwebmail/doc/readme.txt
cd /var/www/cgi-bin/openwebmail/etc/
openwebmail.conf – 主要的設定檔,管理者要設定的選項,應該都寫在這個檔案裡頭
openwebmail.conf.help – openwebmail.conf 所有選項的說明檔