Coding

Restart Upstart Instances on System Reboot

A single Upstart job can have multiple instances running:

1
2
3
$ sudo start my-job port=4000
$ sudo start my-job port=4001
$ sudo start my-job port=4002

However, when the operating system reboots, the job with multiple instances will fail to start, due to instance information is not provided to the job. We can fix this problem by adding a for loop in the script section:

1
2
3
4
5
6
7
8
9
start on (local-filesystems and net-device-up IFACE!=lo)
stop on shutdown
script
for i in `seq 4000 4002`
do
exec /path/to/my/job
done
end script

With this Upstart job, we do not need to provide instance information:

1
$ sudo start my-job

Therefore, during system restart, the job will initiate automatically.

Synchronous Console Methods

In Node v0.10.x, the console functions are synchronous when the destination is a terminal or a file (to avoid lost messages in case of premature exit) and asynchronous when it’s a pipe (to avoid blocking for long periods of time). See console. We can test it with the following script:

Dirname Does Not Follow Symlink

Node’s global object __dirname returns the name of the directory that the currently executing script resides in. However, if a directory is symbolic linked or a symlink, it still return the original path.

For example, the following directory structure:

1
2
3
4
5
6
7
8
/tmp/dirname/
├── foo
│ └── app.js
└── lib
├── bar -> ../foo
└── util.js
3 directories, 2 files

The app.js contains the following line:

1
console.log(__dirname);

Run the script:

1
2
$ cd /tmp/dirname/foo && node app.js
/tmp/dirname/foo

You get the directory the app.js script is residing it. But if you do the same from the symlinked directory:

1
2
$ cd /tmp/dirname/lib/bar && node app.js
/tmp/dirname/foo

Well, you get the same answer, even the current working directory is different:

1
2
$ cd /tmp/dirname/lib/bar && pwd
/tmp/dirname/lib/bar

The return of __dirname does not follow symbolic link.

So, have to be extra careful when requiring files that is symbolic linked. If you think you are in lib/bar directory and try to require the util.js script in app.js:

1
2
3
var path = require('path');
console.log(require('../util'));
console.log(require(path.join(__dirname, '..', 'util')));

Both statements will throw module not found error. Path join does not help either.

The best practice is to avoid symlinks and relative directory requiring. Instead, set up required as modules, and install them in node_modules directory, then they will become top-level modules.