0

I would like to execute the following command using nodejs Spawn on a Debian system : /usr/bin/apt-get upgrade -s | tail -1 | cut -f1 -d' ' I want to use spawn and not exec because of future use of root only commands and i don't want to allow a full shell access (i will update the visudo file with correct commands) Here is my code

  const apt = spawn('/usr/bin/apt-get', ['upgrade', '-s']);
  const tail = spawn('tail', ['-1']);
  const cut = spawn('cut', ['-f1', '-d" "']);

  apt.stdout.on('data', (data) => {
    tail.stdin.write(data);
  });

  tail.stdout.on('data', (data) => {
    cut.stdin.write(data);
  });

  cut.stdout.on('data', (data) => {
    console.log(data.toString());
  });


  apt.stderr.on('data', (data) => {
    console.log("apt stderr: ${data}");
  });

  tail.stderr.on('data', (data) => {
    console.log("tail stderr: ${data}");
  });

  cut.stderr.on('data', (data) => {
    console.log("cut stderr: ${data}");
  });

  apt.on('close', (code) => {
    if (code !== 0) {
      console.log("apt process exited with code ${code}");
    }
  });

  tail.on('close', (code) => {
    if (code !== 0) {
      console.log("tail process exited with code ${code}");
    }
  });

  cut.on('close', (code) => {
    if (code !== 0) {
      console.log("cut process exited with code ${code}");
    }
  });

  res.status(200).json('');

Once executed i have an error because of the '-d" "' parameter that is not recognized. I try escaping the space with a double \ or split the parameter in both but still errors

1 Answer 1

2

It should just be:

const cut = spawn('cut', ['-f1', '-d ']);

No double quotes or backslash escapes -- those are for the use of the shell, not cut, and there's no shell here.

This makes dealing with unknown filenames (for your future use cases) particularly easy: When your strings are passed as arguments (to software that doesn't misuse them my running eval-equivalent code later), you don't need to quote, escape, sanitize, or otherwise modify them before they can be passed as data.

(That is to say -- when you tell your shell cut -f1 -d" ", the actual syscall it invokes to start that cut process, in C syntax, looks like execve("/usr/bin/cut", {"cut", "-f1", "-d ", NULL}, environ); the quotes were syntactic, consumed by the shell when it used them to make the decision that the space after the -d should be part of the same literal argument).

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Charles ! That worked and i also understood why ;-) I missed the shell needs Another point : that means that for a command like /bin/grep -P '^\d+ upgraded'i would have to write it like spawn('grep', ['-P', '"^\\d+ ', 'upgraded"']) ?
'^\d+ upgraded' is parsed by the shell to a single string (that's one of the effects of the syntactic single quotes), so it'd be spawn('grep', ['-P', '^\\d+ upgraded']) to write that same single string in JavaScript.
Some places to start re: understanding how this works on the shell side might be mywiki.wooledge.org/Quotes or wiki.bash-hackers.org/syntax/quoting, and mywiki.wooledge.org/BashParser

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.