It is important to recognise that the current remote directory may not always be what you may expect. A lot will depend on the remote platform of the SFTP server and how the SFTP server has been configured. When things don't seem to be working as expected, it is often a good idea to verify your assumptions regarding the remote directory and remote paths. One way to do this is to login using a command line program like sftp or lftp.
This module is based on the excellent SSH2 module. That module is a general SSH2 client and server library and provides much more functionality than just SFTP connectivity. Many of the connect options provided by that module are less relevant for SFTP connections. It is recommended you keep the config options to the minimum needed and stick to the options listed in the commonOpts below.
The retries, retry_factor and retry_minTimeout options are not part of the SSH2 module. These are part of the configuration for the retry package and what is used to enable retrying of sftp connection attempts. See the documentation for that package for an explanation of these values.
This method uses the openssh POSIX rename extension introduced in OpenSSH 4.8. The advantage of this version of rename over standard SFTP rename is that it is an atomic operation and will allow renaming a resource where the destination name exists. The POSIX rename will also work on some file systems which do not support standard SFTP rename because they don't support the system hardlink() call. The POSIX rename extension is available on all openSSH servers from 4.8 and some other implementations. This is an extension to the standard SFTP protocol and therefore is not supported on all sftp servers.
The upload process also emits 'upload' events. These events are fired for each successfully uploaded file. The upload event calls listeners with 1 argument, an object which has properties source and destination. The source property is the path of the file uploaded and the destination property is the path to where the file was uploaded. The purpose of this event is to provide some way for client code to get feedback on the upload progress. You can add your own listener using the on() method.
Although normally not required, you can add and remove custom listeners on the ssh2 client object. This object supports a number of events, but only a few of them have any meaning in the context of SFTP. These are
All SFTP servers and platforms are not equal. Some facilities provided by ssh2-sftp-client either depend on capabilities of the remote server or the underlying capabilities of the remote server platform. As an example, consider chmod(). This command depends on a remote file system which implements the 'nix' concept of users and groups. The win32 platform does not have the same concept of users and groups, so chmod() will not behave in the same way.
One way to determine whether an issue you are encountering is due to ssh2-sftp-client or due to the remote server or server platform is to use a simple CLI sftp program, such as openSSH's sftp command. If you observe the same behaviour using plain sftp on the command line, the issue is likely due to server or remote platform limitations. Note that you should not use a GUI sftp client, like Filezilla or winSCP as such GUI programs often attempt to hide these server and platform incompatibilities and will take additional steps to simulate missing functionality etc. You want to use a CLI program which does as little as possible.
To see an example of the type of issues you can observe with fastPut() or fastGet(), have a look at issue 407, which describes the experiences of one user. Bottom line, when it works, it tends to work well and be significantly faster than using just get() or put(). However, when developing code to run against different SFTP servers, especially where you are unable to test against each server, you are likely better off just using get() and put() or structuring your code so that users can select which method to use (this is what ssh2-sftp-client does - for example, see the !downloadDir() and uploadDir() methods.
To handle this, ssh2-sftp-client implements a couple of strategies. Firstly, when you call one of the module's methods, it adds error, end and close event listeners which will call the reject method on the enclosing promise. It also keeps track of whether an error has been handled and if it has, it ignores any subsequent errors until the promise ends. Typically, the first error caught has the most relevant information and any subsequent error events are less critical or informative, so ignoring them has no negative impact. Provided one of the events is raised before the promise is fulfilled, these handlers will consume the event and deal with it appropriately.
In addition to the promise based event handlers, ssh2-sftp-client also implements global event handlers which will catch any error, end or close events. Essentially, these global handlers only reset the sftp property of the client object, effectively ensuring any subsequent calls are rejected and in the case of an error, send the error to the console.
It appears that when the sftp server is running on Windows, a ECONNRESET error signal is raised when the end() method is called. Unfortunately, this signal is raised after a considerable delay. This means we cannot remove the error handler used in the end() promise as otherwise you will get an uncaught exception error. Leaving the handler in place, even though we will ignore this error, solves that issue, but unfortunately introduces a new problem. Because we are not removing the listener, if you re-use the client object for subsequent connections, an additional error handler will be added. If this happens more than 11 times, you will eventually see the Node warning about a possible memory leak. This is because node monitors the number of error handlers and if it sees more than 11 added to an object, it assumes there is a problem and generates the warning.
Clients first make an unauthenticated connection to the SFTP server to begin negotiation of protocol settings (cipher, authentication method etc). If you are creating multiple connections in a script, it is easy to exceed the limit, resulting in some connections being dropped. As SSH2 only raises an 'end' event for these dropped connections, no error is detected. The ssh2-sftp-client now listens for end events during the connection process and if one is detected, will reject the connection promise.
Some users have encountered the error 'Timeout while waiting for handshake' or 'Handshake failed, no matching client->server ciphers. This is often due to the client not having the correct configuration for the transport layer algorithms used by ssh2. One of the connect options provided by the ssh2 module is algorithm, which is an object that allows you to explicitly set the key exchange, ciphers, hmac and compression algorithms as well as server host key used to establish the initial secure connection. See the SSH2 documentation for details. Getting these parameters correct usually resolves the issue.
When encountering this type of problem, one worthwhile approach is to use openSSH's CLI sftp program with the -v switch to raise logging levels. This will show you what algorithms the CLI is using. You can then use this information to match the names with the accepted algorithm names documented in the ssh2 README to set the properties in the algorithms object.
A symptom of this issue is that you are able to upload small files, but uploading larger ones fail. You probably have an MTU/fragmentation problem. For each network interface on both client and server set the MTU to 576, e.g. ifconfig eth0 mtu 576. If that works, you need to find the largest MTU which will work for your network. An MTU which is too small will adversely affect throughput speed. A common value to use is an MTU of 1400.
The ssh2-sftp-client module is essentially a wrapper around the ssh2 and ssh2-streams modules, providing a higher level promise based API. When you run into issues, it is important to try and determine where the issue lies - either in the ssh2-sftp-client module or the underlying ssh2 and ssh2-streams modules. One way to do this is to first identify a minimal reproducible example which reproduces the issue. Once you have that, try to replicate the functionality just using the ssh2 and ssh2-streams modules. If the issue still occurs, then you can be fairly confident it is something related to those later 2 modules and therefore and issue which should be referred to the maintainer of that module.
The ssh2 and ssh2-streams modules are very solid, high quality modules with a large user base. Most of the time, issues with those modules are due to client misconfiguration. It is therefore very important when trying to diagnose an issue to also check the documentation for both ssh2 and ssh2-streams. While these modules have good defaults, the flexibility of the ssh2 protocol means that not all options are available by default. You may need to tweak the connection options, ssh2 algorithms and ciphers etc for some remote servers. The documentation for both the ssh2 and ssh2-streams module is quite comprehensive and there is lots of valuable information in the issue logs.
If you run into an issue which is not repeatable with just the ssh2 and ssh2-streams modules, then please log an issue against the ssh2-sftp-client module and I will investigate. Please note the next section on logging issues.
Note also that in the repository there are two useful directories. The first is the examples directory, which contain some examples of using ssh2-sftp-client to perform common tasks. A few minutes reviewing these examples can provide that additional bit of detail to help fix any problems you are encountering.
The second directory is the validation directory. I have some very simple scripts in this directory which perform basic tasks using only the ssh2 modules (no ssh2-sftp-client module). These can be useful when trying to determine if the issue is with the underlying ssh2 module or the ssh2-sftp-client wrapper module. 59ce067264