nodejs / snap

Node.js snap source and updater
MIT License
167 stars 38 forks source link

child_process.spawn produces empty string for various commands (node, npm, ncu) #13

Closed kleinfreund closed 1 year ago

kleinfreund commented 3 years ago

(initially reported in https://github.com/nodesource/distributions/issues/843)


I switched from the PPA binary (https://github.com/nodesource/distributions/blob/master/README.md#debinstall) to the snap binary (https://snapcraft.io/node). This started to break the ncu -g command. Originally, I opened an issue with npm-check-updates, but it doesn’t seem to be an issue on their end (for reference: https://github.com/tjunnone/npm-check-updates/issues/536).

Only with the snap binary do I get the following error:

/home/phil/.npm-global/lib/node_modules/npm-check-updates/lib/npm-check-updates.js:387
        throw err;
        ^

Error: Expected JSON from "npm ls". This could be due to npm instability.

    at parseJson (/home/phil/.npm-global/lib/node_modules/npm-check-updates/lib/package-managers/npm.js:38:15)
    at /home/phil/.npm-global/lib/node_modules/npm-check-updates/lib/package-managers/npm.js:144:30
    at processTicksAndRejections (internal/process/task_queues.js:89:5)

The command that is executed with child_process.spawn is npm ls --global --depth=0 --json which produces the correct JSON with both the PPA and the snap binary when executed directly from the terminal.

Steps to reproduce:

Create a reproduction.js file containing the following code and run node reproduction.js with node being a Node.js binary from a Snap source (reproduces with all versions from v12 to v14 at least).

const { spawnSync } = require('child_process')

// Both these spawn commands will yield nothing in their stdout.
// The latter should just contain a Node version tring such as `v14.10.1`.

// npm ls --global --depth=0 --json
const npmListOutput = String(spawnSync('npm', ['ls', '--global', '--depth=0', '--json']).stdout)
console.log({ npmListOutput });

// node --version
const nodeVersionOutput = String(spawnSync('node', ['--version']).stdout)
console.log({ nodeVersionOutput });

To switch around the Node binary on Ubuntu:

  1. Uninstall Node.

    sudo apt remove nodejs
  2. Install Node via Snap.

    sudo snap install node --channel=16/stable --classic
  3. Verify that Snap’s Node is used (i.e. on my system, the binary is reported to be in /snap/bin/node when running which node).

  4. Run npm-check-updates with the global flag.

    ncu -g
  5. Remove Node via Snap.

    sudo snap remove node
  6. Install Node via apt.

    sudo apt install nodejs
rvagg commented 3 years ago

Yeah .. so .. snaps and spawn aren't awesome due to the funky way they they do paths, I've struggled to figure out the best way to deal with this.

One option to try might be to ln -s /snap/bin/node /usr/bin/node which I've seen some snaps recommend, which is a little nasty but might help solve some path problems.

I've also been forced to use /snap/node/current/bin/node as my path before to get around these problems. Again, a little nasty but can work.

Let me know if either of those options work for you. Unfortunately there are enough limitations that it's not unreasonable to suggest moving back to a native package whenever you need to do anything that moves outside of a happy path of usage (native addons add another layer of problems to the mix).

etatanova commented 2 years ago

Hi! We installed Node.js via snap store and tried to use exec and spawn functions in the VS Code extension environment. In the test extension we could also reproduce the same incorrect behavior as described in this issue. The functions for spawning child processes skip the execution of npm and CLI commands (based on Node.js scripts) and return just an empty result or an error.

rvagg commented 2 years ago

Hey folks, so I recently ran into a similar issue with the combination of VSCode and Golang installed from Snaps, it felt a lot like this one and I'm pretty sure it's all Apparmor-related because of the funky process isolation Snaps are trying to do. Anyway, the workaround here has been working great for that particular issue: https://www.mail-archive.com/ubuntu-bugs@lists.ubuntu.com/msg5924452.html

I haven't tried this to work around Node.js issues (mostly I'm not using it via Snap these days because of these problems!) but someone in this thread could give it a try and report back.

m-thomson commented 2 years ago

I'm using Node-Red to launch a NodeJS instance and getting no output at all. I noticed this entry in syslog which occurred when running the Node-Red "flow":

Nov 5 18:45:59 ss1 kernel: [77021.759179] audit: type=1400 audit(1636137959.907:184): apparmor="DENIED" operation="file_inherit" profile="/snap/snapd/13640/usr/lib/snapd/snap-confine" pid=24351 comm="snap-confine" family="unix" sock_type="stream" protocol=0 requested_mask="send receive" denied_mask="send receive" addr=none peer_addr=none

Possibly related?

kleinfreund commented 1 year ago

I’m closing this as there doesn’t seem to be any interest in reproducing or fixing this.

giner commented 1 year ago

This is still an issue and requires a fix. More details is on the the following issue https://github.com/nodejs/node/issues/37982 and https://bugs.launchpad.net/ubuntu/+source/snapd/+bug/1849753. A workaround is here https://github.com/nodejs/node/issues/37982#issuecomment-1451326285.