bash vi mode converging with ksh

One of the great features of ksh (93 and sun's) is the option to invoke an external editor on the current command line, while preserving multi-line layout.

In vi-editing mode, the ESC-'v' keystroke invokes an external editor ${VISUAL:-${EDITOR:-vi}} on the current command line. Bash does this as well, but on exit, all newlines are replaced with semicolons, while ksh preserves them.

It's one of my minor nits with bash, but for me it's important. I like my 'one-liners' readable, even if they span half a screen... This is nice to have, as many of the script that I've written were prototyped on the command line.

Shortly after my original post I read
the bash(1) man page and found me the 'lithist' shell option.

It works of sorts, but it's not the behaviour I'm familiar with in ksh.
  • When scrolling back in history, ksh truncates long lines and lets you scroll horizontally, while bash will wrap them across multiple lines. Not bad, but counter-intuitive in vi-mode. Maybe there's another option to escape newlines.

  • After invoking vi, and re-evaluating the command line, bash returns to edit-mode. Ksh returns to the default prompt.

  • Bash specific shell options are set with 'shopt' in contrast to 'set -o ' for traditional longname options. I'm not sure why there's two methods for a similar feature, a good guess is that it prevents collisions with other shell options. It beats the csh method of storing options in shell variables.

  • Minor nit: after completion, the shell prompt command counter ( ! in posix mode ) is not incremented until an extra newline is entered. The counter then jumps by two.


Another case for CIFS and ZFS?

Microsoft has released kb/946676, detailing a problem with Windows Home Server shared folders.

When you use certain programs to edit files on a home computer that uses Windows Home Server, the files may become corrupted when you save them to the home server.
The article warns about certain applications that are not supported with shared folders. Users should copy their files to local storage before opening them with any of the suspect applications.

That basically halves the functionality of WHS, which is being touted as a NAS/backup appliance.

I wonder though, whether the problem described here is inherent to the way windows applications use their datafiles. The typical approach I remember is that applications do live updates to the original files, after making a temporary backup file. This in contrast to the traditional unix way of life, where you first create a working copy and when done use that to replace the original.

I really should build my own home NAS based on Solaris/CIFS server and ZFS next year. Let's see what kind of budget I have...

Update: It appears to be a reliability issue under heavy load, and was hard to reproduce. I claim it would not happen with NFS. That's why NFS (and any NAS) write performance can suffer badly, if you don't have the hardware to help it along.

mswhs.com UK fansite
Computerworld article


ksh93 performance through builtins - a small example

I recently held a presentation for the Dutch OpenSolaris Users Group about the work of Roland Mainz on integrating ksh93. I focused on the history of unix shells, how ksh93 was accepted in the OpenSolaris project, specifically highlighting the OpenSolaris ARC process.

I did not discuss the relative merits and reasons for getting ksh93 included, but today I'll mention one reason in particular: shell script performance. Ksh93 is faster than any other POSIX conforming shell in executing code, not in the least because many standard unix commands have been included as builtins in the shell, allowing scripts to bypass fork() and exec().

Here is a comparison of two lines of code in ksh93. Their effect is exactly the same: Ten thousand times, they create and remove a unique directory. The difference is that the second time around, the ksh builtins for mkdir and rmdir are used.

glorantha 10 $ time for i in {0..9999}; do /bin/mkdir $i; /bin/rmdir $i; done

real 0m35.63s
user 0m1.44s
sys 0m1.65s
glorantha 11 $ time for i in {0..9999}; do mkdir $i; rmdir $i; done

real 0m1.44s
user 0m0.33s
sys 0m1.09s

And this explains why a builtin matters. Both the internal and external command are just as efficient if they're only invoked once. When you have to invoke an external command inside an inner loop, the unix fork()/exec() overhead add up.

But there are other ways of improving the above bit of code, if you're satisfied with a slightly different sequence of actions, and non-POSIX code due to the compact {start .. end } notation.

What I like about this code is that it's compact, and quite clear in its intention.

glorantha 12 $ time mkdir {0..9999} && rmdir {0..9999}

real 0m0.53s
user 0m0.02s
sys 0m0.51s
glorantha 13 $ time /bin/mkdir {0..9999} && /bin/rmdir {0..9999}

real 0m0.53s
user 0m0.03s
sys 0m0.48s

More later


Document the why in your code

This article in ACM Queue reminded me of the most valuable
argument I once heard in favor of code comments.

You don't explain what the code does, you tell why it does it.

I'm all for the concept of self-documenting code, and except
for the obvious iterator i and counter n, I do try to find descriptive
names for my data structures.

The strongest argument against comments is that they can be wrong.

There's nothing as frustrating as a comment that contradicts the code.
Especially when you believe it.

So yes, comments are good, but let them tell why.