Send command to child process in execute node (spawn mode)

I am using the exec node while enabling the "Use spawn() instead of exec()?" option. I am running a command that starts a child process and waits for input (child process stays on until I send it an exit command or kill it). Is there a way to send input and interact with that open child process by the exec node?

There are many examples I have run into where I need to do this. One example is interacting with the bluetooth service on a raspi or other boards. For example, I first send the command bluetoothctl and then it takes me inside the bluetooth service so I can run other commands like scan on and so forth.

I prefer to avoid installing additional nodes and just work with what I have as much as possible.

Thank you all in advance!

The node-red-node-daemon node is designed exactly for this situation. It runs a "long running" process and accepts input to STDIN and provides STDOUT, STDERR like the exec node does. It can also be stopped and restarted if required.

Thanks a lot for the quick response! I am having trouble understanding how to use this node. So for example I would like to run the service bluetoothctl, then once it starts I want to send scan on and after 10 seconds I want to send scan off. Can you give me an example on how to do that? I am only able to send the one command bluetoothctl and it says "running" but then I am not sure how to give it inputs.

Thanks!

For anyone searching on how to use node-red-node-daemon, I was able to run the following flow:

[
    {
        "id": "d11658f.c1db3a8",
        "type": "daemon",
        "z": "40e3fdb6.e6a084",
        "name": "",
        "command": "bluetoothctl",
        "args": "",
        "autorun": true,
        "cr": true,
        "redo": false,
        "op": "string",
        "closer": "SIGKILL",
        "x": 630,
        "y": 300,
        "wires": [
            [
                "65928ac7.b26974"
            ],
            [
                "e7c54ebb.12f6a"
            ],
            []
        ]
    },
    {
        "id": "65928ac7.b26974",
        "type": "debug",
        "z": "40e3fdb6.e6a084",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 830,
        "y": 280,
        "wires": []
    },
    {
        "id": "e7c54ebb.12f6a",
        "type": "debug",
        "z": "40e3fdb6.e6a084",
        "name": "",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 830,
        "y": 320,
        "wires": []
    },
    {
        "id": "b6fc1973.31fc18",
        "type": "function",
        "z": "40e3fdb6.e6a084",
        "name": "scan on",
        "func": "msg.payload = \"scan on\";\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 420,
        "y": 260,
        "wires": [
            [
                "d11658f.c1db3a8"
            ]
        ]
    },
    {
        "id": "71b7a856.565ab8",
        "type": "inject",
        "z": "40e3fdb6.e6a084",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "10",
        "x": 250,
        "y": 260,
        "wires": [
            [
                "b6fc1973.31fc18"
            ]
        ]
    },
    {
        "id": "d0bc951f.f43408",
        "type": "function",
        "z": "40e3fdb6.e6a084",
        "name": "scan off",
        "func": "msg.payload = \"scan off\";\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 420,
        "y": 300,
        "wires": [
            [
                "d11658f.c1db3a8"
            ]
        ]
    },
    {
        "id": "63229653.4905d8",
        "type": "inject",
        "z": "40e3fdb6.e6a084",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "15",
        "x": 250,
        "y": 300,
        "wires": [
            [
                "d0bc951f.f43408"
            ]
        ]
    },
    {
        "id": "97591bdd.4c27b8",
        "type": "function",
        "z": "40e3fdb6.e6a084",
        "name": "exit",
        "func": "msg.payload = \"exit\";\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 430,
        "y": 340,
        "wires": [
            [
                "d11658f.c1db3a8"
            ]
        ]
    },
    {
        "id": "ea126e2c.c20b9",
        "type": "inject",
        "z": "40e3fdb6.e6a084",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "20",
        "x": 250,
        "y": 340,
        "wires": [
            [
                "97591bdd.4c27b8"
            ]
        ]
    }
]

I am basically passing a string msg.payload as my child process input after starting the process/app with the daemon node. If anyone sees a better way of doing what I just did, please feel free to share!

Thanks!

1 Like