Issue: PulseAudio command working with console but not in Exec node

Hi All,

I'm having an issue that I'm not able to fix when using a | (pipe) in an exec node. The full command I am trying to exec is:

pactl load-module module-loopback latency_msec=1 source=2 sink=1 | multimon-ng -a DTMF /dev/stdin

But the command will not get executed and the error message thrown is:
Failure: Module initialization failed

However if I just exec the below command in the exec node, it works:
pactl load-module module-loopback latency_msec=1 source=2 sink=1

And if I just exec the below command in the exec node, it also works:
multimon-ng -a DTMF

So I tried the above two commands that are failing in node-red, by executing them directly in the console. Both work:

pi@raspberrypi:~ $ pactl load-module module-loopback latency_msec=1 source=2 sink=1 | multimon-ng -a DTMF /dev/stdin
multimon-ng 1.1.8
  (C) 1996/1997 by Tom Sailer HB9JNX/AE4WA
  (C) 2012-2019 by Elias Oenal
Available demodulators: POCSAG512 POCSAG1200 POCSAG2400 FLEX EAS UFSK1200 CLIPFSK FMSFSK AFSK1200 AFSK2400 AFSK2400_2 AFSK2400_3 HAPN4800 FSK9600 DTMF ZVEI1 ZVEI2 ZVEI3 DZVEI PZVEI EEA EIA CCIR MORSE_CW DUMPCSV X10 SCOPE
Enabled demodulators: DTMF

So I suspect the exec-node does not handle the pipe properly.

I hope someone has faced the same issue and can help me.

PS: It is not a matter of appending the msg.payload as I am even trying by passing the entire command manually in the exec node to make sure the command is executed properly.

Thanks all

Welcome to the forum @janedoe123

I am not at my computer so cannot test at the moment. Have you tried a simple command with pipe such ascat piping into grep to check that it is the pipe that is the problem?

It is more likely an environment thing.

How do you launch node-red? From command line terminal? run as a service? PM2?

Also, what account runs node-red?

Try adding this flow - what do you see in debug window?

printenv...

[{"id":"67000189.da769","type":"inject","z":"5e6c8b.7f38b374","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1420,"y":880,"wires":[["7e0062b2.c73adc"]]},{"id":"7e0062b2.c73adc","type":"exec","z":"5e6c8b.7f38b374","command":"printenv","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":1578,"y":880,"wires":[["bd65cfa7.0626a"],[],[]]},{"id":"bd65cfa7.0626a","type":"function","z":"5e6c8b.7f38b374","name":"","func":"var lines = msg.payload.split(\"\\n\")\nvar envvars = {};\nfor(let i = 0; i < lines.length; i++) {\n    let line = lines[i];\n    let parts = line.split(\"=\");\n    envvars[parts[0]]=parts[1];\n}\nmsg.payload = envvars;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1754,"y":880,"wires":[["36b59d59.44c5a2"]]},{"id":"36b59d59.44c5a2","type":"debug","z":"5e6c8b.7f38b374","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1924,"y":880,"wires":[]}]

then from a terminal where your command works, enter printenv - how do the env vars differ?

lastly,

stop node-red service (assumption) and from the terminal where your command works, enter node-red to start up node-red. run the above flow once more - do the correct env vars appear this time?

If so, then you can modify the service to include extra env vars required.

Thank you Steve !

Node-RED is automatically launched on boot.

Standard user runs Node-RED (in my case, it is "pi" account as I am use a Raspberry Pi), I have checked in the service file.

Running your flow gives the below result:

image

And executing printenv in the console where the command works gives:

The only difference I can see is SHLVL=1 in the console, and SHLVL=0 in node-RED.

The environment vars seem to be ok... Is there something I am missing out?

I dont think the Shell Level will matter.

Hmm, there are also a few env vars missing (NO_AT_BRIDGE, XDG_SESSION, DISPLAY, LC_ALL, DBUS_SESSION) and slight difference in path (that shouldnt matter tho) - one of these might be important to the execution?

Did you try Colins simple pipe test to rule that out?

A simple ps -ef | grep node works fine so no not an issue with exec node and pipe.

1 Like

Thanks Steve,

Indeed there are few env vars missing: NO_AT_BRIDGE, XDG_SESSION, DISPLAY, LC_ALL, DBUS_SESSION

The cat | grep command works as suggested by Colin:

So the question is: How to add the missing env vars to make sure they are taken into account by Node-RED?

Indeed. Do you know how to add the missing end vars NO_AT_BRIDGE, XDG_SESSION, DISPLAY, LC_ALL, DBUS_SESSION in order to make sure my command is executed?

Just a heads up - this is only a suggestion & may not be the cause/fix (i.e. lets rule out env vars before digging)

As a quick and dirty test, you could set the env vars before the command in the exec node e.g. export DISPLAY=:0 _MY_COMMAND_XXXX YYYY ZZZZ

e.g. if you change my demo flow to exec DISPLAY=:0 printenv you will see DISPLAY is now one of the env vars.

I just ran into this post from knolleary

Nov '19

One way of setting environment variables is in your settings.js file.

The following will set the env var MY_ENV_VAR :

process.env.MY_ENV_VAR = "Hello World";

You can add lines like that to the top of your settings file.


Does it mean I need to force them all in settings.js ?

I dont think that setting env vars in settings.js will cause exec to inherit them - I am pretty sure thats for function nodes / change nodes to access additional variables about its "env".

I might be wrong though - you could always try modifying settings.js, re-run the flow i posted - does printenv show your new variables?

Here is what I just tried in the exec node. The command is successfully executed:
multimon-ng -a DTMF

However if I force the below env var in the exec node, with exactly the same command, it fails with the node returning rc:-2:
NO_AT_BRIDGE=1 XDG_SESSION_TYPE=tty DISPLAY=:0 LC_ALL=en_US.UTF-8 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus multimon-ng -a DTMF

I've tried the env var one by one, same result:
NO_AT_BRIDGE=1 multimon-ng -a DTMF
XDG_SESSION_TYPE=tty multimon-ng -a DTMF
DISPLAY=:0 multimon-ng -a DTMF
LC_ALL=en_US.UTF-8 multimon-ng -a DTMF
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus multimon-ng -a DTMF

Am I doing something wrong?

Ok so I have tried something else.

In the console, I am executing the below comand:

pi@raspberrypi:~ $ pactl load-module module-loopback latency_msec=1 source=1 sink=0 | multimon-ng -a DTMF /dev/stdin

It is successfully working:

multimon-ng 1.1.8
  (C) 1996/1997 by Tom Sailer HB9JNX/AE4WA
  (C) 2012-2019 by Elias Oenal
Available demodulators: POCSAG512 POCSAG1200 POCSAG2400 FLEX EAS UFSK1200 CLIPFSK FMSFSK AFSK1200 AFSK2400 AFSK2400_2 AFSK2400_3 HAPN4800 FSK9600 DTMF ZVEI1 ZVEI2 ZVEI3 DZVEI PZVEI EEA EIA CCIR MORSE_CW DUMPCSV X10 SCOPE
Enabled demodulators: DTMF

If I try to launch the very same command using Node-RED and having a look at the logs, I am getting the below error message:

Failed to parse module arguments
Failed to load module "module-loopback" (argument: "latency_msec=1 source=1 sink=0 | multimon-ng -a DTMF /dev/stdin"): initialization failed.
^C

I also found a similar thread here: Exec Node and Terminal Problem ( Alsa)
Not sure it is related to the same issue...

I am really clueless... Why would it work with the console, and not node-Red ?

Ok folks,

I think I got it work but I don't know why... Is this a bug in node-red ?

I took the command pactl load-module module-loopback latency_msec=1 source=1 sink=0 | multimon-ng -a DTMF /dev/stdin and created a pulse.sh script as follows:

#!/bin/sh

pactl load-module module-loopback latency_msec=1 source=1 sink=0 | multimon-ng -a DTMF /dev/stdin

In the node-red exec node, I am calling the pulse.sh as follows:
/home/pi/Documents/pulse.sh

Guess what ? It works!

I really don't know why... That's worrying actually... Does anyone have any idea?

Small up :slight_smile: Is this a Node-Red bug?

PS: I haven't even added/modified any env var for that to work.

I was having trouble with pulseaudio commands from the exec node and found that it was an environment issue.

To solve it i used... XDG_RUNTIME_DIR=/run/user/1000 pactl info

This worked on a headless Raspberry Pi and my desktop machine.