The JavaScript blog.


tutorials node documentation unix essay

Unix and Node: Command-line Arguments

Posted on .

Shebang Bootcamp

Writing an executable script with Node begins with the shebang: #!, followed by the path to a Node executable. Not all Unix systems use the same file system layout, and not all users want to install Node in the same place. Since the shebang must specify an absolute path, a common way around this is to introduce a level of indirection through env:

#!/usr/bin/env node

This can be seen in many popular Node modules, and in other scripting languages too. If I try and run a script like this in my shell, I'll get an error:

➜ ./echo.js
zsh: permission denied: ./echo.js  

I have read permission on the file, but it isn't executable:

➜ ls -l
-rw-r--r--  1 alex  wheel  21  1 Mar 17:24 echo.js
➜ chmod u+x ./echo.js 
➜ ls -l
total 8  
-rwxr--r--  1 alex  wheel  21  1 Mar 17:24 echo.js

Here I've used chmod to set the executable flag for the user that owns the file. Most people use the octal notation for setting permissions, which looks complicated but isn't as hard as it seems.

Argument Vector

Command-line arguments are available through the process global in an array called argv. This term comes from "argument vector", influenced by C where it's conventional to name the argument count and argument vector this way:

int main(int argc, char *argv[])  

Technically these parameters could be named anything, but this is a strongly followed convention.

Compared to C, JavaScript's array is a handy type for representing arguments:

#!/usr/bin/env node

console.log('Arguments:', process.argv.length);  

Running this script with no arguments shows what the script was run with:

Arguments: 2  
[ 'node', '/private/tmp/unix-node/echo.js' ]

Conversely, passing in arguments looks like this:

➜ ./echo.js --text JavaScript in the shell
Arguments: 7  
[ 'node',
  'shell' ]

Handling more complex arguments takes a little bit of work, so it's often preferable to offload the effort to a suitable module. However, some scripts have simple requirements, so array manipulation of process.argv may suffice. This example is from Node's cluster.js file:

exports.start = function() {  
  amMaster = true;

  if (process.argv.length < 1) {
    console.error('Usage: node cluster script.js');

  var args = process.argv.slice(2);
  var scriptFilename = args.shift();

The length of process.argv is validated to ensure the expected option has been supplied, and process.exit(1) is called if validation fails. This is interesting because an argument has been supplied to process.exit. Why 1?

Exit Status

Unix and Unix-like systems use a convention that a non-zero exit status from a program is an error. In C, EXIT_FAILURE is a macro that can be used to denote this, and on POSIX systems this value is 1. Changing the previous example to return a non-zero exit code looks like this:

#!/usr/bin/env node

console.log('Arguments:', process.argv.length);  

if (process.argv.length < 3) {  

Running this script with no arguments should return 1. However, look what happens:

➜ ./echo.js 
Arguments: 2  
[ 'node', '/private/tmp/unix-node/echo.js' ]

... nothing? There's no error message or anything! This is actually a good thing -- think back to the philosophies behind Unix, in particular Doug McIlroy's quote:

Write programs to handle text streams, because that is a universal interface.

In a world based around text streams, we don't want default behaviour that's too noisy. If someone built upon this script, they'd rather deal with a concrete error status. This value can be obtained in most shells by reading $?:

➜ echo $?

Option Parsing Libraries

The two most popular option parsing libraries for Node are Optimist (License: MIT/X11, npm: optimist) and Commander.js (GitHub: visionmedia / commander.js, License: MIT, npm: commander) by TJ Holowaychuk. These are both well-maintained libraries by active members of the Node community.

Optimist has its own argv object that can deal with grouped, long, and short options, and can even display usage:

#!/usr/bin/env node
var argv = require('optimist')  
    .usage('Usage: $0 -x [num] -y [num]')

console.log(argv.x / argv.y);  

Commander.js has a chainable API that's like a DSL for option processing:

#!/usr/bin/env node

var program = require('commander');

  .option('-p, --peppers', 'Add peppers')
  .option('-P, --pineapple', 'Add pineapple')
  .option('-b, --bbq', 'Add bbq sauce')
  .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')

console.log('you ordered a pizza with:');  
if (program.peppers) console.log('  - peppers');  
if (program.pineapple) console.log('  - pineappe');  
if (program.bbq) console.log('  - bbq');  
console.log('  - %s cheese', program.cheese);  

The program's usage is automatically generated.


In Node, powerful option parsing is only an npm install away. The built-in process.argv array is also convenient and easy to manage for simple situations. Just remember to exit programs with conventional status codes, or angry shell scripters may fill up your GitHub issues before you know it!


tutorials node documentation unix essay

Unix and Node: Manual Pages

Posted on .

If you're familiar with npm's documentation you'll have noticed that it comes with a lot of manual pages. I don't think I could have published an npm module without reading man npm-json several times first. To this day I still bring it up to search for the correct properties for the more obscure features.

Let's look at npm to see how Isaac did this, then generalise it a little bit so you can publish your own manual pages.


npm man page

The now ubiquitous npm makes use of man pages for its documentation. This isn't the only way to view these files, but it's my preferred way to read them. The way npm generates documentation is clever -- Isaac has chosen to write files in Markdown, which has a positive side-effect of allowing GitHub to render them. These files are then converted to a markup language that man will understand.

This markup language is derived from early typesetting tools, known as the roff system. If you're interested in writing manual pages by hand, take a look at man groff. To learn about the history of these tools, man roff is an interesting read.

Converting a Markdown document to something roff-like was solved rather well by ronn by Ryan Tomayko. Ronn is a Ruby program, so Isaac has used his own fork of ronnjs to generate his manual pages for npm.

To make this work, npm's makefile will run scripts/doc-build.sh:

man/man1/%.1: doc/cli/%.md scripts/doc-build.sh package.json  
  @[ -d man/man1 ] || mkdir -p man/man1
  scripts/doc-build.sh $< $@

The doc-build.sh script uses bash, sed, and perl to replace values in the Markdown files:

./node_modules/.bin/ronn --roff $src \
| sed "s|@VERSION@|$version|g" \
| perl -pi -e 's/npm\\-([^\(]*)\(1\)/npm help \1/g' \
| perl -pi -e 's/npm\\-([^\(]*)\(3\)/npm apihelp \1/g' \
| perl -pi -e 's/npm\(1\)/npm help npm/g' \
| perl -pi -e 's/npm\(3\)/npm apihelp npm/g' \
> $dest

Another option for manual page generation is the mantastic web service, mentioned by TJ Holowaychuk in the comments on HelsinkiJS February, Todo, Testing Backbone.js.

Therefore, a general pattern for generating manual pages in Node apps is as follows:

  • Create files for documentation using your preferred markup language
  • Use a suitable tool to generate something similar to the groff language
  • The resulting manual pages can be distributed when publishing to npm, (Node includes node.1 in its source)

An alternative would just be to write the manual pages using the groff language to begin with. It's surprisingly easy to pick up, although it's not as friendly as Markdown and doesn't have the advantage of being easily read without formatting.

Installing Manual Pages

When a module is installed with npm, it'll actually copy man pages to {prefix}/share/man if they're available. To do this, tell npm where the man pages are in the directories property:

"directories": {
  "man": "./doc/man"

If this module is installed as a global module, then npm will copy the manual pages from ./doc/man to {prefix}/share/man.


When writing a general purpose tool with Node, consider writing a manual page using groff, or converting your Markdown documentation. The command-line jockeys amongst us will appreciate it, and it'll bring your application a little bit closer to feeling like a true part of a Unix system.


tutorials node unix essay

Unix and Node

Posted on .

Recently, Node has received a huge amount of development effort to improve its Windows support. However, most of us probably run Node on some flavour of Unix -- whether it be a Linux, Mac OS, Solaris, or a non-fruit BSD.

As JavaScript enthusiasts we can do a lot in Unix with just a little bit of Node. This new essay series is a collection of tips and observations I've made about Unix and Node. If you're interested in writing command-line tools or networking daemons, Node is a good choice, and you'll see why over the next few weeks.

Folklore and Tradition

If you're a solid programmer but lack fundamental Unix knowledge, I won't hold it against you. The important thing to realise is learning Unix requires knowledge of traditions and philosophies. As stated by Eric S. Raymond in The Art of UNIX Programming:

If you are not a programmer, or you are a programmer who has had little contact with the Unix world, this may seem strange. But Unix has a culture; it has a distinctive art of programming; and it carries with it a powerful design philosophy. Understanding these traditions will help you build better software, even if you’re developing for a non-Unix platform.

This means learning to write Unix programs that behave the way seasoned Unix users expect isn't always a case of looking up standards and best practices.
One of the most famous comments on the philosophy of Unix is by Doug McIlroy:

Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.

Does that sound familiar? Try changing the word "program" to "module":

  • Write modules that do one thing and do it well.
  • Write modules that work together.
  • Write modules that handle events and streams.

In The Art of UNIX Programming, Raymond summarises many of these ideas and philosophies into a set of design rules that are readily available on Wikipedia: Unix philosophy.

Rule of Diversity: Distrust all claims for "one true way".

Coming to Unix development from a web developer's background requires a change in thinking. When working as a client-side developer, one may regularly refer to W3C specifications. However, when writing Node software for Unix, it's likely that the philosophy of Unix developers will shape the application more than standards and specifications. To see why we need to take a look at Node's relationship to POSIX.


The family of standards that helps us write portable code is known as POSIX. This covers the C Standard Library, process creation and control, signals, pipes, and a lot more. In addition, the core Node developers have their own philosophy and concerns. For example, Node has to maintain portability with Windows. Certain aspects of POSIX don't necessarily fit in with Node's philosophy, hinted at here by Ryan Dahl while discussing the possibility of a Node POSIX library:

dup, dup2, fork are out of the question and will never be added. They do not coincide node's philosophy. chroot is not useful but is a posix thing. The posix module I suggested was to support random user/permissions stuff like getpwnam(). I'd rather not have that if we can get away with it.

-- Ryan Dahl on an official POSIX library

This comment by Isaac Schlueter is also interesting:

So far, in any of the cases where we'd thought we'd need to split out a posix library, we've been able to find sane approaches for both Windows and Unix. Who knows if that'll continue, but it'd be nice to not have to do require("posix") ever.

-- Isaac Schlueter on an official POSIX library

How does this affect us as developers interested in writing Unix software? The implications are that Node provides an opaque API layer that sits on top of the operating system, but this isn't quite true. Differences in Node's API between Windows and other operating systems are documented in Node's API documentation. One example is path.join, which will correctly use backslashes in Windows and forward slashes elsewhere.

Design Principles

Extrapolating Raymond's principles to Node development is an inspirational way to look at Node development. In my experience, writing monolithic applications with Node isn't a sound architectural approach. I've found breaking applications down into small modules and binaries that do one thing well is a good idea. Remember that npm modules don't have to be publicly released: set that private property to true in your package.json to ensure it isn't published.

I'd add another rule to Eric's list:

  • Rule of Sharing: Make supporting documentation, licensing, and tests clear and easy to find. Tests should be easy to run.

To allow people to easily run tests, include a "scripts": { "test": "make test" } so npm test can be used. Also, clearly license Node modules by adding something like this to package.json:

"licenses": [
    "type": "MIT +no-false-attribs",
    "url": "http://github.com/isaacs/npm/raw/master/LICENSE"

-- From npm's package.json

The Twelve-Factor App

Unix philosophy reminds me of The Twelve-Factor App by Adam Wiggins. This methodology is inspired by working on Heroku's platform, which runs hundreds of thousands of applications. Remember how I mentioned POSIX defines signals? Well, knowledge of signals comes in handy when writing applications that behave correctly on a platform like Heroku:

Processes shut down gracefully when they receive a SIGTERM signal from the process manager. For a web process, graceful shutdown is achieved by ceasing to listen on the service port (thereby refusing any new requests), allowing any current requests to finish, and then exiting.

-- From Disposability, The Twelve-Factor App

Running software "in the cloud" ultimately means running it on a platform with some level of POSIX compliance.


Unix might have its own culture and principles, but its philosophies can make us better Node developers. Write your next command-line application or daemon with Node, and you might be pleasantly surprised.