Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

add REPL config, help, and document #12

Closed
wants to merge 7 commits into from

5 participants

@jeffbski

Provide ability to configure REPL via config.

  • repl - where to have REPL listen, defaults to env.CLUSTER_MASTER_REPL || 'cluster-master-socket'
    • if repl is null or false - REPL is disabled and will not be started
    • if repl is string path - REPL will listen on unix domain socket to this path
    • if repl is an integer port - REPL will listen on TCP 0.0.0.0:port
    • if repl is an object with address and port, then REPL will listen on TCP address:PORT

Examples of configuring repl

var config = { repl: false }                       // disable REPL
var config = { repl: '/tmp/cluster-master-sock' }  // unix domain socket
var config = { repl: 3001 }                        // tcp socket 0.0.0.0:3001
var config = { repl: { address: '127.0.0.1', port: 3002 }}  // tcp 127.0.0.1:3002

Provide help command within the REPL

Document REPL use

mcculloughsean and others added some commits
@mcculloughsean mcculloughsean Add info about the sweet REPL in the README
Describe how you use the REPL, how to change the path of the socket,
and lists commands you can use in the REPL
f554ef5
@jeffbski jeffbski add nc as possible client 4dedfd2
@jeffbski jeffbski add help to REPL and update README 754bd6c
@jeffbski jeffbski make REPL location configurable with options
Allow `repl` config option passed into clusterMaster constructor

* `repl` - where to have REPL listen, defaults to `env.CLUSTER_MASTER_REPL` || 'cluster-master-socket'
  * if `repl` is null or false - REPL is disabled and will not be started
  * if `repl` is string path - REPL will listen on unix domain socket to this path
  * if `repl` is an integer port - REPL will listen on TCP 0.0.0.0:port
  * if `repl` is an object with `address` and `port`, then REPL will listen on TCP address:PORT
5ed6ceb
@jeffbski jeffbski provide repl config examples 2becf97
@jeffbski jeffbski change REPL quit to stop
Since quit is a common command to exit certain
types of command shells, I felt it would be better
to use a different name for stopping the cluster,
since it would be easy to get confused and accidentally
shut down the cluster when simply wanting to exit the
REPL shell.

I switched the REPL command to stop() for a graceful
shutdown and a kill() for stopping hard.
bc6f53e
@jeffbski jeffbski add .exit to list of REPL commands
Although Control-D can be used, for some users it would
be good for them to know that they can also just type
`.exit`
6bf801b
@jeffbski

Since it had been a long time since this pull request was created and hadn't yet been merged, I finally published my fork in npm as cluster-master-ext so it would be available I npm.

My fork is at https//github.com/jeffbski/cluster-master

@isaacs
Owner

Sorry for the long delay. Landed and published as v0.2.0

@isaacs isaacs closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 8, 2013
  1. @mcculloughsean

    Add info about the sweet REPL in the README

    mcculloughsean authored
    Describe how you use the REPL, how to change the path of the socket,
    and lists commands you can use in the REPL
Commits on Jan 15, 2013
  1. @jeffbski

    add nc as possible client

    jeffbski authored
Commits on Jan 16, 2013
  1. @jeffbski
  2. @jeffbski

    make REPL location configurable with options

    jeffbski authored
    Allow `repl` config option passed into clusterMaster constructor
    
    * `repl` - where to have REPL listen, defaults to `env.CLUSTER_MASTER_REPL` || 'cluster-master-socket'
      * if `repl` is null or false - REPL is disabled and will not be started
      * if `repl` is string path - REPL will listen on unix domain socket to this path
      * if `repl` is an integer port - REPL will listen on TCP 0.0.0.0:port
      * if `repl` is an object with `address` and `port`, then REPL will listen on TCP address:PORT
  3. @jeffbski

    provide repl config examples

    jeffbski authored
Commits on Jan 17, 2013
  1. @jeffbski

    change REPL quit to stop

    jeffbski authored
    Since quit is a common command to exit certain
    types of command shells, I felt it would be better
    to use a different name for stopping the cluster,
    since it would be easy to get confused and accidentally
    shut down the cluster when simply wanting to exit the
    REPL shell.
    
    I switched the REPL command to stop() for a graceful
    shutdown and a kill() for stopping hard.
Commits on Jan 28, 2013
  1. @jeffbski

    add .exit to list of REPL commands

    jeffbski authored
    Although Control-D can be used, for some users it would
    be good for them to know that they can also just type
    `.exit`
This page is out of date. Refresh to see the latest.
Showing with 107 additions and 9 deletions.
  1. +56 −0 README.md
  2. +51 −9 cluster-master.js
View
56 README.md
@@ -88,4 +88,60 @@ The `exec`, `env`, `argv`, and `silent` configs are passed to the
* `onMessage` - Method that gets called when workers send a message to
the parent. Called in the context of the worker, so you can reply by
looking at `this`.
+* `repl` - where to have REPL listen, defaults to `env.CLUSTER_MASTER_REPL` || 'cluster-master-socket'
+ * if `repl` is null or false - REPL is disabled and will not be started
+ * if `repl` is string path - REPL will listen on unix domain socket to this path
+ * if `repl` is an integer port - REPL will listen on TCP 0.0.0.0:port
+ * if `repl` is an object with `address` and `port`, then REPL will listen on TCP address:PORT
+
+Examples of configuring `repl`
+
+```javascript
+var config = { repl: false } // disable REPL
+var config = { repl: '/tmp/cluster-master-sock' } // unix domain socket
+var config = { repl: 3001 } // tcp socket 0.0.0.0:3001
+var config = { repl: { address: '127.0.0.1', port: 3002 }} // tcp 127.0.0.1:3002
+```
+
+Note: be careful when using TCP for your REPL since anyone on the
+network can connect to your REPL (no security). So either disable
+the REPL or use a unix domain socket which requires local access
+(or ssh access) to the server.
+
+## REPL
+
+Cluster-master provides a REPL into the master process so you can inspect
+the state of your cluster. By default the REPL is accessible by a socket
+written to the root of the directory, but you can override it with the
+`CLUSTER_MASTER_REPL` environment variable. You can access the REPL with
+nc or [socat](http://www.dest-unreach.org/socat/) like so:
+
+
+```bash
+nc -U ./cluster-master-socket
+
+# OR
+
+socat ./cluster-master-socket stdin
+```
+
+The REPL provides you with access to these objects or functions:
+
+* `help` - display these commands
+* `repl` - access the REPL
+* `resize(n)` - resize the cluster to `n` workers
+* `restart(cb)` - gracefully restart workers, cb is optional
+* `stop()` - gracefully stop workers and master
+* `kill()` - forcefully kill workers and master
+* `cluster` - node.js cluster module
+* `size` - current cluster size
+* `connections` - number of REPL connections to master
+* `workers` - current workers
+* `select(fld)` - map of id to `field` (from workers)
+* `pids` - map of id to pids
+* `ages` - map of id to worker ages
+* `states` - map of id to worker states
+* `debug(a1)` - output `a1` to stdout and all REPLs
+* `sock` - this REPL socket'
+* `.exit` - close this connection to the REPL
View
60 cluster-master.js
@@ -9,6 +9,7 @@ var cluster = require("cluster")
, os = require("os")
, onmessage
, repl = require('repl')
+, replAddressPath = process.env.CLUSTER_MASTER_REPL || 'cluster-master-socket'
, net = require('net')
, fs = require('fs')
, util = require('util')
@@ -54,6 +55,8 @@ function clusterMaster (config) {
cluster._clusterMaster = module.exports
+ if (typeof config.repl !== 'undefined') replAddressPath = config.repl // allow null and false
+
onmessage = config.onMessage || config.onmessage
clusterSize = config.size || os.cpus().length
@@ -75,7 +78,7 @@ function clusterMaster (config) {
forkListener()
// now make it the right size
- debug('resize and then setup repl')
+ debug((replAddressPath) ? 'resize and then setup repl' : 'resize')
resize(setupRepl)
}
@@ -89,11 +92,19 @@ function select (field) {
}
function setupRepl () {
+ if (!replAddressPath) return // was disabled
+
debug('setup repl')
- var socket = path.resolve('cluster-master-socket')
- if (process.env.CLUSTER_MASTER_REPL) {
- socket = process.env.CLUSTER_MASTER_REPL
+ var socket = null
+ var socketAddress = undefined
+ if (typeof replAddressPath === 'string') {
+ socket = path.resolve(replAddressPath)
+ } else if (typeof replAddressPath === 'number') {
+ socket = replAddressPath
if (!isNaN(socket)) socket = +socket
+ } else if (replAddressPath.address && replAddressPath.port) {
+ socket = replAddressPath.port
+ socketAddress = replAddressPath.address
}
var connections = 0
@@ -108,7 +119,7 @@ function setupRepl () {
function startRepl () {
var sockId = 0
- net.createServer(function (sock) {
+ var replServer = net.createServer(function (sock) {
connections ++
replEnded = false
@@ -117,18 +128,41 @@ function setupRepl () {
sock.write('Starting repl #' + sock.id)
var r = repl.start({
- prompt: 'ClusterMaster ' + process.pid + ' ' + sock.id + '> ',
+ prompt: 'ClusterMaster (`help` for cmds) ' + process.pid + ' ' + sock.id + '> ',
input: sock,
output: sock,
terminal: true,
useGlobal: false,
ignoreUndefined: true
})
+
+ var helpCommands = [
+ 'help - display these commands',
+ 'repl - access the REPL',
+ 'resize(n) - resize the cluster to `n` workers',
+ 'restart(cb) - gracefully restart workers, cb is optional',
+ 'stop() - gracefully stop workers and master',
+ 'kill() - forcefully kill workers and master',
+ 'cluster - node.js cluster module',
+ 'size - current cluster size',
+ 'connections - number of REPL connections to master',
+ 'workers - current workers',
+ 'select(fld) - map of id to field (from workers)',
+ 'pids - map of id to pids',
+ 'ages - map of id to worker ages',
+ 'states - map of id to worker states',
+ 'debug(a1) - output `a1` to stdout and all REPLs',
+ 'sock - this REPL socket',
+ '.exit - close this connection to the REPL'
+ ]
+
var context = {
+ help: helpCommands,
repl: r,
resize: resize,
restart: restart,
- quit: quit,
+ stop: quit,
+ kill: quitHard,
cluster: cluster,
get size () {
return clusterSize
@@ -186,9 +220,17 @@ function setupRepl () {
delete debugStreams['repl-' + sockId]
}
- }).listen(socket, function () {
- debug('ClusterMaster repl listening on '+socket)
})
+
+ if (socketAddress) {
+ replServer.listen(socket, socketAddress, function () {
+ debug('ClusterMaster repl listening on '+socketAddress+':'+socket)
+ })
+ } else {
+ replServer.listen(socket, function () {
+ debug('ClusterMaster repl listening on '+socket)
+ })
+ }
}
}
Something went wrong with that request. Please try again.