# node-ssh **Repository Path**: dawdler/node-ssh ## Basic Information - **Project Name**: node-ssh - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-11 - **Last Updated**: 2020-12-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README Node-SSH - SSH2 with Promises ========= Node-SSH is an extremely lightweight Promise wrapper for [ssh2][ssh2]. #### Example ```js const fs = require('fs') const path = require('path') const {NodeSSH} = require('node-ssh') const ssh = new NodeSSH() ssh.connect({ host: 'localhost', username: 'steel', privateKey: '/home/steel/.ssh/id_rsa' }) /* Or ssh.connect({ host: 'localhost', username: 'steel', privateKey: fs.readFileSync('/home/steel/.ssh/id_rsa', 'utf8') }) if you want to use the raw string as private key */ .then(function() { // Local, Remote ssh.putFile('/home/steel/Lab/localPath', '/home/steel/Lab/remotePath').then(function() { console.log("The File thing is done") }, function(error) { console.log("Something's wrong") console.log(error) }) // Array string, 'remote' => string)> ssh.putFiles([{ local: '/home/steel/Lab/localPath', remote: '/home/steel/Lab/remotePath' }]).then(function() { console.log("The File thing is done") }, function(error) { console.log("Something's wrong") console.log(error) }) // Local, Remote ssh.getFile('/home/steel/Lab/localPath', '/home/steel/Lab/remotePath').then(function(Contents) { console.log("The File's contents were successfully downloaded") }, function(error) { console.log("Something's wrong") console.log(error) }) // Putting entire directories const failed = [] const successful = [] ssh.putDirectory('/home/steel/Lab', '/home/steel/Lab', { recursive: true, concurrency: 10, // ^ WARNING: Not all servers support high concurrency // try a bunch of values and see what works on your server validate: function(itemPath) { const baseName = path.basename(itemPath) return baseName.substr(0, 1) !== '.' && // do not allow dot files baseName !== 'node_modules' // do not allow node_modules }, tick: function(localPath, remotePath, error) { if (error) { failed.push(localPath) } else { successful.push(localPath) } } }).then(function(status) { console.log('the directory transfer was', status ? 'successful' : 'unsuccessful') console.log('failed transfers', failed.join(', ')) console.log('successful transfers', successful.join(', ')) }) // Command ssh.execCommand('hh_client --json', { cwd:'/var/www' }).then(function(result) { console.log('STDOUT: ' + result.stdout) console.log('STDERR: ' + result.stderr) }) // Command with escaped params ssh.exec('hh_client', ['--json'], { cwd: '/var/www', stream: 'stdout', options: { pty: true } }).then(function(result) { console.log('STDOUT: ' + result) }) // With streaming stdout/stderr callbacks ssh.exec('hh_client', ['--json'], { cwd: '/var/www', onStdout(chunk) { console.log('stdoutChunk', chunk.toString('utf8')) }, onStderr(chunk) { console.log('stderrChunk', chunk.toString('utf8')) }, }) }) ``` #### API ```ts // API reference in Typescript typing format: import { Client, ConnectConfig, ClientChannel, SFTPWrapper, ExecOptions, PseudoTtyOptions | ShellOptions } from 'ssh2'; import { Prompt, TransferOptions } from 'ssh2-streams'; // ^ You do NOT need to import these package, these are here for reference of where the // types are coming from. declare type Config = ConnectConfig & { host?: string; port?: number; username?: string; password?: string; privateKey?: string; passphrase?: string; tryKeyboard?: boolean; onKeyboardInteractive?: ( name: string, instructions: string, lang: string, prompts: Prompt[], finish: (responses: string[]) => void ) => void; }; interface SSHExecCommandOptions { cwd?: string; stdin?: string; execOptions?: ExecOptions; encoding?: BufferEncoding; onChannel?: (clientChannel: ClientChannel) => void; onStdout?: (chunk: Buffer) => void; onStderr?: (chunk: Buffer) => void; } interface SSHExecCommandResponse { stdout: string; stderr: string; code: number | null; signal: string | null; } interface SSHExecOptions extends SSHExecCommandOptions { stream?: 'stdout' | 'stderr' | 'both'; } interface SSHPutFilesOptions { sftp?: SFTPWrapper | null; concurrency?: number; transferOptions?: TransferOptions; } interface SSHGetPutDirectoryOptions extends SSHPutFilesOptions { tick?: (localFile: string, remoteFile: string, error: Error | null) => void; validate?: (path: string) => boolean; recursive?: boolean; } class NodeSSH { connection: Client | null; connect(config: Config): Promise; isConnected(): boolean; requestShell( options?: PseudoTtyOptions | ShellOptions | false ): Promise; withShell( callback: (channel: ClientChannel) => Promise, options?: PseudoTtyOptions | ShellOptions | false ): Promise; requestSFTP(): Promise; withSFTP( callback: (sftp: SFTPWrapper) => Promise ): Promise; execCommand( command: string, options?: SSHExecCommandOptions ): Promise; exec( command: string, parameters: string[], options?: SSHExecOptions & { stream?: 'stdout' | 'stderr'; } ): Promise; exec( command: string, parameters: string[], options?: SSHExecOptions & { stream: 'both'; } ): Promise; mkdir( path: string, method?: 'sftp' | 'exec', sftp?: SFTPWrapper | null ): Promise; getFile( localFile: string, remoteFile: string, sftp?: SFTPWrapper | null, transferOptions?: TransferOptions | null ): Promise; putFile( localFile: string, remoteFile: string, sftp?: SFTPWrapper | null, transferOptions?: TransferOptions | null ): Promise; putFiles(files: Array<{ local: string; remote: string; }>, options?: SSHPutFilesOptions): Promise; putDirectory( localDirectory: string, remoteDirectory: string, options?: SSHGetPutDirectoryOptions ): Promise; getDirectory( localDirectory: string, remoteDirectory: string, options?: SSHGetPutDirectoryOptions ): Promise; dispose(): void; } module.exports = NodeSSH; ``` ### Keyboard-interactive user authentication In some cases you have to enable keyboard-interactive user authentication. Otherwise you will get an `All configured authentication methods failed` error. #### Example: ```js const password = 'test' ssh.connect({ host: 'localhost', username: 'steel', port: 22, password, tryKeyboard: true, }) // Or if you want to add some custom keyboard-interactive logic: ssh.connect({ host: 'localhost', username: 'steel', port: 22, tryKeyboard: true, onKeyboardInteractive(name, instructions, instructionsLang, prompts, finish) { if (prompts.length > 0 && prompts[0].prompt.toLowerCase().includes('password')) { finish([password]) } } }) ``` For further information see: https://github.com/mscdex/ssh2/issues/604 ### License This project is licensed under the terms of MIT license. See the LICENSE file for more info. [ssh2]:https://github.com/mscdex/ssh2