I'm sure I have typos below.  I hope the text survived the paste
process.  Please forgive.  I've already spent more time than I have to
spare on this this eve.


Greatly improved David.  Looks professional now.  Here are some problems
that I still see...


1:  Preserving argument grouping and whitespace

$@ without quotes will not preseve user-specified arguments.  Here's
an example.  "echargs" is just a program of mine that uses parentheses
to clearly show the argument groupings.  Here's my test script:

     #!/bin/sh

     echo 'Without quotes:'
     echargs $@

     echo '
     With quotes:'
     echargs "$@"


Here's a run:

     onella$ /tmp/passthru one ' ' 'thr  ee'
     Without quotes:
     (/usr/local/bin/echargs) (one) (thr) (ee)

     With quotes:
     (/usr/local/bin/echargs) (one) ( ) (thr  ee)
     onella$

You can see that echargs got the three arguments that the user supplied
only when "$@" was used.


2:  Eval

The only time eval should be run is if you need to dereference something
twice (like a shell variable set the the name of another shell variable).
The shell automatically dereferences your command-line once.  Here's
another script to show how the eval dereferences and clobbers 
user-supplied arguments.

     echo 'With eval, without quotes:'
     eval echargs $@

     echo '
     With eval, with quotes:'
     eval echargs $@

     echo '
     Without eval, with quotes:'
     echargs "$@"

Run:

     onella$ /tmp/thru2 one ' ' 'thr  ee'
     With eval, without quotes:
     (/usr/local/bin/echargs) (one) (thr) (ee)

     With eval, with quotes:
     (/usr/local/bin/echargs) (one) (thr) (ee)

     Without eval, with quotes:
     (/usr/local/bin/echargs) (one) ( ) (thr  ee)

Yes, you could probably get it to work with eval by escaping (with
quotes and/or backslashes), but why make the code ugly AND run a
command that serves no purpose at all here (eval)?  Compare the
eval in runUtil.sh with the corresponding straight-forward command:

     eval $jdkhome/bin/java $thread_flag -classpath "\"$cp\""  \
      $jargs org.hsqldb.util.$@

     "$jdkhome/bin/java" $thread_flag -classpath "$cp" $jargs \
      "org.hsqldb.util.$@"

(I also properly quoted the last arg so it will properly preserve
the user-given args as explained in the first section above.  I
also quoted the 0th arg to make it a little more difficult for
somebody to tamper with $jdkhome in order to run another program
as root).


3. Several init script problems

In some environments, it can be a big problem when init scripts
do not completely disassociate from the terminal.  If unexpected
problems come up, the bootup sequence can get stuck if the program
is not disassociated from the controlling terminal (usually the
console).  Cron jobs can hang.  Package installation scripts (like
Solaris pkg and RedHat rpm) sometimes purposefully do not supply
a tty at all.

You aren't saving stderr.

Your script does not capture any errors of the main java invocation.
When you run something in the background with &, the shell return
status indicates only if the process (java in this case) was
successfully execed.  Try this

     onella# ls /really/bad
     ls: /really/bad: No such file or directory
     onella# echo $?
     1
     onella# ls /really/bad &
     [1] 22994
     onella# ls: /really/bad: No such file or directory

     [1] + Done (1)             ls /really/bad
     onella# echo $?
     0

Notice that even though "ls /really/bad" returns an error status,
"ls /really/bad &" does not.

I suggest that you completely disassociate the program, and then
"watch" the log file to see if/when the program is successfully
started.  Since you can asynchronously monitor the log, you can
quit as soon as the daemon is fully started.  Something like


     startupfunc() {
         MAXTIME=50   # Max seconds for java to successfully start daemon

         age  /err/log/file
         age  /log/file
         java whatever <&- > /log/file 2> /err/log/file &

         (( ctr = 0 ))
         while [ $ctr -lt $MAXTIME ]; do
             (( ctr = ctr + 1 ))
             # Maybe you'd rather look for the "Listening for..." string?
             grep "^HSQLDB server .* is running$" /err/log/file  \
              > /dev/null && echo && return 0
             echo -n .
             sleep 1
         done
         echo Your error message
         return 1
     }


The age routine rotates the logfiles.  You need a virgin error log file
because you are looking for a "new" startup message.  Let me know if
you want my "age" script (it is currently in use on hundreds of
commercial production servers).


4. Exec

Wrapper scripts are an excellent place to use exec.  I recommend

     exec "$jdkhome/bin/java" $thread_flag -classpath "$cp"  \
      "$jargs org.hsqldb.util.$@"

for runUtil.sh.  If you don't use exec, you

     1:  Have a bash shell running which is entirely superfluous at
         this point.  (It can't do anything useful from now on).

     2:  Have a process in between the user and the program complicating
         signal propagation.

     3:  Have a process in between the user and the program complicating
         debugging with tools liks ps, symbolic debuggers, lsof, fuser,
         etc.


Let me know if you'd like to see a production script which uses any of
the stuff discussed above.



-------------------------------------------------------
This SF.NET email is sponsored by: AMD - Your access to the experts
on Hammer Technology! Open Source & Linux Developers, register now
for the AMD Developer Symposium. Code: EX8664
http://www.developwithamd.com/developerlab
_______________________________________________
hsqldb-developers mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/hsqldb-developers

Reply via email to