@ashnazg/ssh

1.3.0 • Public • Published

title: "@ashnazg/ssh" sidebar_label: SSH

Usage

var ssh = require('@ashnazg/ssh'); // ~/projects/ashnazg-npm/ssh/ssh.js
ssh.verbosity(1); // optional. accepts these tiers:
// 0: quiet
// 1: print action headers
// 2: show rsync progress
// 3: print all close values

var {code, stdout, stderr, duration_ms} = ssh('user@server', 'echo foo');

// 'host' can also be {user:'foo', ip:'ip or dns'}

// options
ssh('host', 'cmd', {
	reject: true, // rejects on any exit value other than 0. set this to false on cmds where you WANT to grab all exit codes of your cmd. (ssh fails still throw.)

	connect_timeout: 5, // in seconds
	batch_mode: true, // die rather than have the ssh-client go into interactive "not in known_hosts" flow
	disable_hostkey_check: false, // RISKY see below

	inherit: false, // setting this to true will bind the ssh cmd's unix streams to your process's own -- nice for some CLI use cases
	stdio: [...], // for finer control than 'inherit', see node spawn stdio docs

	// probably just an internally used feature:
	onChildCreated(child) {
		// this is for manipulating the child process immediately upon creation. This is useful for things like streaming data to stdin.
	}
});

stream and execute bash script

You can run a bash script remotely:

ssh.script(host, '~/local/script/path', ['--script','--opts'])

note see ssh.write()'s stdio behavior. (note that I really need to fix that; script()'s caller needs to have the option of capturing stderr/out.)

You can run arbitrary large bash scripts without it being on disk or crammed into the CLI mode:

ssh(host, ['optional array of script args'], {stream: ['lots of bash']});
ssh(host, {stream: ['lines']});

NOTE stream mode takes over stdin (as well as out and err until I implement better stdio configurability)

rsync

note rsync's special behavior about whether the source path has a trailing slash.

If you're calling this from a CLI/terminal, note that verbosity(2) will automatically also set rsync's stdout to be your screen by forcing {inherit: true} to be on. You can disable that bit of behavior by setting {inherit} or {stdio} to anything that's not 'undefined'

ssh.rsync(host, '~/files/', '/remote/path');

write one file and set attributes

  • data can be a string, an array of strings, or a JSON-able object.
  • if you add an option of {chmod: 0600} it'll chmod the file.
  • {chown: 'user'} works in a similar fashion.
ssh.write(host, ['data'], remote_dest, {append: false, sudo: false, chmod: undefined, chown: undefined})
ssh.append(...) is the same but with {append: true} preconfigured

ssh.read(host, 'fn') returns 'raw file contents'

note: the above two do not respect {inherit} or {stdio} options, as they're overwriting those to use the file stream themselves.

test for connectivity

There's only one helper function that treats ssh connectivity problems as a resolve(true) instead of a rejection, and treats any cmd exit code as 'good enough'.

ssh.canSshAs('xander@server'); // like all of these, it also takes {user:'xander', ip:'server'}

To save on trips to the well, it also takes a command, so that if you are connecting, you get your next question answered as well. (I use this to figure out whether apt-get or yum is the package manager.) Note that canSshAs is similar to ssh.stdout.scalar() in that your command's stdout is trimmed and returned

ssh.canSshAs('x@s', {command: 'which apt-get yum'});
// result: '/usr/bin/apt-get'

A variation on the above that addes retries: ssh.waitForReadiness(host); will try 10 times, 5 seconds between timeouts and the next try. If it ever succeeds, the default command will return the path to apt-get or yum.

The optional configs specific to this function are:

ssh.waitForReadiness(host, {
	tries: 10,
	retry_delay: 5,
	initial_delay: 0,
	cmd: 'which apt-get yum'
});

If you're waiting for a newly provisioned box, and know it'll be N seconds before it could be responsibe, you can pass N as initial_delay so you're not waiting attempts too early.

Silly useful shorthand notations

These all have an optional trailing {options} that supports the above fields. Some like getVersion() also support the extra fields mentioned here.

ssh.stdout() returns "stdout" instead of {stdout, ...}
ssh.stdout.lines() returns ['std1', 'out2'] with all EOL delimiters removed
ssh.stdout.scalar() returns 'stdout' but with whitespace trimmed off both ends
ssh.exitCode() returns the integer instead of {code,...}
ssh.truthy() returns true if code=0
ssh.exists(host, filename) returns bool
ssh.install(host, package_name, options) just runs apt-get. (or the host's packager if host is a server record like {user,ip,packager})
ssh.isInPath(host, program_name) returns true if 'which' finds it in PATH
ssh.userExists(host, username) returns bool (it checks /etc/passwd)
ssh.getVersion(host, program_name, {line: 1}) returns a string. returns null if not found.

Release 1.3.0

  • meta now supports 'success'
  • mkdir now uses -mMODE
  • rejections now have at minimum {code,message} to be more error-like
  • added more tools, such as createUser, which can install rsa keys and sudoer powers on request.
    • ssh.canConnect
    • ssh.canSudo
    • ssh.waitForReadiness
    • ssh.userExists
    • ssh.setHostname
    • ssh.getVersion

Release 1.2.0

A complete rewrite, breaking every signature in the old version.

Release 0.1.0

Added:

  • ssh.canSshAs and waitForReadiness
  • ssh.stdout.lines (to the docs at least)
  • ssh.stdout.scalar

Readme

Keywords

none

Package Sidebar

Install

npm i @ashnazg/ssh

Weekly Downloads

4

Version

1.3.0

License

MIT

Unpacked Size

42.8 kB

Total Files

8

Last publish

Collaborators

  • xander