spmjs / node-scp2

[MAINTAINER WANTED] A pure javascript scp program based on ssh2.
385 stars 96 forks source link

"Write after End" when scping a directory #17

Closed Gooseus closed 9 years ago

Gooseus commented 9 years ago

I am attempting to copy a directory remotely using SSH and public-key method. It will work once, and then I get this on the next attempt to upload.

Error: write after end
    at writeAfterEnd (_stream_writable.js:132:12)
    at ChannelStream.Writable.write (_stream_writable.js:180:5)
    at SFTP._send (/usr/local/app/node_modules/scp2/node_modules/ssh2/lib/SFTP/SFTPv3.js:1017:23)
    at SFTP.stat (/usr/local/app/node_modules/scp2/node_modules/ssh2/lib/SFTP/SFTPv3.js:750:15)
    at /usr/local/app/node_modules/scp2/lib/client.js:134:12
    at Object.async.until (/usr/local/app/node_modules/async/lib/async.js:707:13)
    at /usr/local/app/node_modules/scp2/lib/client.js:130:11
    at Client.sftp (/usr/local/app/node_modules/scp2/lib/client.js:50:5)
    at Client.mkdir (/usr/local/app/node_modules/scp2/lib/client.js:119:8)
    at /usr/local/app/node_modules/scp2/lib/client.js:257:14

The app then restarts and I'm able to make the request once again. It seems like one of the streams being used isn't being closed correctly or isn't be recreated when the scp call is made again?

Gooseus commented 9 years ago

So I forked this and may have fixed locally... my suspicion was that it had to do with the Client being instantiated once as a singleton and being reused across multiple scp calls. So I made this change:

https://github.com/Gooseus/node-scp2/compare/lepture:master...master

var Client = require('./client').Client;

function cp2remote(client, src, dest, callback) {
...
}

function cp2local(client, src, dest, callback) {
...
}

exports = module.exports = require('./client');

exports.scp = function(src, dest, callback) {
  var client = new Client();
  var parsed = client.parse(src);

  client.on('error', callback);

  if (parsed.host && parsed.path) {
    cp2local(client, parsed, dest, callback);
  } else {
    cp2remote(client, src, dest, callback);
  }
})

So basically I create a new Client each time and pass that in to the cp functions. Might be a performance hit, but for my use case (and most I think) file copying is expected to be expensive.

Let me know if want me to shoot you a pull request for this or if you have other thoughts or concerns on my approach.

bschaepper commented 9 years ago

This is a problem for subsequent scp(...) calls too. Gooseus' fork does the trick.

lepture commented 9 years ago

Is it fixed by this pr https://github.com/lepture/node-scp2/pull/19 ?

toddtarsi commented 9 years ago

Yeah, it should at least. It resolved my issues performing multiple sequential scp actions.

bschaepper commented 9 years ago

Is there going to be an updated version available via npm any time soon? would be great :-)

lepture commented 9 years ago

@bschaepper 0.2.1 is released.