Oracle Blog

kto

Friday Dec 14, 2007

I've been trying to setup a system that could easily switch between using MKS and CYGWIN, and also run from a
Java program... what a pain.

Some of the issues I've run into:

The Windows convention of using \\ characters in pathnames is a major pain with \\ being an escape
character in most shells and in Java strings too.
Most of the time you can get away with using / instead of \\ on Windows, but the system
seems to favor the \\ character.
If you use \\ characters, depending on how many times the string is processed you might need \\\\ or \\\\\\\\ or even \\\\\\\\\\\\\\\\, how ugly is that?

Java doesn't understand /cygdrive/ or /usr/bin paths, so you have to use cygpath -m
to get the name into the 'mixed' style of C:/

Java paths like CLASSPATH and properties with paths use the Windows convention of ";" separators and the
C: or drive letter paths.

When Java starts up it primes the java.library.path property with the current directory and the paths in
the PATH variable. So depending on what is in PATH, you get a very different java.library.path setting.
Also an old unfixed bug in java gives you duplicate entries in java.library.path.
So a java process started from a cygwin shell could behave very different than being started in a
non-cygwin shell.

Spaces in paths become problematic, so using the MKS dosname -s or cygwin's cygpath -m -s is
pretty essential. But those short non-space paths on Windows could become invalid if the original directory is deleted and re-created, so if a directory could come and go, those short paths have to be constantly recreated.

The cygwin PATH variable is ':' separated cygwin paths, like any Unix system.
On Windows, and MKS, the PATH variable used ';' as a separator and the cygwin paths must be
transformed, using something like cygpath -m -p "${PATH}".

Inside shells, it's always a good idea to quote the paths, and you have to quote the Windows PATH because
it contains the ";" character, which is a shell command separator.
Doing x=${PATH} won't work if the PATH has ";" characters in it or spaces.
You end up quoting paths all the time, even using cygpath to transform a Windows PATH
you should x=`cygpath -p "${PATH}"`

Not sure exactly when and where but the shells seem to try and adjust and even add to the PATH settings
sometimes. The cygwin shells have a -l option to adjust the environment as a login shell, but
it's not entirely obvious where the profile file comes from. Comes down to "Where is HOME?" on a windows
system running cygwin. :\^(

Both cygpath and dosname only work if the directory exists.

Using the cygwin sshd doesn't guarantee the shell used when you ssh into the Windows machine.
It appears to use whatever shell is found on the System PATH setting.
Installing MKS adds MKS to the System PATH.

At this point, at least on Windows, I'm not too crazy about trying to get all these
things to work well together.
I may completely avoid shells on Windows from now on, it's like getting a lump of coal
for XMAS. :\^(

-kto

P.S. I see in a comment that I may have discouraged people from using cygwin, I did not mean to do that.
Either MKS or cygwin on it's own, or mixed with Java is very possible, heck anything is possible.
And I suspect there are other Windows Unix tool sets that would work just fine.
The problem I was having was when they all got mixed together in a process chain.
Creating a shell script that works with in either a MKS bash session and a cygwin bash session is
quite possible, and not too messy. But having these two shell processes be connected is another story.
I actually prefer cygwin even with the differences in PIDs and the pathname/PATH issues
because it seems to behave like Unix, the ps and kill seem to be reliable.
We have used MKS for a long time, and basically have been happy with it, our only issue is
that it is not free for our OpenJDK users.
So we are trying to convert to cygwin where we can, but bridging between the two at runtime is the most
difficult.