Windows SSH


If you need to ssh into a Windows machine, I highly recommend you use MobaSSH (free for personal use).  It's much easier than:

Cool WebGL demo: Tron dashboard


The power of GNU screen


Ever feel like the whole world knows something really useful except you?  I went to a tech conference the other day and someone mentioned the screen command. where have you been all my life?!

In a nutshell: screen allows you to start a long-running process and then "detach" and shut down your computer while the command continues to run on the server.  Very cool.  Here's a quickstart guide:

perform initial configuration by opening ~/.screenrc and add the following:

# enable shell in screen
shell -$SHELL

# turn off flash notification
vbell off

# clear terminal when exit editor or screen
altscreen on

# set title
termcapinfo xterm*|rxvt*|kterm*|Eterm* 'hs:ts=\E]0;:fs=\007:ds=\E]0;\007'
hardstatus string "%h"
hardstatus off

# set footer
caption always "%{= kw} %=%-w%{= bk}%50>%n %t%{-}%+w%<"

in terminal, verify screen is installed:
screen -v
in terminal, open a new session
in screen (has purple box in footer), create new session
Ctrl+a c
in screen, switch to another session (where # refers to the session number 0, 1, 2, etc.)
Ctrl+a #
in screen, switch to next running session (use p for previous)
Ctrl+a n
in screen, list the running sessions
Ctrl+a "
in screen, detach from the current session
Ctrl+a d
in terminal, list the running sessions
screen -ls
in terminal, resume a running session
screen -r #####

P.S. You can change your hardstatus string value to a variety of things to display in your terminal title.  However, adding the user name is tricky.  If you use %h you get the default prompt, which likely contains some variation of user@domain, but if you want to create a custom title (say, server name ~ user name), then things get a bit harder.  Most guides will tell you to include ${USER} in your string, which does in fact work...unless you sudo su to a different user account.  Argh! - it still shows your original login username!  To fix this, add the following to each account's ~/.bashrc or ~/.bash_profile file (where the pink text is your custom title):

if [ "$TERM" = "screen" ] ; then PS1=$PS1"\[\e]0;${HOSTNAME%%.*} ~ ${USER}\a\]" ; fi

P.P.S. A popular alternative to screen is tmux

Set up Selenium Grid2 on Windows (for testing with IE, Safari, Chrome/Opera, and Firefox)


Update: If you have an Amazon Web Services (AWS) account, here's a nice CloudFormation template that will do everything for you!


Confused by Selenium?  You're not the only one!  There are many Selenium guides out there but I couldn't find any that provided a complete tutorial for installing it on Windows for IE, Safari, Chrome, and Firefox testing so I thought I'd document my process with Windows Server 2008 R2:

1. login to Windows with an account that has administrator rights

2. if not already open, click on Start and search for Server Manager to open; then click on Configure IE ESC link (in the Security Information section) and turn off IE ESC for both Administrators and Users

3. if not already done, use this guide to show file extensions and hidden folders

4. install Java

5. install Chrome

6. install Firefox

7. install Safari for Windows  Update: Safari for Windows is no longer supported and does not provide an accurate testing platform -- either use a cloud service to test Safari on Mac or install a Selenium Grid Node on a Mac

8. create a folder in C:\ called selenium and download into it

9. download and extract the InternetExplorerDriver and ChromeDriver drivers into the C:\selenium folder (Notes: Use the 32-bit versions even if your Windows OS is 64-bit because even if your OS is 64-bit, browsers run as 32-bit.  The Firefox and Safari drivers are already included in the selenium-server-standalone.jar file as pre-built extensions.  Opera uses the same engine as Chrome so you don't have to run separate tests for it.)

10. click Start and search for Edit the system environment variables to open the System Properties dialog, then click the Environment Variables... button, then click on the Path variable in the System variables list and click the Edit... button.  At the end of the Variable value textbox add:

;C:\Program Files (x86)\Java\jre7\bin\;C:\selenium\
11. restart Windows

12. create a file called hub.json in the C:\selenium folder with the following contents:

  "host": null,
  "port": 4440,
  "newSessionWaitTimeout": -1,
  "servlets" : [],
  "prioritizer": null,
  "capabilityMatcher": "org.openqa.grid.internal.utils.DefaultCapabilityMatcher",
  "throwOnCapabilityNotPresent": true,
  "nodePolling": 5000,
  "cleanUpCycle": 5000,
  "timeout": 300000,
  "browserTimeout": 0,
  "maxSession": 5,

13. create a file called node.json in the C:\selenium folder with the following contents:

      "platform": "WINDOWS",
      "browserName": "firefox",
      "maxInstances": 1,
      "seleniumProtocol": "WebDriver"
      "platform": "WINDOWS",
        "browserName": "chrome",
        "maxInstances": 1,
      "seleniumProtocol": "WebDriver"
      "platform": "WINDOWS",
      "browserName": "internet explorer",
      "version": "11",
      "maxInstances": 1,
      "seleniumProtocol": "WebDriver"
      "platform": "WINDOWS",
      "browserName": "internet explorer",
      "version": "10",
      "maxInstances": 1,
      "seleniumProtocol": "WebDriver"
      "platform": "WINDOWS",
      "browserName": "internet explorer",
      "version": "9",
      "maxInstances": 1,
      "seleniumProtocol": "WebDriver"
      "platform": "WINDOWS",
      "browserName": "internet explorer",
      "version": "8",
      "maxInstances": 1,
      "seleniumProtocol": "WebDriver"
      "platform": "WINDOWS",
      "browserName": "safari",
      "maxInstances": 1,
      "seleniumProtocol": "WebDriver"
    "registerCycle": 5000,

14. test the Selenium server by:

i. opening a command prompt and typing:
java -jar C:\selenium\selenium-server-standalone-2.41.0.jar -role hub -hubConfig C:\selenium\hub.json
ii. opening another command prompt window and typing:
java -jar C:\selenium\selenium-server-standalone-2.41.0.jar -role node -nodeConfig C:\selenium\node.json
iii. open a browser and go to and verify all browsers are displayed

15. stop the hub and node by closing each command prompt

16. download NSSM (used to start Selenium as a Windows service) and extract nssm-{version}\win64\nssm.exe (assuming your OS is 64-bit, otherwise use the 32-bit NSSM executable) to C:\selenium

17. open a command prompt and type:
nssm install seleniumhub java -jar C:\selenium\selenium-server-standalone-2.41.0.jar -role hub -hubConfig C:\selenium\hub.json
18. then, type:
nssm install seleniumnode java -jar C:\selenium\selenium-server-standalone-2.41.0.jar -role node -nodeConfig C:\selenium\node.json
19. restart the computer

20. after it restarts, login, open a browser, and go to to verify all browsers are displayed

21. add firewall exceptions by opening a command prompt and typing:
netsh advfirewall firewall add rule name="SeleniumIn" dir=in action=allow protocol=TCP localport=4440
netsh advfirewall firewall add rule name="SeleniumOut" dir=out action=allow protocol=TCP localport=4440

Congratulations!  Your Selenium grid is now functional and you can use a Selenium WebDriver-compatible testing framework (such as Codeception, WebDriverJS, etc) to connect to it (using the server's actual IP address, not localhost or

P.S. For security reasons, in my tutorial I've used non-default ports 5550 and 4440 instead of the default 5555 and 4444.  Feel free to use your own custom port numbers if you wish.

P.P.S. For ease and convenience, this tutorial installed the hub and node on the same server.  In a more realistic scenario, there would be a central hub on one server and multiple worker nodes on separate servers.  In that case, you would follow steps 1-4,8,10-12,14i,15-17,19,21 for the hub and all steps except 12,14i,14iii,17 for the node(s).  You will also need to update the "host" and "hubHost" settings in step 13 to point to the node's and hub's actual IP address, respectively.


Additional resources:

Motorola kills swype with KitKat


The Motorola Razr M update to KitKat today deleted my free OEM install of swype.  Major lame   :(

Since the free Google keyboard app (that's presumably meant to replace it) tracks your typed messages in the cloud and the free version of the Yii keyboard app doesn't have left/right arrows, I finally broke down and paid my lame $4 to The Man - argh!

...even then, I still lose my left/right arrows on the main keyboard screen (an OEM-only feature) and now have to swipe the swype symbol onto the +!= button to get to them.  Double Argh!!

Tech vs. Breakfast


What happens when you put a nerd in charge of breakfast:


P.S. hosting a tech conference at a hotel that does not offer free wi-fi is like a crime against humanity.

Temporarily convert bike helmet to caving helmet


So a friend invites you to go caving but you don't have a headlamp...what to do?  Well, you could just bring a flashlight and carry it around with you but that would remove an available hand for climbing, steadying, etc. and it will also get the flashlight pretty dirty (especially if it's a muddy cave).  My solution was to attach a couple small flashlights to my bike helmet (which you should be wearing anyways for protection):

1. Find or buy 2 mini LED flashlights, preferably with an on/off switch at the rear and grooves in the handle:

2. Take some wire (I used two bag twist-ties and tied their ends together) and loop them around the flashlight handle and put the ends through a hole in the side of the bike helmet so the light source is pointing forward:

3. Break a Popsicle stick in half and tie the wire around it tightly (the stick prevents the wire from falling back out of the helmet hole):

4. Place some tape (I used electrical) over the wire and stick so it doesn't rub against your head:

5. Put the helmet on and try it out in a dark room to verify the light source focuses generally in front of you and has the desired brightness.  Then, add additional tape on the outside for additional stabilization:

6. Repeat the process for the other side of the helmet:

7. Enjoy your temporary caving helmet!