10 cli snippets

gracefully closing node.js applications via signal handling

To make your node.js application gracefully respond to shutdown signals, use process.on(SIGNAL,HANDLER).

For example, to respond to SIGINT (typically Ctrl-c), you can use:

process.on( "SIGINT", function() {
  console.log('CLOSING [SIGINT]');
  process.exit();
} );

Note that without the process.exit(), the program will not be shutdown. (This is you chance to override or "trap" the signal.)

Some common examples (in CoffeeScript):

process.on 'SIGHUP',  ()->console.log('CLOSING [SIGHUP]');  process.exit()
process.on 'SIGINT',  ()->console.log('CLOSING [SIGINT]');  process.exit()
process.on 'SIGQUIT', ()->console.log('CLOSING [SIGQUIT]'); process.exit()
process.on 'SIGABRT', ()->console.log('CLOSING [SIGABRT]'); process.exit()
process.on 'SIGTERM', ()->console.log('CLOSING [SIGTERM]'); process.exit()

PS: On Linux (and similar) you can enter kill -l on the command line to see a list of possible signals, and kill -N PID to send signal N to the process with process ID PID.

Published 8 Jan 2013

 

Check require.main to test if a Node.js file is run directly

In Node, when a file is run directly from the command line, require.main is set to its module. Hence require.main === module tells you whether or not your script was invoked directly or required by another file.

A JavaScript "main" idiom:

//#!/usr/bin/env node
// file: example.js

function main() {
  // ...
}

if(require.main === module) {
  main();
}

The main method will run if example.js is invoked via node example.js or ./example.js but not when required within another script (via require('./example'), for example).

A CoffeeScript "main" idiom (using classes, although it doesn't have to):

#!/usr/bin/env coffee
# file: example.coffee
class Example
  main:()->
    # ...

if require.main is module
  (new Example()).main()

The main method will run if example.coffee is invoked via coffee example.coffee or ./example.coffee but not when required within another script (via require('./example'), for example).

Also see the nodejs.org docs.

Published 3 Mar 2013

 

In node-optimist, argv._ is an array of the "extra" parameters

In substack's node-optimist, you can use argv._ to fetch any parameters remaining after optimist has done its parsing.

For example (in CoffeeScript):

# file: example.coffee
optimist = require 'optimist'
options = {
  'help' : { description:'Show this message and exit.', boolean:true, alias:'h' }
}
argv = optimist.usage('Usage: $0 [--help]', options).argv

# Now argv._ contains an array "extra" parameters, if any
console.log argv._

For example

coffee example.coffee --help

yields

[ ]

but either of

coffee example.coffee --help foo.txt bar.png

or

coffee example.coffee foo.txt bar.png

yield

[ "foo.txt", "bar.png" ]
Published 3 Mar 2013

 

Ruby-like ARGF for Node.js

tokuhirom's node-argf module offers a Ruby-like ARGF for Node.js.

Install via:

npm install argf

or by adding

{
  "dependencies" : {
    "argf" : "latest"
  }
}

to your package.json file.

Use ARGF like this:

ARGF = require('argf');
argf = new ARGF();  // create argf based on current
                    // command line parameters or
                    // input streams.

// register a callback for when all input data has been read
argf.on('finished', function() {
  console.log("Done processing all inputs.");
});

// process the input(s)
argf.forEach( function(line) {
  console.log("Read:",line);
  console.log("From source:",argv.stream.path);
}

Like Ruby's ARGF, the module assumes any elements in process.argv represent files to process (and uses the input stream if no files are provided.

You can also pass an array to new ARGF() to provide the list of files, which is handy if you're using something like node-optimist. (Note that in node-optimist you can use argv._ to get the remaining parameters after parsing.) For example:

optimist = require('optimist');
ARGF = require('argf');

options = {
  # ...
}
argv = optimist.usage('Usage: $0 ...', options).argv;

argf = new ARGF(argv._);

argf.on('finished', function() {
  console.log("Done processing all inputs.");
});

// process the input(s)
argf.forEach( function(line) {
  console.log("Read:",line);
  console.log("From source:",argv.stream.path);
}
Published 3 Mar 2013

 

Use 'less -S' for horizontal scrolling

The flag -S (or --chop-long-lines) will cause less to truncate lines at the screen (terminal) boundary, rather than wrapping as it does by default. You can then scroll horizontally (with the arrow keys, for example) to view the full lines when needed.

cat some_file_with_very_long_lines | less -S
Tagged bash, linux, one-liner and cli.

 

How to right-align text in your bash prompt

Right aligning text by padding with spaces

To have text in your bash prompt ($PS1) hug the right side of the terminal:

PS1="`printf "%${COLUMNS}s\n" "${TEXT}"`$PS1"

(This assumes you want the right-aligned text to appear before the rest of your prompt, if any. Move the $PS1 bit to the left side of the string to have the right-aligned text appear after the rest of your prompt.)

The ${COLUMNS} variable contains the number of columns in the current terminal (it should change if you resize the terminal). The ${TEXT} variable is a placeholder for the text you want to right-align.

The trick here is to use printf to left-pad the string to given width. printf "%ns" "text" will left-pad the given string (here, text) with spaces until the entire string is n characters wide.

Right aligning text by padding with something other than space.

Say you want to pad with - instead of space. Try:

PS1="`printf -vch "%${COLUMNS}s" "${TEXT}"; printf "%s" "${ch// /-}"`$PS1"

This will left-pad the ${TEXT} with spaces, as above, and then replace any spaces with -.

If you have any spaces in ${TEXT} you want to preserve, one hacky work-around is to mark spaces in $TEXT with some other character, say _, and then replace _ with a space () after the other substitution:

$ PS1="$PS1`printf -vch "%${COLUMNS}s" "${TEXT}"; printf -vch "%s" "${ch// /-}"; printf "%s\n" "${ch//_/ }"`"

Drawing a line to the end of the line

I recently added a line containing the date and time to my bash prompt (so I can tell when a given command completed) and wanted to draw a line across the rest of the screen to make it visually easier to tell where a new prompt is displayed. Something like this:

-- Tue 02-Oct-2012 05:19 PM --------------------------------

(Assuming the terminal is 60 characters wide.)

Here's how I did it.

Within my $PROMPT_COMMAND I execute the following:

line="`printf -vch "%${COLUMNS}s" ""; printf "%s" "${ch// /-}"`"
dts="`date +"-- %a %d-%b-%Y %I:%M %p "`"
PS1="$PS1\e[1m\e[32m${dts}${line:${#dts}}"

The first line creates a variable ($line) with ${COLUMNS} dashes (-). This line would span the length of the terminal.

The second line creates a variable ($dts) with my date and time format of choice (prefixed with -- just for kicks).

The ${dts}${line:${#dts}} bit in the third line displays my date and time string ($dts) and then a substring of $line, starting at the length of my date and time string (${#dts}). (In this particular case ${dts} is always exactly 28 characters long, so that value could be hard-coded but this way it works in the general case too.)

If you are curious, the \e[1m\e[32m bit makes the text bold (\e[1m) and green (\e[32m).

Tagged bash, linux and cli.

 

Pretty-print JSON with Python's json.tool

Pretty-print a JSON file using Python (v2.5+)'s built-in json.tool module:

cat MYFILE.json | python -m json.tool
Published 15 Feb 2014
Tagged python, json, cli and one-liner.

 

Python one-liner for reading a CSV file into a JSON array of arrays

Reading a CSV file into 2-d Python array (an array of arrays):

import csv
array = list(csv.reader(open( MYFILE.csv )))

Dumping that as JSON (via the command-line):

$ python -c "import json,csv;print json.dumps(list(csv.reader(open( CSV-FILENAME ))))"
Published 15 Feb 2014
Tagged python, json, cli and one-liner.

 

Launch an HTTP server serving the current directory using Python

The Python SimpleHTTPServer module makes it easy to launch a simple web server using a current working directory as the "docroot".

With Python 2:

python -m SimpleHTTPServer

or with Python 3:

python3 -m http.server

By default, each will bind to port 8080, hence http://localhost:8080/ will serve the top level of the working directory tree. Hit Ctrl-c to stop.

Both accept an optional port number:

python -m SimpleHTTPServer 3001

or

python3 -m http.server 3001

if you want to bind to something other than port 8080.

Published 20 Feb 2014
Tagged python, http, cli, one-liner, ops and tool.

 

Reading from input files or STDIN in Ruby using ARGF.

ARGF makes it easy for a Ruby script to read from STDIN, a file specified on the command-line argument or multiple files specified on the command line, all through the same interface.

Recall that ARGV array contains the arguments passed to your Ruby script on the command line.

ARGF assumes that any elements that remain in ARGV represent files. Methods like ARGF.each (accepting a block) and ARGF.readlines (returning an array) operate on the concatenation of all files found in ARGV. If ARGV is empty, then ARGF operates on STDIN instead.

For example, a cat-like program could be implemented in Ruby as:

ARGF.each_line { |line| puts line }

When working with optparse, use the parse! method to strip recognized "flag" parameters from ARGV, leaving only the files you want to operate so that ARGF works just like you want it to. For example:

require 'optparse'

options = { }
opt_parser = OptionParser.new do |opt|
  opt.banner = "Usage: #{$0} [OPTIONS]"
  opt.separator  ""
  opt.separator  "OPTIONS"

  opt.on("-h","--heading HEADING","a heading to display.") do |heading|
    options[:heading] = heading
  end

  opt.on("-v","--verbose","be more chatty") do
    options[:verbose] = true
  end
end
opt_parser.parse!

puts options[:heading] unless options[:heading].nil?
ARGF.each_line { |line| puts line }
Tagged ruby, dev and cli.

 

This page was generated at 4:16 PM on 26 Feb 2018.
Copyright © 1999 - 2018 Rodney Waldhoff.