SFTP node crashes server, the other one is not working

Hi!

We are using node-red to transfer files to another server via sftp.

For that, we were using node-red-contrib-sftp (node) - Node-RED but this is now always only giving us "connecting" when we use the put function, without any debug or log output. (List and Get works)
We then tried another node (node-red-contrib-better-sftp (node) - Node-RED) and it even crashes the server with the following information in the log:

15 Sep 18:16:16 - [red] Uncaught Exception:
15 Sep 18:16:16 - [error] Error: : Connection ended unexpectedly by remote server
    at Object.formatError (/root/.node-red/node_modules/ssh2-sftp-client/src/utils.js:57:18)
    at Client.<anonymous> (/root/.node-red/node_modules/ssh2-sftp-client/src/index.js:1038:21)
    at Client.emit (node:events:513:28)
    at Socket.<anonymous> (/root/.node-red/node_modules/ssh2/lib/client.js:312:10)
    at Socket.emit (node:events:525:35)
    at endReadableNT (node:internal/streams/readable:1359:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
nodered.service: Main process exited, code=exited, status=1/FAILURE
nodered.service: Failed with result 'exit-code'.

As both nodes are not working: might this be connected to any dependency which both nodes are using but which is not working or any linux problem?

The admin of the server where we want to put files on via ssh says that neither our user, nor the ip of the server where node red runs on is blocked.
With the same credentials, we are able to login using filezilla / putty or other programs.

Thanks!

I had the same problem here, no solution found yet.

That node is VERY old. It references v2 of the support library - the current is v9!

So no great surprises that it isn't working I'm afraid.

You could try referencing the support library directly in a function node perhaps?

theophilusx/ssh2-sftp-client: a client for SSH2 SFTP (github.com)

I'm currently trying to use scp-promises - npm in a function node but had no success yet.

The node-sample imports CreateScpConnection from scp-promises but I wasn't able to do so in the node. (import { CreateScpConnection } from 'scp-promises')
I'm currently trying around with similar codes from How to make PDF from HTML - #4 by Steve-Mcl and Useage of contrib-npm - #6 by bakman2 provided by @Steve-Mcl and @bakman2 (things like const { scpPromises } = new CreateScpConnection("");) and so on instead of using "import".

Also, I need to find a way to set the path and filename based on msgs.

Try...

const scp = scpPromises.CreateScpConnection(...

If that doesn't work then try putting a node warn in there to figure out what is what...

node.warn({scpPromises})

Note: I am assuming you have named the npm import on the setup tab as scpPromises

Thanks!

With scp-promises it didn't work, but it seems to work with node-scp:

const Client = nodeScp.Client;

async function test() {
  try {
    const client = await Client({
      host: 'hostname',
      port: 22,
      username: 'user',
      password: 'pw',
      // privateKey: fs.readFileSync('./key.pem'),
      // passphrase: 'your key passphrase',
    })
    await client.uploadFile(
      '/sourcefile.csv',
      '/destinationfile.csv',
      // options?: TransferOptions
    )
    // you can perform upload multiple times
    //await client.uploadFile('./test1.txt', '/workspace/test1.txt')
    client.close() // remember to close connection after you finish
  } catch (e) {
    console.log(e)
  }
}

test()

return msg;

I will now try to dynamically set sourcefile and destinationfile.

1 Like

Ok here is the working flow with dynamic paths:

[
    {
        "id": "7cfd133f7dc601d4",
        "type": "function",
        "z": "bf69329bcb962369",
        "name": "scp put 2",
        "func": "const Client = nodeScp.Client;\nconst remotepath = msg.remotepath;\nconst sourcepath = msg.sourcepath;\n\nasync function test() {\n  try {\n    const client = await Client({\n      host: 'host',\n      port: 22,\n      username: 'un',\n      password: 'pw',\n      // privateKey: fs.readFileSync('./key.pem'),\n      // passphrase: 'your key passphrase',\n    })\n    await client.uploadFile(sourcepath, remotepath)\n    // you can perform upload multiple times\n    //await client.uploadFile('./test1.txt', '/workspace/test1.txt')\n    client.close() // remember to close connection after you finish\n  } catch (e) {\n    console.log(e)\n  }\n}\n\ntest()\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [
            {
                "var": "nodeScp",
                "module": "node-scp"
            },
            {
                "var": "ssh2",
                "module": "ssh2"
            }
        ],
        "x": 800,
        "y": 780,
        "wires": [
            [
                "b56b8a9d3f8410fd"
            ]
        ]
    },
    {
        "id": "42a1217fd3ada431",
        "type": "inject",
        "z": "bf69329bcb962369",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 400,
        "y": 780,
        "wires": [
            [
                "be49f9ed614eacc1"
            ]
        ]
    },
    {
        "id": "b56b8a9d3f8410fd",
        "type": "debug",
        "z": "bf69329bcb962369",
        "name": "debug 52",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1020,
        "y": 780,
        "wires": []
    },
    {
        "id": "be49f9ed614eacc1",
        "type": "change",
        "z": "bf69329bcb962369",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "sourcepath",
                "pt": "msg",
                "to": "/home/test.csv",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "remotepath",
                "pt": "msg",
                "to": "/remote/test.csv",
                "tot": "str"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 600,
        "y": 780,
        "wires": [
            [
                "7cfd133f7dc601d4"
            ]
        ]
    }
]
const Client = nodeScp.Client;
const remotepath = msg.remotepath;
const sourcepath = msg.sourcepath;

async function test() {
  try {
    const client = await Client({
      host: 'host',
      port: 22,
      username: 'un',
      password: 'pw',
      // privateKey: fs.readFileSync('./key.pem'),
      // passphrase: 'your key passphrase',
    })
    await client.uploadFile(sourcepath, remotepath)
    // you can perform upload multiple times
    //await client.uploadFile('./test1.txt', '/workspace/test1.txt')
    client.close() // remember to close connection after you finish
  } catch (e) {
    console.log(e)
  }
}

test()

return msg;
2 Likes

If you want to see/catch errors in node-red, change the above to...

node.error(e, msg)
1 Like