Friday, December 16, 2011

Chrome browser cookie exceptions, howto

Google's fast, new Chrome browser has a development process that seems to fix problems rapidly.

An unmet need in the user interface, however, is explicating (right on the page) how to enter domains for cookie handling exceptions.

The proper way to be secure (though you may disagree) IMHO follows:

* Wrench-Options-Under the Hood-Content Settings-Cookies.
* Select, `Block sites from setting any data'.
* Check, `Block third party cookies from being set'.
* Check, `Clear cookies and other site and plug-in data when I close my browser'.
* Click, `Manage Exceptions...'.
* Add and delete hostname patterns until you see what you like.

The problem is, it gives no subdomain examples. Per one bug report, the user cannot figure out the right syntax to enter them. Without adding the right subdomains, navigating to mysteriously redirects us in a loop.

Its unusual wildcard syntax, for Google blogging, is:


The brackets must be entered explicitly. In other words, they do not merely indicate optional content.

Some kind of, `"Learn more" about the pattern syntax' link would be awesome.

Explicitly also, one could enter all the relevant subdomains (which is appropriate for some domains):

Copyright (c) 2011 Mark D. Blackwell.

Tuesday, December 13, 2011

Lean Startup book thoughts

Have you read The Lean Startup by Eric Ries yet? good summary.


Entrepreneurs are everywhere, he says, even in large, stolid, companies -- true even of IBM! I hope they exist, where you are now. Disruptive innovation might come from competitors.


Just now, in the Amazon preview, I read the book's introduction. I see the book's epilogue: 'Waste Not'. That is so key! (to me, also).

Paraphrasing Ries: startup success, thus changing the world, is exciting. Let's not waste vision, passion and energy.


'A new kind of accounting, designed for startups.' Like any accounting, it's good for measuring categories we want to watch, like how much is devoted to experimentation on customers.


Good to have '[c]ross-functional teams ... accountable to learning milestones ... instead of [specializing people in] ... functional departments.' Good to suggest things across functions. Good to set up a Lean Startup culture and systems.


Lean Startup circle
Lean Startup at
Lean Startup Wiki

Good to connect socially with the Lean Startup people.


The book's graphs show manufacturing trending downward greatly these last ten years. With much borrowed money, he says we have been throwing our excess effort into many failed products. Hm, a recent Ries post says we are in a software development 'summer', but sometime a 'winter' will come.


'Startups exist to *learn* how to build a sustainable business.'

With 'Build-Measure-Learn', steering to the 'destination[:] creating a thriving and world-changing business.' What a good idea!

Are we developing our own companies on Lean Startup principles?


Like 'Zappos' [experiment,] ... a clear, quantifiable outcome: either a sufficient number of customers would buy or they would not.'

We might 'put [ourselves] in a position to interact with real customers and learn[.]' Right now, we could put a question on a website (and publicize it): are you (anyone browsing) interested in an app (of any kind) to do this?


He says plausible-sounding management theories, even seemingly reasonable (including legacy ones derived from manufacturing), are only as good as how well their predictions work.

Legacy practices (of 'good market research', even 'solid strategy') don't work when there is extreme 'uncertainty'. '[C]haos ... doesn't work either.'

'[N]ew product development ... routinely [and obviously now] requires ... [that which from a manufacturing perspective is] failure to plan adequately[,] failure properly to execute [the plan and a temporary] failure to deliver results ... on the way to greatness.' In other words, people (who learned the manufacturing paradigm) do resist.

Ries, quoting Scott Cook, 'Moving leaders from playing Ceasar with their thumbs up and down on every idea to --instead --putting in the culture and systems so that teams can move and innovate at the speed of the innovation system.'

Emphasizes he does not (just) do whatever customers say, interestingly, but focuses 'on what customers want (without asking them)'. That jibes with (my) experience: customers usually aren't good (naturally) doing breakthrough, useful, product imagining and creating.


'Validated learning.' 'Scientific method.' It's great to see actual science entering into business management. BTW, science in general took a long time to overcome human nature and be adopted, just as (in particular) it did in business management.

'[O]ne ... lesson ... of the scientific method: if you cannot fail, you cannot learn.'


Ries highly recommends The Four Steps to the Epiphany, 'the original book about customer development': dog-eared in his IMVU days.

Copyright (c) 2011 Mark D. Blackwell.

Thursday, December 8, 2011

One-click registration on websites belonging to phone apps

Recently, gmail passed me this advert (just for example). It is for a programming competition site that (incidentally) offers one-click registration (you know, while signed into other prestigious sites).

In most websites created for phone apps, user registration is better if it's one-click (in addition to signin). Sites (as above) do this in order to facilitate acting on impulse. (I'm not telling you anything you already don't know.)

In just two clicks (total!), users can register at the new website (even before buying the phone app) while they are skimming (or reading) posts or articles about the phone app's general topic (or smartphone technology), from a link which mentions some jazzy, new, tech feature. Generating this kind of news is something popular bloggers love to do. And it increases the phone app's mindshare.

Plausibly, in this way (huge) numbers of people would have an emotional commitment for trying-and-buying that phone app, and some would do so. If they are browsing in their smartphone, in one click they can purchase (and download) the app. Synergy! because websites are linked in ... well, a web.

People who use information aggregators (some generated by grassroots online communities, like my friend M) would (in their instream) see links to this new website, and inform their friends the same way. Thus will social synergy cause an explosive chain reaction!

One-click registration transfers (part of) the reputation of a very popular website, onto the new website.

After a person has gone through the effort of deciding to register themselves (and their personal information) on a popular website, and thus trust it, they desire also to trust (on the web) wherever else that (particular) website automatically allows them to register.

With the first website, we are in a 'community,' or have established a relationship. This leverages the natural human tendency to trust anyone referred to us, by a trusted other. Communities are a strong part of (genetically programmed) human nature.

This level of referral trust seems even to exceed the trust from (simple) hyperlink clicking. Perhaps what is called, 'cognitive dissonance' also plays a part.

Copyright (c) 2011 Mark D. Blackwell.

Friday, December 2, 2011

Webmaster gallery

I made a picture gallery application for webmasters who use plain-vanilla web-hosting services (particularly those with cPanel).

The webmaster uploads pictures, thumbnails and CSS to a directory, then runs the app in order to create and modify the picture descriptions. It handles later uploaded pictures just as well.

It has been installed and run successfully (using cPanel).

An art gallery (of the app's first client) is visible (actually the static pages generated).

It is written in Rails 3.

Copyright (c) 2011 Mark D. Blackwell.

Thursday, November 17, 2011

Bach-Lehman (and Young #1) using electronic tuner, howto

Here's how to use an electronic tuner to tune a harpsichord in Bradley Lehman's Bach temperament, as well as Thomas Young's. They sound so much better than equal temperament (even better than Vallotti)--everyone should try them!

I found Lehman-Bach instructions (taking Vallotti as a starting point) in the section, `Easy way to tune it accurately and mostly electronically' (search for it) of his homepage.

Yet, there is another way. His section, `Electronic device instructions for the Bach' at the bottom
of `Practical temperament instructions by ear' also recommends we, `See the interesting method by David Hitchin', who says his method is useful if one has the `Korg-OT12 or a similar tuner which provides for ET and the Pythagorean, Werkmeister III and Vallotti temperaments.'

Dr. Lehman says the Thomas Young temperament he recommends (Young #1) `is not the more familiar "Young #2"; it is his first and better one...entirely symmetrical, and very simple...Young's #2 [the worse one] is technically [just] a transposition of the entire VALLOTTI temperament upward by a 5th.'

I found these instructions in the `YOUNG #1 1799/1800' section of his `Practical temperament instructions by ear':

1. Tune all of VALLOTTI first.
2. Nick F downward slightly so it's equally tempered between C and Bb.
3. Nick B upward slightly so it's equally tempered between E and F#.

Copyright (c) 2011 Mark D. Blackwell.

Monday, November 14, 2011

Text-label your measures in LilyPond with YAML

Some music (especially some choral music) is somewhat irregular of measure length. Naturally with this kind of music, while entering (and editing, following one's musical sense), often measures will join or split. Then half of the measure numbers are thrown off. This is especially true of early music, and recent music whose source documents were prepared somewhat in a free way.

Often, given multiple voice parts (or instruments), each, for various purposes, necessitates several source files in parallel (if working in LilyPond): such as for adjustments to piano or organ reductions. Many features not yet done (completely and automatically) well by LilyPond necessitate these additional parallel files.

Whenever information is parallel, it requires careful synchronizing of all the measures (and measure lengths). What a bother!

Obviously, if humans are checking and synchronizing something (with difficulty), this is a good opportunity for computers to do the work instead. In that situation, I wrote a computer program allowing measures to be labeled by (text) strings, instead of (only) by measure numbers.

The program fills each measure (completely) with spacer rests (unless told otherwise). This eases synchronization, because you need only include measures with actual content.

The program uses YAML as its data entry format. YAML's noise (the extra characters you enter) is very spare. It seems cleanest for entering LilyPond source (it interferes only minimally) yet allows measures to be labeled easily by text strings.

Available on my GitHub (and written in Ruby), the program is called, 'yaml2lilypond'. Recently, I successfully used it to engrave (typset) a large work--and it helped a lot!

Copyright (c) 2011 Mark D. Blackwell.

Saturday, November 12, 2011

Lean startup

Recently, a project owner I know read with interest the new book, The Lean Startup: How Today's Entrepreneurs Use Continuous Innovation to Create Radically Successful Businesses, by Eric Ries. It just came out September, 2011; his blog is Startup Lessons Learned. Web searching for "lean startup" found:

From `Taking the guesswork out of startup success' (by Anne Fisher):

`“[S]tart...with a very basic, sloppy site, and...continually change it according to what users tell [you] they like and don’t like.” [E]very single week[,] invite customers in, plunk them down in front of computers, watch them use the site, and ask them questions about it. The (often surprising) answers then get built into the product.'

From Jeff Shuman's comment #40 in `Teaching a “Lean Startup” Strategy' (by Carmen Nobel):

`In Peter Drucker's 1985 book Innovation and Entrepreneurship, he noted that “When a new venture does succeed, (more often than not) it is in a market other than the one it was originally intended to serve, with products or services not (quite) those with which it had set out, bought in large part by customers it did not even think of (when started), and used for a host of purposes besides the ones for which the products were first designed.”'

From `Four myths about the Lean Startup' (by Eric Ries):

`Lean not blindly do what customers tell them, nor do they mechanically attempt to optimize numbers. They use...actionable analytics as vehicles for to make their vision successful.'

From `Top 5 myths about the lean startup' (by Eric Ries):

`Lean startups are driven by a compelling vision, and they are rigorous about testing each element of this vision against reality...with every tool available...They use customer development, split-testing, and in-depth analytics as vehicles for learning about how to make their vision successful. Along the way, they pivot away from the elements of the vision that are delusional [emphasis added].'

`Lean...refers to a process of building companies and products based on lean manufacturing principles, but applied to innovation. That process involves rapid hypothesis testing, learning about customers, and a disciplined approach to product development.'

`[A] startup is [any] human institution creating a new product or service under conditions of extreme uncertainty.'

From Brian Mcfarlane's comment:
`getting out from behind you[r] computer and talking to real people will reward you with unresolved problems you may not of thought of to help you get to a product-market fit sooner.'

From `The Promise of the Lean Startup' (by Eric Ries):

`In parallel to [the] work by the “solution team”...there is a new kind of “problem team”...that is asking the bigger questions, such as: Who will our customers be? What problem does our product solve for them? How many of them are there? And how will we reach them?'

`The promise of the lean startup is that instead of building our companies according to myths, we can guide them with facts and the knowledge required to use those facts well. Or put another way, that we won’t waste our time building products or services that nobody wants.'

`The ultimate goal of a lean startup is to identify where its vision intersects with what reality can accommodate...It tries out new ideas with a fraction of customers in order to prioritize using facts, not opinions. Its unit of progress is that of validated learning about its customers. [Thus] the practice of entrepreneurship can be put on solid, rigorous, footing.'

`Instead of seeing process as a synonym for bureaucracy, it sees it as a synonym for discipline. Focusing all of its energy on only those activities that matter, it frees up time and energy for true productivity.'

Other references:
Why Lean Startups are Hard Part 1 – Our Genes Aren’t Lean - Kevin Dewalt
Perfection By Subtraction – The Minimum Feature Set - Steve Blank

Copyright (c) 2011 Mark D. Blackwell.

Wednesday, November 9, 2011

IPv6 aware, Linux iptables cloud hand-firewall for Debian lenny, howto

Recently, I set up a Linux software firewall by hand for a virtual machine instance running Debian lenny.

Reasonable, now or in the future, is concern about IPv6 traffic. 'Is your firewall aware?' speaks of some danger: 'You might think that [using iptables to] disallow incoming connections to your server on port 22[,] except from a single trusted IP[,] is sufficient to stop connections hitting your machine, but if it is accessible over IPv6 you'll soon discover this isn't the case.'

Many VM providers have not so far (completely) enabled IPv6. However, for anyone who has written their own firewall script, it is a good idea to be prepared beforehand for the event.

The latest VM's, running on recent kernels, can use regular, IPv6-capable firewalls, though they are somewhat hard to find. For instance, the Debian package, 'shorewall6' implements an IPv6 firewall, which 'requires kernel 2.6.24 or later'. Per their FAQ, 'Linux kernels before 2.6.20 didn't support connection tracking for IPv6'.

My particular VM provider allows me only kernel 2.6.18. So, for my old kernel, I developed a fairly simple firewall script, with goals to:

* Restrict sole use of my VM to a list of authorized, remote IP's
* Block tunneling of IPv6 through IPv4, inbound and outbound
* Ease establishing the same rules for IPv6 as for IPv4
* Learn more about iptables firewalls, and
* Learn something about IPv6

This modular firewall script allows full and easy control over IP addresses, protocols and ports. It was derived, with additions, from James Turnbull's 'Bastion Host Iptables Script' (see References).

In order to simplify, it leaves out denial of service (DOS) protection, because that seems unlikely in casual VM use. And, it assumes your VM's IP address is IPv4.

It is impossible accidentally to be locked out, because VM providers naturally offer direct console access, independent of services running on the VM.

The script is available free of charge from my GitHub account.

Bastion Host Iptables Script: Appendix A (or chapter 2) of James Turnbull's book, _Hardening Linux_. For download, see


6in4 - Wikipedia
6to4 - Wikipedia
Adding proper IPv6 to my home network - Martin F. Krafft
After installation - Securing Debian manual - Debian
Anything in anything - Wikipedia
Basic iptables - howtos - 5dollarwhitebox
Basic iptables - Debian/RedHat (see comments) - HowToForge
Collection of basic Linux firewall iptables rules - LinuxConfig
Debian firewall - Debian
Druidic firewall - I)ruid
Easy firewall generator for iptables - Scott Morizot
Entries in /proc/sys/net/ipv6/ - Linux IPv6 howto - TLDP
Firewalling with netfilter/iptables - Shane Tzen
Firewalls - Debian
Firewalls resources - Center for Education and Research in Information Assurance and Security (CERIAS)
Firewalls tag - DebianAdministration
Getting IPv6 connectivity under Linux - Juliusz Chroboczek
Guidelines for firewall vendors regarding MIPv6 traffic - Internet Engineering Task Force
Internet firewalls: frequently asked questions- Paul D. Robertson, et al
The Internet is a dirty, dirty mistress - Dustin D. Trammell
Invisible IPv6 traffic poses serious network threat - Carolyn Duffy Marsan - Network World
Ip6tables: IPv6 firewall for Linux - Vivek Gite
Iptables - Wikipedia
Iptables(8) - Linux man page - Linux
Iptables firewall - Thomas Pircher - TTY1
Iptables firewall script & configuration files for Linux 2.4.x-2.6.x - Bob Sully
Iptables/firewall setup for clusters - Richard Benson - Dixcart
Iptables howto - Community documentation - Ubuntu
Iptables rules - TheGeekStuff
Iptables tag - DebianAdministration
Iptables tutorial - Oskar Andreasson - Frozentux
IPv6 - Wikipedia
IPv6 & Linux howto - Peter Bieringer
IPv6: Configuration for Debian - lenehan
IPv6 firewalling -
IPv6 firewalls - GetIPv6
IPv6-ready kernel - Linux IPv6 howto - TLDP
IPv6 security considerations and recommendations - Microsoft
IPv6 with Debian - Martin F. Krafft
Is your firewall IPv6 aware? - Debian administration - Steve Kemp
ISATAP - Wikipedia
Learn how to use IPp6tables - TLDP
Links2World howto - Links2World Firewall
Linux 2.4 packet filtering howto - Rusty Russell
Linux iptables avoid IP spoofing & bad addresses attacks - LinuxTitli
Linux iptables block common attacks howto - LinuxTitli
Linux iptables: how to specify a range of IP addresses or ports - Vivek Gite
Linux: IPv6 - Peter Bieringer
Linux IPv6 howto - TLDP
List of IP protocol numbers - Wikipedia
Local area network - Wikipedia
Miredo(8) - Linux man page - Linux
Restoring iptables automatically on boot - Jawnsy - DebianAdministration
Running IPv6 in practice - Gribozavr - DebianAdministration
Securing network access - Securing Debian manual - Debian
Set up Ubuntu server in the cloud howto - dambrosio
The settings statement - Links2world Firewall
Shorewall firewall installation, configuration & understanding - Stephen P. Edwards
System run levels and init.d scripts - Debian
Teredo may render your firewall useless - René Pfeiffer
The Teredo protocol: tunneling past network security & other security implications (PDF) - James Hoagland - Symantec
Teredo tunneling - Wikipedia
Top 5 best Linux firewalls - Ramesh Natarajan - TheGeekStuff
Using iptables to secure your virtual machine - Cloud hosting applications - eApps
Why you want IPv6 - LinuxReviews

Copyright (c) 2011 Mark D. Blackwell.Copyright (c) 2011 Mark D. Blackwell.

Tuesday, October 25, 2011

Upgrade Xen VM Debian from sarge to lenny, howto

Here's how to upgrade a Debian Linux distribution to 'lenny', on a cheap Xen VM plan such as's, which (of Debian) offers only version 3.1 ('sarge').

Upgrading to Debian 'squeeze' is inadvisable on TekTonic (until they offer an upgraded Linux kernel); please see my experimental blog post.


I used Tektonic's shell access (through SSH), without logging in further to the account, 'root'.

One cannot change the date or time (apparently, as a DomU) under Xen. The command, 'date' appeared to work, but the time wasn't actually changed:

$ date --set=HHMM

My CPU is a 32-bit, dual-core AMD Opteron 242 (per, '/proc/cpuinfo').


First, upgrade within sarge, per '[Sarge] upgrades from previous releases', '[Etch] upgrading your sarge system' and 'Distribution archives':

$ mkdir /root/upgrade
$ script -t 2>/root/upgrade/sarge-to-sarge-latest.time -a /root/upgrade/sarge-to-sarge-latest.script
$ cd /

Edit (see the command, below):
1. Make sure the word, 'stable' is not in there. (If it is, change it to, 'sarge'.)

2. Change to .

3. Comment out (with a leading '#', or remove) the line.

4. Comment out the line.

$ nano /etc/apt/sources.list

Here is the desired result:

deb   sarge main contrib non-free

Do this twice, to see error messages go away:

$ aptitude update


$ aptitude install aptitude
$ aptitude -f upgrade
$ exit

One should see the message, 'File is /root/upgrade/sarge-to-sarge-latest.script'.


Next, upgrade from sarge to etch, per 'Upgrades from previous releases' and 'Upgrading the rest of the system':

$ script -t 2>/root/upgrade/sarge-to-etch.time -a /root/upgrade/sarge-to-etch.script

Edit, changing 'sarge' to 'etch':

$ nano /etc/apt/sources.list

Twice fetch the new list:

$ aptitude update


$ aptitude install aptitude
$ aptitude upgrade
$ aptitude install initrd-tools
$ aptitude --download-only dist-upgrade
$ aptitude dist-upgrade
$ exit

One should see the message, 'File is /root/upgrade/sarge-to-etch.script'.


Next, upgrade from etch to lenny, per 'Upgrades from previous releases':

$ script -t 2>/root/upgrade/etch-to-lenny.time -a /root/upgrade/etch-to-lenny.script
$ dpkg --audit
$ dpkg --get-selections | grep hold
$ aptitude search "~ahold" | grep "^.h"

1. Change 'etch' to 'lenny'.

2. Change, '' to, ''.

$ nano /etc/apt/sources.list

Fetch the new list:

$ aptitude update

To fix an error saying, 'public key is not available':

$ aptitude install debian-archive-keyring
$ aptitude install aptitude apt dpkg

Make a request (in order to start aptitude working):

$ aptitude search "?false"


$ aptitude update
$ aptitude --download-only safe-upgrade

Thrice, till nothing changes:

$ aptitude safe-upgrade


$ aptitude --download-only dist-upgrade
$ aptitude dist-upgrade


Updates & backports - Debian Reference -
Debian volatile replaced by new updates suite - News -

1. Uncomment and change the security line (use '/', not '-'):

deb   lenny/updates main contrib non-free

2. Add post-release updates:

deb   lenny/volatile main contrib non-free

$ nano /etc/apt/sources.list

Fetch the new list:

$ aptitude update

Repeat till nothing changes:

$ aptitude safe-upgrade

Remove a now-unused, old file:

$ rm -i /etc/network/options


$ exit

One should see the message, 'File is /root/upgrade/etch-to-lenny.script'.


Back up:

$ dpkg --get-selections "*" > /root/upgrade/dpkg-get-selections.txt
$ cd /
$ mkdir /backup
$ mkdir /backup/full
$ tar --create --one-file-system --file=/backup/full/upgraded-to-lenny.tar bin boot etc home lib opt root sbin selinux usr var/lib/apt/extended_states var/lib/aptitude/pkgstates var/lib/dpkg
$ cd /backup/full
$ gzip --best upgraded-to-lenny.tar

Shut down:

$ shutdown -h now

One must, on HyperVM, also click, 'shutdown' in order for its File Manager to see any files. Navigate (in it) to, '/backup/full' and click the icon under, 'Dn' to offload the corresponding, '.gz' file, made by gzip.

Copyright (c) 2011 Mark D. Blackwell.

Wednesday, September 28, 2011

Node.js frontend to Rails

I have an intuition that Node.js can fruitfully front-handle user web requests, then pass them to Ruby/Rails, when doing this:

* In the case that processing requests (from users) requires collecting information from elsewhere, like various web service APIs (very common, now!).

Node.js would handle the (long) event queue thus generated, then send HTTP requests to Ruby/Rails, forging the sender in the header like the users'.

Then, Ruby/Rails won't block for very long, only long enough for the database.

Node.js could put the info anywhere, like the URL or in a fast database.

Copyright (c) 2011 Mark D. Blackwell.

Monday, September 26, 2011 user data insecure

I've just signed up (again) to, and noticed that Dice only checks the first 8 password characters.

There is no description of a Dice password on the site, I believe.

However, a good feature is that Dice passwords can contain:
* Special characters like ! $ % & (etc., except backticks `)
* Bracket characters like ? [ ] { } ( ) < > (etc.)
* Underline and minus: _ -

in addition to the (more) usual digits and to distinguishing upper- and lower-case letters.

Using these, (Keepass informs me) Dice attains '53 bits of [password] quality,' which is not very much, in addition to a certain cleartext sniffing problem (see below).

But who cares?

EDIT: Dice confirmed they only use the first 8 characters of the password. They also pointed out (correctly) that their login form has an action which is https, so it normally uses SSL encryption.

However, some people say that corporate or other sniffers can see, block, rewrite (using Perl or something) and resend to a Dice user the packets in their login page as Dice sends it out unsecured, making its form action contain (sometimes) another address, other than the https address their software intends!

When the form is submitted (to the wrong address) they can see the Dice username or email, and the password. Then they can log into Dice using these credentials, and see whose resume it really is. If they want to.

They say some banks even have this problem!


Copyright (c) 2011 Mark D. Blackwell.

Thursday, September 22, 2011

Learn You a Haskell for Great Good!

Following is a note I wrote to the author of a wonderful book:

Hi, Miran Lipovača,

Thanks for your wonderful, _Learn You a Haskell for Great Good!_. Just now, I am resuming reading it, after completing a project (in another language).

For many people, it is important to be refreshed by beauty, as of mathematics in your book!

Copyright (c) 2011 Mark D. Blackwell.

Friday, September 16, 2011

Meantone tuning systems

As you may know, interestingly, the tuning systems called quarter (1/4) and sixth (1/6) comma meantone differ, not only in their fractions, but also because their two commas (from which they calculate the fractions) are of different sizes (albeit somewhat close). To wit:

The comma in 1/6-comma meantone has one size (the well-known difference between 12 pure fifths and 7 octaves: about 23.46 cents: called the Pythagorean comma), per:

However, the comma in 1/4-comma meantone has another size (it is the difference between four pure fifths, C-G-D-A-E and two octaves, plus a pure major third, C-C-C-E: about 21.51 cents: called the syntonic comma). In other words,

'The syntonic comma... is the difference between four justly tuned perfect fifths, and two octaves plus a justly tuned major third', per:

Interesting (linguistically, furthermore) is that 'mean-tone' is so-called, precisely because in that system, as you may remember, any major second (a 'tone') is found to be the 'mean' (the ordinary average, logarithmically) between the two notes of whatever size of major third it is we have, per p. (?) of Ross W. Duffin's _How Equal Temperament Ruined Harmony_.

The interesting, following book quotation admittedly differs in meaning from the Wikipedia article, quoted next following.

'[The] ratio between the major [whole] tone [is] 9:8 and the minor [whole] tone [is] 10:9[.] In meantone temperaments, the major and minor tones are made equal. In Pythagorean tuning, the minor tone is replaced by the major tone of 9:8. In quarter-comma meantone, the major and minor tones are made equal to the square root of 5:4.

'In the previous, Pythagorean tuning, a major third was 5:4 (C3 to E3 in the harmonic series, based on the piano note, C1) and there were two whole tones. The major semitone was 9:8 (C4 to D4) and the minor semitone was 10:9 (D4 to E4). These two semitones are not the same size.

'In any mean-tone tuning, however, these two semitones are averaged. This means that the two semitones have the same size, of 1/2 * sqrt( 5). This means that equal-temperament is a mean-tone tuning. Also, at first, people were rather shocked when the irrational square root of five disrupted the mathematically pure, small-whole number world of musical consonance.'

Now, for the Wikipedia article:

'In general, because the two semitones can be viewed as the difference between major and minor thirds, and the difference between major thirds and perfect fourths, tuning systems that match these just intervals closely will also distinguish between the two types of semitones and match their just intervals closely', per:

Another interesting and relevant Wikipedia article is:

Copyright (c) 2011 Mark D. Blackwell.

Sunday, August 28, 2011

SoundCloud promotes your music compositions

Recently, I discovered a nice website, SoundCloud which promotes (aurally, visually and socially) music that you compose.

Or, you can use it to play a stream of compositions, by typing tags and search words.

I searched for tag, 'classical', and keyword, 'experimental', and the resulting hits sound pretty nice!

It's been out since 2007: recently 5 million registered users.

Copyright (c) 2011 Mark D. Blackwell.

Wednesday, August 24, 2011

Cygwin, Git Bash and native Windows apps, howto

I use Debian and Windows XP — the latter sometimes on a netbook, but principally on a fast desktop computer (it has a nice monitor). On Debian, I develop software in the normal way. But, when I'm on Windows, I have to resort to a variety of techniques.

On a fast desktop computer, I use many native Windows apps (e.g. 7-Zip instead of Tar with compression; in the Windows way). I use Cygwin apps where a good native Windows version is lacking.

For example, previously I ran Cygwin's LilyPond till I noticed the niceness of the Windows version.

But mostly on Cygwin I enjoy the Bash command line interface and its filesystem.

My desktop's Git is through Cygwin, but the netbook has msysGit (with its own version of Bash). (Msysgit is also known as Git Bash.)

Within msysGit, so far, Bash's symbolic links aren't good — if you make one, it actually copies the whole folder!

I could try alternatives (suggested on MinGW's MSYS page) such as Interix (also known as Microsoft's SFU or SUA).


In order to maintain only one copy on the desktop of things like SSH keys (used by Git) I followed instructions to move my Cygwin user home directory to the same place as my Windows user home directory — which worked just fine! (Additionally, I set LANG to en_US.UTF-8, as suggested.)

Now, this command works just fine for me:

ruby app/hello.rb

I seem to recall that, for a while, it gave me an error, 'no such file'. Perhaps when I cleaned and upgraded my Cygwin installation (including my .bash* files) and then did a couple of reboots, the problem went away. (Don't you hate that?)

Cygwin can run both Cygwin apps, and native Windows apps. For speed and maintainability reasons, it's good to minimize the programs installed into Cygwin, doing so only if no native Windows version will succeed there (or can conveniently be run outside it). For example, my RubyGems installation is a native Windows one.

In Cygwin, the command, 'rake' (e.g.) might give you:

No such file or directory -- /cygdrive/c/progra/ruby/1.8.7-p352/bin/rake (LoadError)

even though it is found by, 'which rake':


The solution (in Cygwin) is to type, 'rake.bat' (gem.bat, irb.bat, pik.bat, etc.).

If desired, you can alias rake, gem, irb and pik as with Robert Wahler's Stack Overflow answer, but just on the command line — it doesn't normally work in Bash scripts. (E.g., 'alias rake=rake.bat' — to reverse it: 'unalias rake'.)

If you are having problems with native Windows programs still not finding files in Cygwin, you might want to look at one aspect of Cygwin filesystems (some sources say) which requires special handling.

The documentation says passing filesystem paths (in Cygwin Bash) to native Windows apps (such as Ruby) is done (although sometimes I need to) in one of two ways:

One is to use native 'Win32' paths — two examples follow, for which I made a Ruby test program ('app/hello.rb' containing only, 'p __FILE__'). They require at least one, escaped backslash:

In (Cygwin's) current directory (using native Win32 paths):

ruby '.\hello.rb'
ruby .\\hello.rb

Or in 'app', relative to the current directory:

ruby 'app\hello.rb'
ruby app\\hello.rb

The other is to use cygpath:

In the current directory (add, '-a' for the full path):

ruby "`cygpath -m hello.rb`"

Or in the relative directory, 'app' (recently, with one long path, I had to do it this way):

ruby "`cygpath -m app/hello.rb`"


Developing with both msysGit and Cygwin normally generates Unix permissions problems. Their Gits flip-flop the permission bits between '100777' (Cygwin) and '100644' (msysGit) on most files! Those with certain typically-executable extensions like .exe and .bat alternate between '100777' (Cygwin) and '100755' (msysGit).

To avoid most of this problem, you can mount your Cygwin user home directory in a way close to the msysGit method:

/cygdrive/c/Documents\040and\040Settings/[user name] /home/[user name] ntfs binary,noacl,bind 0 0

'noacl' tells Cygwin not to use the Access Control Lists found in Microsoft's NT tree. (BTW, as of Cygwin 1.7.9-1, 'posix=1' and 'nouser' are ignored here.)

The exception is that Cygwin will look for '#!' at the beginning of files to set the executable bit; msysGit, as mentioned above, will look at extensions like .exe and .bat.

In a development project, it might be useful to set write- and execute-permissions (at least the 'user' bits). If you want to manipulate permission bits further in your repository, you can tell msysGit (or even Cygwin Git) to ignore permission bit differences. Then you can set (see Jakub Narębski's answer) the (user?) execute bits:

git update-index --chmod=+x [file paths]

and reset them:

git update-index --chmod=-x [file paths]

before you do, 'git commit'.

(Tested with Ruby 1.8.7 (2011-06-30 patchlevel 352) [i386-mingw32], Cygwin 1.7.9-1.)

BTW, to see what Cygwin version you are running:

cygcheck -c cygwin


file modes - Cygwin
NT Security - Cygwin
file modes - msysGit

Copyright (c) 2011, 2015 Mark D. Blackwell.

Saturday, August 13, 2011

BASH (GNU shell for Unix) cheat sheet

While using the command-line shell, BASH (for Unixen, part of GNU (GNU's Not Unix), developed by FSF (Free Software Foundation), quite popular and superior), for a long time I employed just a few of its manipulation features for command lines -- just these, in fact:
!$ - last command's last argument
(C-r) - reverse search, through command history

Recently, I have wanted to combine multiple arguments from multiple commands. To help me remember how, I used the technique of making a cheat sheet. Interestingly, BASH is similar to the text editor, Emacs (as well as Nano). Here is a sample:

Key abbreviations:
(C-) - Ctrl
(M-) - Alt
(newline) - Enter
(rubout) - Backspace

Move the cursor:
(C-a) - beginning-of-line
(C-e) - end-of-line
(M-f) - forward-word
(M-b) - backward-word

Change text:
(M-t) - transpose-words

Kill and yank:
(C-k) - kill-line
(C-x rubout) - backward-kill-line
(M-d) - kill-word
(C-y) - yank

(tab) - complete
(M-/ M-/) - complete-filename
(M-g) - glob-complete-word
(M-?) - possible-completions
(C-x /) - possible-filename-completions

(C-_) - undo

Event designators:
(!-2) - command previous to last
(!-2:1-2) - second previous commands's first and second arguments
(!-2:0 !:3* !-2:2) - second previous command word plus its second argument, the last command's third and following arguments intervening

There's more on GitHub.

Copyright (c) 2011 Mark D. Blackwell.

Monday, August 8, 2011

CSS selector objects and methods for testing in Ruby

Let's say, for a given web page, you are writing some tests. And, supposing, you want to test whether the page contains a single DIV, of CSS class, 'only'.

And, you want to know whether the DIV (or the page) contains a single FORM, of CSS class, 'good-form'.

And further, you want to know whether the FORM (or the page) contains (among other things) a single INPUT, of CSS class, 'my-input'.

And further, whether that INPUT has CSS attribute, 'type=text'.

So, a CSS selector, useful for finding that on a web page, would be:

    div.only > form.good-form > [type=text]


Maybe (in your test) specifying descendents instead of children would have a better flexibility, allowing later intervening DIV's (for instance). With this difference, the new CSS selector would be:

    div.only  form.good-form [type=text]

How might one like to specify these selectors, speculatively and ideally? Even better than the CSS selector strings in Ruby above might be... what?

(A.)   HTML elements

Well, it might be nice if code for DIV's could work simply like this:

    D.class 'only'

(Unfortunately, this would clobber Object#class, probably interfering with essential Ruby functionality elsewhere in our application.) We could compromise and give it a longer method name:

    D.css_class 'only'

(B.)   HTML Attributes

A web page might also, in addition to an INPUT element carrying all of the desired attributes, supply some other INPUT with fewer of them, or indeed another kind of INPUT entirely.

So, obviously, it is good to test for:

o The desired number of INPUT's (in total), and
o The presence of each INPUT, carrying all the attributes desired.

In light of this, wouldn't it be nice if one easy method invocation could assert the unique presence of exactly one INPUT, plus its unique presence carrying a specific set of attributes?

Another thing possibly useful might be checking the attributes one at a time; I don't know.

The same would probably apply also to any other kind of HTML element having attributes.

A seemingly good way to invoke the method would be:

    attribute 'type', 'text', 'value', 'your name here'

And, for unpaired attributes:

    attribute 'hidden'

So: how could these semantics really work? Here's an example, carrying the idea further:

(C.)   An implementation

# Fuller Example of Web Page Testing, Using CSS Selector Objects and Methods:

module CssSelectorConstants; D,F,I = %w[ div form input ].map{|e| CssString e} end

class SomeTestClass

    extend CssSelectorConstants

    def test_web_page
        d_o = D. css_class 'only'
        fg = d_o.descend(F).css_class 'good-form'
        im = fg. descend(I).css_class 'my-input'

        a_t = im.attribute 'type', 'text'
        atv = im.attribute 'type', 'text', 'value', 'your name here'
        av = im.attribute 'value', 'your name here'

# There should be exactly one DIV, 'div.only':
        assert_select d_o, 1 do

# And within that, exactly one FORM, 'form.good-form':
            assert_select fg, 1 do
#                                                                         I.e., exactly one:
#                                                                                   div.only form.good-form

# And within that, exactly one INPUT, '':
                assert_select im, 1
#                                                                         I.e., exactly one:
#                                                                                   div.only form.good-form

# And exactly one INPUT, '[type=text]':
                assert_select a_t, 1
#                                                                         I.e., exactly one:
#                                                                                   div.only form.good-form
#                                                                                   [type=text]

# And exactly one INPUT, '[value=your name here]':
                assert_select av, 1
#                                                                         I.e., exactly one:
#                                                                                   div.only form.good-form
#                                                                                   [value=your name here]

# And exactly one INPUT, '[type=text,value=your name here]':
                assert_select atv, 1
#                                                                         I.e., exactly one:
#                                                                                   div.only form.good-form
#                                                                                   [type=text,value=your name here]
            end #form
        end #div
    end #def
end #class

See also:
CSS selector objects & methods (for Rails; GitHub)

Copyright (c) 2011 Mark D. Blackwell.

Wednesday, July 27, 2011

Open letter re: error in my post

I sent this letter to a friend, but others might find it interesting. [Elided name for privacy -- the letter starts ...] Hi!

Thanks again for (verbally) informing me that I misspelled Brandenburg in a post.

As George Soros (left-wing hedge fund owner and subsequent philanthropist) says, learning we have made a specific mistake causes joy and hope, because this knowledge is an opportunity to improve future outcomes. :)

It's been a while (I know) but I have corrected the post -- indeed, thanks!

With warm regards,
Mark D. Blackwell

Copyright (c) 2011 Mark D. Blackwell.

Brandenburg 5 in Bach-Lehman tuning

The following is a re-post.

Please click to listen before reading further. Today, w/s Brandenburg MIDI turned up a top-page (Google) result, the fifth Brandenburg concerto, in D major, ('[o]ne of the lushest and most thrilling pieces ever written'--quotations are from Wikipedia), by (Johann Sebastian) Bach, 'now regarded as the supreme composer of the Baroque [period, and] one of the greatest of all time', produced by Alan Kennington, moderately, clearly and with great unity on a (single) MIDI instrument, the harpsichord.

According to the artist, '[T]he performer needs to be able to bring out the music comprehensibly. When the music is at the right speed, it resonates in the listener. It generates a kind of excitement and pleasure... I believe that Baroque composers wanted their audience to feel pleasure... Bach was more interested in giving gentle pleasure[,] rather than a sudden rush of breathless excitement.'

For this very purpose I adjusted its tuning to Bach- Lehman 1722 temperament using Scala, whose 'motto is INVENIT ET PERFICIT which means, "it finds and perfects"'. The result? My friend M agrees that this is a:

much more beautiful, second movement (Affettuoso), in B minor.

For this, it is essential to use some good wave-table MIDI synthesizer software like Microsoft GS Wavetable SW Synth which is based on Roland wavetables.

The Creative SoundBlaster SoundFont Synth and the QuickTime Music Synthesizer (at least on PC's) somehow blot out temperaments' emotional content, and they make this listening comparison meaningless.

For comparison, the original:

equal-tempered version

I predict you shall be uncomfortable with it, now. As my friend M said, it seems 'like a terribly out of tune MIDI file'. Now we know it wasn't the MIDI system's fault.

Also available are the

first and third

movements (both Allegro) fully adjusted to Bach- Lehman 1722 tuning.

(I have emailed Alan U. Kennington, Ph.D., and he granted permission for this use. His website states, 'All original material on the web site is Copyright (C) 1999-2009, Alan U. Kennington. Permission is hereby granted for non-commercial reproduction of small portions of this material under the Artistic Licence, provided that this copyright notice is attached.')

Copyright (c) 2010 Mark D. Blackwell.

Monday, July 25, 2011

Prevent accidental drag and drop on touchpad laptops in Windows Explorer, howto

For convenience on many laptops, the touchpad functions like (left) clicking a mouse. However, in Windows Explorer, a classic problem occurs. We can drag and drop folders by mistake into other folders--they can get lost that way, or mess up our carefully organized tree.

The solution is a distance, a threshold, before accepting a drag (of a clicked mouse). We don't want natural hand jitter (visible at small resolutions) or accidental motion (while clicking) to be interpreted as a request to drag graphical objects around. This problem is well known--and Windows has such a threshold. However, their default is 4 pixels!

Some people's jitter is greater than others' (viz. Parkinson's disease); the default may be way too small to avoid the problem for touchpads, too.

Using 40 pixels as the threshold, I first move past two folders (or files) in Windows Explorer. Then before releasing the mouse, I pull it back to wherever I want, even to the adjacent folder.

There are two settings: horizontal and vertical. I set both the same--the horizontal is important, too, to prevent inadvertent mouse drags.

HKEY_CURRENT_USER\Control Panel\Desktop
DragHeight = "40"
DragWidth = "40"

Restart the computer for the change to take effect.

This setting allows windows also to be dragged conveniently. Drag a centimeter (half an inch) then back to your new, desired, fine location. The feeling is like a momentary slow response.

If you wish, you can use Microsoft's TweakUI (a free-of-charge Windows XP download) to set these.

You might enjoy playing with click-lock (on the mouse) for this problem, though it changes the user interface in a deep way, globally.

I wonder if someone in the leadership structure of Microsoft might be big enough to admit--to themselves--they are continuing a mistake (whether small or important) that occurred some time in the past but was correct at one time, the mistake caused by an increase in monitor resolution (as others have said), and respond to some users' cries for help by changing this 4-pixel default? Because the key difficulty is in admitting a mistake. Already they have enabled us to change our setting; it's merely avoiding a redecision about the default which is causing a problem in the wider world.

The current state on this issue seems one of drifting inertia and big-company self-insulation. (Some of their attitude about it is visible on their Developer Network.)

Disable Drag And Drop In Windows Explorer? (from Scot's Newsletter's Forum, editor of ComputerWorld)
Stop Windows copying files accidentally when Ctrl-click selecting (How-To Geek: more)
Prevent folder moving (see R. McCarty's answer)
Click lock (see S. Goodkin's answer)

Copyright (c) 2011 Mark D. Blackwell.

Saturday, July 23, 2011

Installing Leo (Outlining Editor) on Windows, howto

An introduction to Leo

Looking at text editors recently, I found a recommendation for Leo ('Leonine Editor with Outlines', developed by Edward K. Ream).

The (free) programmer's text editor and outliner (see Joe Orr's slideshow, or w/s Leo tutorial) improves software project readability, excitingly -- but it's not only for programmers. Leo is a feature-rich, productivity-increasing tool.

Using outlining is a fresh approach for the world of Literate Programming. It resolves the awkwardness, but easily fulfills the essence: it provides more readability, along with program code colocation with additional explanations, which helps prevent obsolescence.

To start, all you have to do (A) is enter an idea about any section of your text and (B) incrementally develop (in Leo) an outline of your ideas, referring to sections of the text.

Programmers need only (A) enter an idea about any (freely-chosen) section of their source code (e.g., its purpose) and (B) incrementally develop (in Leo) an outline of thoughts, referring to sections of the code.

Additions you make, no matter how few, are a kind of Easy Literate Programming.

Even while using Leo, no other team members will feel impacted, even if they edit the same source files without it. In no way does it hide the project source files inside its own folders or files, and it's compatible with version control systems, such as Git.

How can Leo accomplish this? Leo in a Nutshell explains. Ream's view is worth reading also, on Slashdot.

Leo is fairly mature and ready for use, long having had a 'small but extremely loyal group of users'[1] in addition to the developer's personal use. Its architecture is extensible by scripting; upwards of 75 interesting plugins have been written. It has borrowed much from Emacs. Some of its voluminous documentation seems obsolete (however) or merely implementation-oriented.

Presumably all Leo needs to know about the languages (even if obscure) used on your project is the syntax of how to form block- and single-line comments.

Leo opens a file by default (normally ~/.leo/workbook.leo, even on Windows) so if you want you can use it as a personal outlining planner.


Leo's outlines have cloneable nodes (and subtrees), and therefore multiple views. This might be a simple idea; I'll give you two examples.

For any given bug, a tree of relevant files can be collected (and cloned) and focused on without distraction. In the bug tree, as you edit those files, the ordinary hierarchy of files is being updated also (but not by special software). Since the nodes are cloned, you are editing the same files, not merely in essence but in actuality.

Insofar as you make notes briefly while puzzling out a problem or solving a bug, naturally they are entered right there in the place provided: in the bug's file tree (or associated with it). Afterward, you collapse the bug's tree, left behind to help explain the solved bug to future readers (developers) whenever they might need it -- Easy Literate Programming.

To explain something special to developers (readers) of the project, any files or folders (even sections of files) can be clone-arranged into a new tree structure (regardless of the layout of a project's filesystem).

In particular, if you have written about several cross-cutting (e.g., aspect-oriented) concerns (say, a, b and c), or wish to explain them to other developers, then it's good to clone-arrange the relevant files (unless that's all the files) into trees belonging to those concerns, though the files actually reside elsewhere in the project's main organizational filesystem folders (say, w, x, y and z).

It's an alternative to tagged filesystems in a way, but with explanations that grow organically -- it naturally produces a kind of manual, with an outlined table of contents.

Here's how to install Leo on Windows XP in detail (for the non Python-familiar) the way I did, using some installation instructions (or a fuller version) on the website as a basis:

Leo prerequisites

Leo requires Python 3 (or 2). Download and install minimally the latest Python-3 for Windows from Python's official website--I used 'python-3.2.1.msi'--to 'C:\progra\Python32'.

For Python, and Register Extensions, Tcl/Tk and Utility Scripts, pick 'Will be installed on local hard drive'. For Documentation and Test Suite, pick 'Entire feature will be unavailable'.

Download and install minimally the latest binary package for Windows containing QT-4, the 'cross-platform application and UI framework' and Python bindings, PyQT-4 from its developer's website; I used 'PyQt-Py3.2-x86-gpl-4.8.4-1.exe'.

Leo requires 'Qt runtime'. To ease uninstalling later, select 'Start Menu shortcuts'. Unselect everything else, including Documentation, Examples, QScintilla and the developer tools Developer, Qt, and SIP.

When PyQt asks you to specify a 'Python installation folder', give the same folder as above, 'C:\progra\Python32'; the library goes there, in a subfolder.

Installing Leo

Download and install the latest one-click installer for Windows (.exe) of Leo from its download page or possibly here. Click where it says, 'Looking for the latest version'. I used 'LeoSetup-4.9-final-a.exe'.

Leo may complain, 'Python not found,' but that's okay; we'll tell it later.

Leave selected 'Leo', '.leo File Association' and 'Leo Start Menu' and click Next. For 'Destination Folder', give 'C:\progra\Leo-4.9-final' or the equivalent. For Python Folder, give the same folder as above, 'C:\progra\Python32'. Keeping the default Start Menu folder, 'Leo', click Install and Finish.

Open a command line window with Win+ R and go to the Leo program directory with 'cd \progra\leo*'. Type It should say something like, 'is Python 3: True', and a little while later (possibly a window) will ask you for, 'an id that identifies you uniquely'. After that, Leo's graphical window should pop up.

From now on, you should be able to start Leo using the Windows Start menu.

Improving usability of Leo

With any folder menu in Windows Explorer, do Tools-Folder Options. Pick the File Types tab; move down and select the row that contains LEO in the Extensions column. Click the Advanced button; uncheck 'Confirm open after download'. Under Actions, make sure 'open' is selected and click the Edit button. Uncheck 'Use DDE' and into the box, 'Application used to perform action', paste:

C:\progra\Python32\pythonw.exe C:\progra\Leo-4.9-final\ "%1"

and click OK. (Double-quotes fix file and folder names that have embedded spaces, e.g. as you know, 'My Documents'.) Click OK again.

Now if you click any Leo file, an instance should be loaded to edit it.

The best documentation to read first is available by means of Menu-Help-Open quickstart.leo.

[1]Leo (Text editors wiki)

Further introduction

o Leo

Why I love Leo (Dan Rahmel)
What makes Leo special
Manual introduction
Blogpost: Using Leo as a personal information manager (PIM) (J.Tauber)
Leo (text editor) (Wikipedia)
Ream's thoughts on Joe Orr's slideshow
Leo website slideshow
Introductory tutorial

o Solved by Leo

Outliners, trees and meshes (Scott Rosenberg, author of Dreaming in Code, etc.)
Outlines and meshes (Taking Note, an anonymous blog)

o Background: Outliners

Outliners then and now (Scott Rosenberg)
MORE outliner (retrospective/review,
MORE, dinosaur (retrospective/review, Matt Neuburg)

o Background: Literate Programming

LP (Ward Cunningham wiki)
Software design for engineers and scientists (J.A. Robinson, GoogleBooks from w/s literate programming editor)
LP (PyLit website)
Lightweight LP with example (J.W.Shipman)
LP Workshop (Mac program)
LP is a terrible idea (Matt Giuca)
LP, why? (Bart Childs)
LP to enhance agile methods (Vreda Pieterse: publications)

o Related, vaguely

Tabulator: RDF semantic web browser (Tim Berners-Lee)
Bacon on instruments of the mind (Taking Note)

For more information

o On Leo

All about Leo
More Leo resources
Joe Orr's Leo resource page
Installing Leo on Windows (Matt Wilkie)
Develop in Haskell with Leo

o General

Outliner editor family (Text editors wiki)
Outliners: comparison (Mark Wieczorek)
XP/agile universe (conferences)

Copyright (c) 2011 Mark D. Blackwell.

Monday, July 11, 2011

Unfamiliar Windows keyboard shortcuts

I like to open folders sometimes in a new window, sometimes the same window. It's difficult to right-click my particular computer mouse. Also, generally I prefer keyboard shortcuts.

First I tried using Microsoft Windows Explorer's option which always opens a new window; soon I was frustrated, closing the many windows. (See Windows Explorer-Menu-Tools-Folder Options-General-Browse Folders.)

To open the other view (folder or explorer) in a new window, I was motivated to find a shortcut: either with the keyboard or a left mouse click. Some research found many that were unfamiliar and quite useful.

Here are my select keyboard and mouse shortcuts for Windows XP and later. You might not know all of them--I think you will find at least one excitingly useful!

App = Application key (AKA Menu key, context menu key)
Win = Windows key (AKA Flag key, Meta key, MOD4, Start key, Super key, Windows logo key, WinKey)

Alt+ Esc: Cycle programs in starting order
Alt+ F6: Cycle windows of active program
Alt+ PrintScreen: Capture program window (paste into Paint)
Alt+ Shift+ Esc: Cycle programs in starting order, backward
Alt+ Spacebar M Arrow: Move active window
Alt+ Spacebar S Arrow: Resize active window
App: Show context menu
Ctrl+ Shift+ Esc: Task manager
F6: Cycle screen elements (e.g., in SeaMonkey, go to address bar)
Win: Show start menu
Win+ Break: Show system properties
Win+ D: Show desktop (toggle)
Win+ E: Explore My Computer
Win+ L: Lock/logon screen (switch user)
Win+ M: Minimize all windows
Win+ R: Run
Win+ Shift+ M: Undo minimize all windows (also undo show desktop)
Win+ Shift+ Tab Enter: Cycle programs in taskbar, backward
Win+ Tab Enter: Cycle programs in taskbar
Win+ U: Utility manager (accessibility)
(Shift+ F10: same as App)

Command-line window:
Alt+ Spacebar E K (make selection) Enter: Select text
Alt+ Spacebar E L Arrow: Scroll
Alt+ Spacebar E P: Paste text

Alt+ Double-click: Show properties (single folder or file)
Alt+ Enter: Show properties (multiple folders & files)
Enter: Open single selection in folder view (or last-selected)
Shift+ Enter: Explore single selection (or last-selected)
(App O: same as Enter; App X: same as Shift+ Enter)

Multi-document program:
Ctrl+ F4: Close active document

... Icon of non-maximized document:
Double-click: Close

Windows Explorer (file chooser in other programs):
Alt+ Double-click: Show properties (of single folder or file; except explore-view navigation pane)
Alt+ Enter: Show properties (multiple folders & files)
Alt F W Enter: Create new folder
Alt V E O: Show navigation pane (toggle)
Ctrl+ Keypad '+': Fit columns
F4: Show folder trail (toggle)
Shift+ Click: Select from top to pointer

Finally, to avoid right-clicking, here are the shortcuts I was looking for:

... In explore view:
App O: New folder-view window(s)
Enter: Change to single selection; explore (some of) multiple selection in new windows
(App X, Click Shift+ Double-click: same as Enter)

... In folder view:
Ctrl+ Enter: Open single (or some of multiple) selection in new window(s)
Enter: Change to first-selected
Shift+ Enter: Explore in new window(s)
(App X, Click Shift+ Double-click: same as Shift+ Enter)


Saturday, June 11, 2011

Mass, songs I composed

I composed some music!

Also, I engraved its sheet music. (Good-looking, if I say so myself. I would be happy to engrave anyone's music! Please email me [click my profile] for reasonable rates.)

The following are free of charge (with the Creative Commons license):

A mass setting in Latin. Its title is, `Missa Brevis, Thomas Young'; its subtitle, `In a Sequence of Chords Inspired by His Harpsichord Temperament No. 1 of 1799, For Choir of Four Parts, Unaccompanied' (with optional organ). (Opus 1: May 2010, improved December 2011.)

I attempted, with music, to express the emotions naturally present in the mass text (for a wide audience, not necessarily Christian).

PDF sheet music and MIDI are available. The movements are Antiphon (Asperges Me & Vidi Aquam--Latin & English), Kyrie (Sixfold & Ninefold), Gloria, Sanctus & Benedictus and Agnus Dei.

Two songs, both on Roman Catholic/Anglican/Episcopal Church Lectionary texts (in English) for the Feast of the Sacred Heart (among other occasions, or for general use). (Opus 2: June 2010, improved December 2011.)

My aim was to approximate the pitches of natural speech, as well as to express the emotion of the texts.

They are for alto solo with tenor solo accompaniment (and optional keyboard):

1. `Jesus Addressed' (from Lk. 15:3-5) with PDF sheet music and MIDI, with piano accompaniment and without.

2. `It Is Rare' (from Rom. 5:7-8) with PDF sheet music and MIDI, with piano accompaniment and without.

I improved the print layout of the songs December, 2011.

The mass setting was inspired by (and is an homage to) Young's 1799 system of well-temperament (Young #1, called `ideal' by Owen H. Jorgensen in his classic book Tuning of 1991). It follows his temperament order of major thirds (which have roots C G=F D=Bb A=Eb E=Ab B=Db Gb), with CE purest-sounding and GbBb (in a sense, farthest away) the least pure-sounding (albeit the mass was written for equal-temperament).

Thus the (mass's) overall sequence of chords is actually two simultaneous circles of fifths. You can see an annotation of the chords in the sheet music (their roots, as well as major or minor), revolving (usually) in both directions. The movements are thus unified, and I added harmonic coloration (and inversion) to make them enjoyable.

Here is how I devised the mass's chord roots, in order of composition:

The Kyrie sections (of the two Kyrie settings) revolve from C to Gb; the Christe sections are the reverse. (The Sixfold one was composed after Agnus Dei.)

The Sanctus & Benedictus setting (considered as a unit) offers Young's equalized third roots the other way: C F G Bb D Eb A Ab E Db B Gb.

In the Gloria setting, the entire circle of fourths first revolves upward (on major chords) feeling like classical resolution, then downward (with some text-appropriate, minor chords) feeling like Plagal hymn resolution.

In the Agnus Dei setting, two arcs of fifths intertwine, though one breaks order slightly (and is reversed): C G D A E B Gb and Ab Eb Bb F (Db). Thus there (emotionally) is a regular falling pattern: C Ab G Eb D Bb A F E Db B Gb. Interestingly, the last four match the (chord) roots of the Benedictus, which inspired me.

Young's equalized third roots are presented simultaneously in the Antiphon setting, which revolves from C to Gb then reverses.

To the Gloria, Sanctus, Benedictus and Agnus Dei settings (previously Anglican chant: full-measure chords) I added rhythm (as well as improving the overall print layout) December, 2011.

Copyright (c) 2011 Mark D. Blackwell.

Wednesday, March 23, 2011

Install Rails 3 application to cPanel in sub-URI, howto

Recently, I successfully installed a Rails 3.0.3 application (using Ruby 1.8.7) on a plain-vanilla webhost with cPanel (which normally is restricted to Rails 2).

It can be managed in the normal way (started and stopped) on cPanel's webpage, 'Manage Ruby on Rails Applications', because of additional code I wrote in the Rails app.

Here's how I did it:

o See the webhost's current Ruby version and gem environment (for your_user_name) with:

cron> gem env

(If shell access is unavailable, command lines can be run as one-time cron jobs by specifying (year) month, day, hour and minute.)

o Ask the webhost to update if they don't have the latest RubyGems system software:

root> gem update --system

o Create a Ruby on Rails application (on the cPanel Ruby on Rails page) specifying application path, 'rails_apps/your_app_name'.

o In cPanel's File Manager (with the option to show hidden files) navigate to $HOME/rails_apps/your_app_name and delete the contents just made. Upload your Rails 3 application (there, compressing with 'zip' gives the relative pathnames required by cPanel) and extract it.

o Correct your cPanel user's gem environment by uploading to $HOME/.gemrc the following:

gem: --no-rdoc --no-ri

# Note: a non-default value adds another gempath.
# Is default for rubygems 1.5.2:
gemhome: /home/your_user_name/.gem/ruby/1.8

# Is default for rubygems 1.5.2:
- /home/your_user_name/.gem/ruby/1.8
# Your app's vendor bundle:
- /home/your_user_name/rails_apps/your_app_name/vendor/bundle/ruby/1.8
# Change this to the webhost's gem repository location:
- /usr/lib/ruby/gems/1.8

o The webhost's cPanel Software/Services RubyGems page might be incorrect:

oo It might say the location of your ruby gems is '/home/your_user_name/ruby/gems'. This is wrong; Rubygems software currently uses, '/home/your_user_name/.gem/ruby/1.8'.

oo It might recommend adding a gem repository to the include path. This is unnecessary; don't add either of the following:


o Install the bundler gem:

cron> gem install bundler

o Generate Gemfile.lock with:

cron> cd $HOME/rails_apps/your_app_name; bundle install --path vendor/bundle

o Ask the webhost to install (in the system gem repository) any gems Bundler failed to install, for instance, when Bundler tries to compile native extensions, which fails for cPanel users. For me, this was:

root> gem install mysql2

o Replace the Bundler code in config/boot.rb with a fixed list of gems:

# Set up gems listed in the Gemfile.
gemfile = File.expand_path('../../Gemfile', __FILE__)
require 'bundler'
rescue Bundler::GemNotFound => e
STDERR.puts e.message
STDERR.puts "Try running `bundle install`."
end if File.exist?(gemfile)

o To make the list, sort Gemfile.lock and keep only its highest version of each gem. My fixed list was:

require 'rubygems'

require 'mysql2'

# Moved arel up, because otherwise got error:
## /usr/lib/ruby/site_ruby/1.8/rubygems.rb:274:in `activate': can't activate arel (= 2.0.7, runtime) for [], already activated arel-2.0.8 for ["activerecord-3.0.3"] (Gem::LoadError)

gem 'arel', '=2.0.7'

gem 'abstract', '=1.0.0'
gem 'actionmailer', '=3.0.3'
gem 'actionpack', '=3.0.3'
gem 'activemodel', '=3.0.3'
gem 'activerecord', '=3.0.3'
gem 'activeresource', '=3.0.3'
gem 'activesupport', '=3.0.3'
gem 'builder', '=2.1.2'
gem 'erubis', '=2.6.6'
gem 'i18n', '=0.5.0'
gem 'mail', '=2.2.15'
gem 'mime-types', '=1.16'
gem 'polyglot', '=0.3.1'
gem 'rack', '=1.2.1'
gem 'rack-mount', '=0.6.13'
gem 'rack-test', '=0.5.7'
gem 'rails', '=3.0.3'
gem 'railties', '=3.0.3'
gem 'rake', '=0.8.7'
gem 'thor', '=0.14.6'
gem 'treetop', '=1.4.9'
gem 'tzinfo', '=0.3.24'

o Seamonkey's caching causes problems in testing. The setting, 'Menu-Edit-Preferences-Advanced-Cache-Compare the page in the cache to the page on the network', should be 'Every time I view the page'. This still did not prevent all old, cached pages even with page reloads. I recommend using another browser, such as Opera to test your application.

o For my Rails 3 application, I used port 12009, one higher than cPanel's Mongel port for Rails (12008).

o Besides the cPanel button, you can start the application yourself in the cPanel way by:

cron> cd $HOME/rails_apps/your_app_name; /usr/bin/ruby /usr/bin/mongrel_rails start -p cPanel_Mongel_port; -d -e development -P log/

o When troubleshooting, you can also start the application yourself by:

cron> cd $HOME/rails_apps/your_app_name; $HOME/.gem/ruby/1.8/bin/rails server webrick --port=Rails_3_port

o In config/environment.rb, add this line at the top:

unless (STARTED_BY_CPANEL='script/rails' != $PROGRAM_NAME)

o and these lines at the bottom:

load File.expand_path '../../monkey_patch_mongrel_1.1.5/start_webrick.rb', __FILE__

o Make a directory at the app root called, 'monkey_patch_mongrel_1.1.5'. Into it, place a file called 'dispatcher.rb' containing:

## Work around Mongrel source file: mongrel-1.1.5/lib/mongrel/rails.rb: 148
## require 'dispatcher'

module ActionController
class AbstractRequest
def relative_url_root=

o Also place a file there called 'start_webrick.rb' containing:

p, 'in '+__FILE__

# Versions tested on:
# Apache: 2.2.15
# Architecture: x86_64
# cPanel: 11.28.86
# cPanel Pro: 1.0 (RC1)
# Hosting package: Starter
# Kernel: 2.6.9-89.31.1.ELsmp (Linux)
# Mongrel: 1.1.5 (cPanel's)
# MySQL: 5.1.45
# Rails: 3.0.3
# Ruby: 1.8.7 patchlevel 330

module MyStartup
require 'pathname'

MY_RAILS_ENV=ENV['RAILS_ENV'] # Set by cPanel's Mongrel.

pfd=[]; PROGRAM_FILE.descend{|e| pfd << e} 1

ARGUMENTS="--environment=#{MY_RAILS_ENV} --port=#{PORT}"
# For debugging, change to '':
REDIRECT_OUTPUT='> /dev/null'

class GemPathEntry
SYSTEM = Pathname('/').join *%w[ usr lib ruby gems 1.8 ]
USER = USER_HOME .join *%w[ .gem ruby 1.8 ]
APP_BUNDLE = APP_ROOT .join *%w[ vendor bundle ruby 1.8 ]
MY_GEM_PATH=[GemPathEntry::APP_BUNDLE, GemPathEntry::USER, GemPathEntry::SYSTEM].join ':'

# We might need Bundler in system gems. Or, as working now, in user (.gem) gems; I don't remember.

# The following line doesn't work because Bundler (1.0.10) "bundle install --binstubs" rewrites gem executables to invoke Bundler:
## r = APP_ROOT.
r = GemPathEntry::APP_BUNDLE
RAILS_COMMAND=['exec',r.join(*%w[bin rails]),'server',SERVER,ARGUMENTS,REDIRECT_OUTPUT].join ' '

].join ' '

def self.stop_process(name,pid,signal)
p "I Stopping #{name} pid #{pid} at #{}"
Process.kill signal, pid
p "I #{Process.waitall.inspect}, #{name} finished at #{}"
rescue Errno::EINVAL, Errno::ESRCH
p "I No #{name} process #{pid}"
# Got error, undefined local variable or method `pwa' with:
## p pwa, "All child processes finished at #{}." unless (pwa=Process.waitall).empty?
# Sometimes there are other processes, I don't know why; so wait for them.
p "I #{pwa.inspect}, all child processes finished at #{}" unless pwa.empty?

# Rack (1.2.1) fails with Rails 3.0.3 and any Mongrel, although Webrick works, per:


p "I Program name ($0) is #{$PROGRAM_NAME}"
$LOAD_PATH.unshift APP_ROOT.join 'monkey_patch_mongrel_1.1.5'

unless WEBRICK_MONITOR_PID=Process.fork # Mongrel doesn't stop all threads, so we use a process.
p "I Starting Webrick monitor pid #{WEBRICK_MONITOR_PID} at #{} using command:"
Process.exec c unless WEBRICK_PID=Process.fork # Fork and replace another process.
p "I Starting Webrick pid #{WEBRICK_PID} at #{}"
Signal.trap 'TERM' do
stop_process 'Webrick', WEBRICK_PID, 'INT'
p "I #{Process.waitall.inspect}, Webrick finished (itself); stopping Mongrel at #{}"
unless File.exist? MONGREL_PID_FILE.to_s
p "I File '#{MONGREL_PID_FILE}' not found"
`#{s='mongrel_rails stop'}`
p "I '#{s}' finished at #{}"

Kernel.at_exit do # Handle being stopped by Mongrel.
stop_process 'Webrick monitor', WEBRICK_MONITOR_PID, 'TERM'


o The following rewrite rules require you to make this symlink:
/home/your_user_name/public_html/your_app_name ->

ln -s $HOME/rails_apps/your_app_name/public $HOME/public_html/your_app_name

o At least in Rails 3.0.3, the following config/application.rb statement, which allows your application to generate the proper sub-URI URL's for its static assets such as images, requires an extra '/your_app_name' in the RewriteCond directive for most cached pages:

config.action_controller.asset_path=proc{|p| "/your_app_name#{p}"}

o Note that cPanel users cannot change Apache's system-level configuration file (/usr/local/apache/conf/httpd.conf), for instance to add Alias directives, so the following applies:

'The most common situation in which mod_rewrite is the right tool is when the very best solution requires access to the server configuration files, and you don't have that access. Some configuration directives are only available in the server configuration file. So if you are in a hosting situation where you only have .htaccess files to work with, you may need to resort to mod_rewrite.' --from

o The Pattern argument to RewriteRule must be without leading slash (it is stripped by Apache) or trailing slash. Its Substitution argument must have the leading slash.

o Apache's directive, DirectorySlash redirects bare sub-URI requests to '/your_app_name/', since 'your_app_name' is a symlink to your application's directory, 'public'. Similarly, Apache normally redirects bare HTTP_HOST requests to '/' because 'public_html' is a directory.

o Per: httpd-docs-2.2.14.en/mod/mod_rewrite.html#rewriterule
Per-directory Rewrites: When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is automatically removed for the pattern matching and automatically added after the substitution has been done.

o My file, 'public_html/.htaccess' has these directives regarding cache expiration:

# Requires mod_expires to be enabled.
<IfModule mod_expires.c>
# Enable expirations.
ExpiresActive On
# Cache all files for 2 weeks after access (A).
ExpiresDefault A1209600
# Do not cache dynamically generated pages.
ExpiresByType text/html A1

o Apache's <if> directive is unavailable until version 2.3, per:

o Apache's FallbackResource directive is unavailable until version 2.2.16, per:

o Place this .htaccess file in your application's public directory:

# Rails 3.0.3 cPanel Apache settings.
# Don't show directory listings for URLs which map to a directory.
Options -Indexes
# Set the default handler to none.
# Don't follow symbolic links in this directory or below.
Options -FollowSymLinks

# Rewrite module.
<IfModule mod_rewrite.c>
RewriteEngine on
# Per :
RewriteOptions inherit
RewriteBase /your_app_name

# 1. Simplify the rules for your sub-URI by redirecting a missing subdomain to 'www.':

RewriteCond %{HTTP_HOST} ^your_user_name\.com$ [NC]
RewriteRule ^(.*)$$1 [L,R=301]

# 2. Rewrite your Rails application URI's to various files if they exist.

# 2.1. Rewrite its page-cached URI's:

# 2.1.1. Try to rewrite the sub-URI root URI to a file ('public/your_app_name.html') with path '/home/your_user_name/public_html/your_app_name/your_app_name.html':

RewriteCond %{HTTP_HOST} ^www\.your_user_name\.com$ [NC]
RewriteCond %{REQUEST_FILENAME}your_app_name.html -f
#SHOW RewriteRule ^$ /your_app_name/your_app_name.html?dr=%{DOCUMENT_ROOT}&rf=%{REQUEST_FILENAME} [L,R=301]
RewriteRule ^$ /your_app_name/your_app_name.html [L]

# 2.1.2. Try to rewrite a sub-URI, non-root URI to a file with extension '.html' (under tree, 'public/your_app_name/') by prefixing '/home/your_user_name/public_html/your_app_name' and suffixing '.html':

RewriteCond %{HTTP_HOST} ^www\.your_user_name\.com$ [NC]
RewriteCond %{DOCUMENT_ROOT}/your_app_name%{REQUEST_URI}.html -f
#SHOW RewriteRule ^(.+)$ /your_app_name/$1.html?dr=%{DOCUMENT_ROOT}&ru=%{REQUEST_URI}&rf=%{REQUEST_FILENAME} [L,R=301]
RewriteRule ^(.+)$ /your_app_name/your_app_name/$1.html [L]

# 3. Rewrite all other requests (except existing files) to the Rails port:

RewriteCond %{HTTP_HOST} ^www\.your_user_name\.com$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
#SHOW RewriteRule ^(.*)$ /your_app_name/your_app_name.html?rf=%{REQUEST_FILENAME} [L,R=301]
RewriteRule ^(.*)$$1 [L,P]


o References: (simpler)

o Then as a result, if you start your application, its cPanel Mongrel log in log/mongrel.log should look like this:

** Daemonized, any open files are closed. Look at log/ and log/mongrel.log for info.
** Starting Mongrel listening at
** Starting Rails with development environment...
Wed Mar 23 12:29:15 -0700 2011
"in /home/your_user_name/rails_apps/your_app_name/config/environment.rb"
Wed Mar 23 12:29:15 -0700 2011
"in /home/your_user_name/rails_apps/your_app_name/monkey_patch_mongrel_1.1.5/start_webrick.rb"
Wed Mar 23 12:29:15 -0700 2011
"I Program name ($0) is /usr/bin/mongrel_rails"
"I In /home/your_user_name/rails_apps/your_app_name/monkey_patch_mongrel_1.1.5/start_webrick.rb"
"I Starting Webrick monitor pid at Wed Mar 23 12:29:15 -0700 2011 using command:"
"export HOME=/home RAILS_ENV=development GEM_HOME=/home/.gem/ruby/1.8 GEM_PATH=/home/your_user_name/rails_apps/your_app_name/vendor/bundle/ruby/1.8:/home/.gem/ruby/1.8:/usr/lib/ruby/gems/1.8; cd /home/your_user_name/rails_apps/your_app_name; exec /home/your_user_name/rails_apps/your_app_name/vendor/bundle/ruby/1.8/bin/rails server webrick --environment=development --port=12009 > /dev/null"
"I Starting Webrick pid 15175 at Wed Mar 23 12:29:15 -0700 2011"
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).
** Rails signals registered. HUP => reload (without restart). It might not work well.
** Mongrel 1.1.5 available at
** Writing PID file to log/
[2011-03-23 12:29:16] INFO WEBrick 1.3.1
[2011-03-23 12:29:16] INFO ruby 1.8.7 (2009-06-12) [x86_64-linux]
[2011-03-23 12:29:16] INFO WEBrick::HTTPServer#start: pid=15175 port=12009

o If you use the cPanel button to stop your application, it should look like this:

** TERM signal received.
"I Stopping Webrick monitor pid 22436 at Wed Mar 23 12:47:43 -0700 2011"
"I Stopping Webrick pid 22437 at Wed Mar 23 12:47:43 -0700 2011"
[2011-03-23 12:47:43] INFO going to shutdown ...
[2011-03-23 12:47:43] INFO WEBrick::HTTPServer#start done.
"I [[22437, #<Process::Status: pid=22437,exited(0)>]], Webrick finished at Wed Mar 23 12:47:43 -0700 2011"
"I [], Webrick finished (itself); stopping Mongrel at Wed Mar 23 12:47:43 -0700 2011"
"I File '/home/your_user_name/rails_apps/your_app_name/log/' not found"

o If, from inside your application, you also want to stop cPanel's Mongrel server and Webrick (I did, because my application makes static pages), add this to one of your controllers:

WEBRICK_PID_PATH=App.root.join *%w[ tmp pids ]
s=f.gets("\n").chomp "\n"
s.to_i if s.present?
rescue Errno::ENOENT

def stop_application(s) "I #{s}; sending INT to application PID #{application_PID}"
Process.kill 'INT', application_PID

def stop_server
# Attempt to stop Webrick server gracefully by sending it SIGINT:
if WEBRICK_PID.present? && WEBRICK_PID > 0
begin "I sending INT to Webrick PID #{WEBRICK_PID}; application PID is #{application_PID}"
Process.kill 'INT', WEBRICK_PID
rescue Errno::EINVAL, Errno::ESRCH
# Handle various unusual conditions:
when WEBRICK_PID.blank?
'No Webrick file found'
when (WEBRICK_PID <= 0)
"Bad value in Webrick file: #{WEBRICK_PID}"
when (WEBRICK_PID != application_PID)
"Server PID #{WEBRICK_PID} differs from application's: not Webrick?"
when (!webrick_killed)
"No process #{WEBRICK_PID}"
# TODO: Handle hung Webrick server?
stop_application s if s

o If you stop Mongrel from within your application, it should look like this:

[2011-03-23 12:30:46] INFO going to shutdown ...
[2011-03-23 12:30:47] INFO WEBrick::HTTPServer#start done.
"I [[15175, #<Process::Status: pid=15175,exited(0)>]], Webrick finished (itself); stopping Mongrel at Wed Mar 23 12:30:47 -0700 2011"
** TERM signal received.
"I Stopping Webrick monitor pid 15174 at Wed Mar 23 12:30:47 -0700 2011"
"I Stopping Webrick pid 15175 at Wed Mar 23 12:30:47 -0700 2011"
"I No Webrick process 15175"
"I [[16266, #<Process::Status: pid=16266,exited(0)>]], all child processes finished at Wed Mar 23 12:30:47 -0700 2011"
"I 'mongrel_rails stop' finished at Wed Mar 23 12:30:47 -0700 2011"
"I [[15174, #<Process::Status: pid=15174,exited(0)>]], Webrick monitor finished at Wed Mar 23 12:30:47 -0700 2011"

Webmaster gallery - cPanel Rails 3 app - Mark D. Blackwell

Copyright (c) 2011 Mark D. Blackwell.