2015/01/13

Porting Frankenstein’s ___.sh to Linux

Frankenstein’s ___.sh was developed on a Mac. The first server it ran on was a FreeBSD shared host at nearlyfreespeech.net. Until recently, there was no need for it to run on a Linux box.

However, this changed late last year, when I wanted to be able to publish to this blog from my iPhone. I had made a Pythonista script to publish to the Displayator blog, which was working with the 1.0 version of Frankenstein’s (I published the last announcement there using the Pythonista script). One big difference between 1.0 and 2.0 is that the new version use absolute URLs, so to preview a new post on the server before publication requires either a subdomain segragated from the main site, or an entirely different site. While it would be very cheap to set up a new, domainless, site on nearlyfreespeech (it really is nearly free), I also have a Linode (Arch) Linux1 box in the cloud doing barely anything. It is also likely that a dedicated host with with an SSD will be faster at generating the site, if only slightly.

I didn’t want to try to get ___.sh to run on the iPhone itself as that would require a Jailbreak (which I don’t want to do), but getting it to run on my Linux cloud box should be possible. I’ll then be able to use ssh to connect directly and execute the commands manually (paste new post to staging server, generate site, start webserver, view in browser, accept/reject, commit, push to github, push to public server, done) or, like I did for the 1.0, use a Pythonista or Editorial script to do all the operations for me.

Running ___.sh at 100% on Linux required a few adjustment. There were two commands spouting errors:

date: invalid option -- 'j'
Try 'date --help' for more information.

and

find: warning: you have specified the -mindepth option 
after a non-option argument -type, but options are not 
positional (-mindepth affects tests specified before it 
as well as those specified after it).  Please specify 
options before other arguments.

find: warning: you have specified the -maxdepth option 
after a non-option argument -type, but options are not 
positional (-maxdepth affects tests specified before it 
as well as those specified after it).  Please specify 
options before other arguments.

The find errors were easy enough to fix by re-ordering the parameters on every line where -maxdepth or -mindepth are present and putting them as the second argument. The date one however comes from a more substantial incompatibility between the Linux and BSD version of the utility. I didn’t find a way to reconcile the parameters so an invocation producing the same output would work on both OS families.

In ___.sh, date is used to convert the blog post’s date from a sensible format like 2014/11/18 1845 to the ugly2 English-language centric RFC-822 format of Tue, 18 Nov 2014 18:45:35 +0100.

For the OSX/BSD date, I have to specify both the input format ("%Y/%m/%d %H%M") and the output format ("+%a, %d %b %Y %H:%M:%S %z"), for a final command that is pretty heavy3:

date -j -f "%Y/%m/%d %H%M" "\1/\2/\3 \4"  "+%a, %d %b %Y %H:%M:%S %z"

The linux verion seems to be more user centric. It recognize “2014/11/18 1845” as a date, and knows about the rfc-822 format, so the entire command is much shorter:

date -d "\1/\2/\3 \4" --rfc-822

Now, to make this work on both OS at the same time, I had at least two options:

  1. Check for the OS version and use the appropriate syntax.
  2. Use both, and ignore any error output.

Option #1 would have involved more logic and more lines of code to write. It was promptly discarded.

For option #2, running date with the wrong parameter only produces text on stderr, so it merely required figuring how to suppress that part of the output . Thankfully, the syntax for forwarding stderr to /dev/null is the same on both OS families, so a few google searches and tests later, it was implemented and adopted.

I’ll spare you the full command line where it is used, but the date part went from date -j -f "%Y/%m/%d %H%M" "\1/\2/\3 \4" "+%a, %d %b %Y %H:%M:%S %z" to this:

date -d "\1/\2/\3 \4" --rfc-822 2>/dev/null date -j -f "%Y/%m/%d %H%M" "\1/\2/\3 \4" "+%a, %d %b %Y %H:%M:%S %z" 2>/dev/null

Yes, I have both invocations one after the other. The overall command became slightly longer and “uglier4”, but it works on both OS families and no line were added!

Henceforth, you can now enjoy the benefits of running Frankenstein’s ___.sh, one of the simplest5 static site generator around, on your *BSD, OSX or Linux box!


  1. I leave hosting my websites to professionals so I don‘t loose sleep over it being up or able to handle the (tiny) traffic I have. I use that Arch linux instance as a VPN host for pretending to be in the US. I also wrote a fabfile script that can regenerate it from scratch in 5 minute flat (mostly waiting for Linode to provision it and for packages to download and install). But I don’t recommend using this particular distro unless you really really really (really) want to learn about linux.  ↩

  2. The only sensible thing is the timezone format: +0100 makes more sense than UTC+1 or DST / CST / EST etc…  ↩

  3. "\1/\2\/3 \4" is where the post's date goes. It comes from the parsing of the blog post file name, which contains the year, month, day and time of the post publication.  ↩

  4. Not that is was anywhere near pretty before.  ↩

  5. Some might say rudimentary. There are no variables (yet), but it supports 4 different type of content. And you won't need to be messing around with templating languages or installing scripting language runtimes and their dependencies. It only needs multimarkdown and Linux/BSD/OSX.  ↩

 
Archives / RSS
— ~ —