Pergunta

Dentro nodejs, a única maneira de executar comandos externos é via sys.exec (CMD). Eu gostaria de chamar um comando externo e fornecer dados via Stdin. No Nodejs, ainda não parece ser uma maneira de abrir um comando e depois empurrar dados para ele (apenas para executar e receber suas saídas padrão+erros), então parece que a única maneira de fazer isso agora é através de um único comando de string, como:

var dangerStr = "bad stuff here";
sys.exec("echo '" + dangerStr + "' | somecommand");

A maioria das respostas para perguntas como essa se concentrou em Regex, que não funciona para mim no NodeJS (que usa o mecanismo JavaScript V8 do Google) ou recursos nativos de outros idiomas como o Python.

Eu gostaria de escapar do Dangerstr, para que seja seguro compor uma sequência executiva como a acima. Se ajudar, o DERGERSTR conterá dados JSON.

Foi útil?

Solução

Existe uma maneira de escrever para um comando externo: process.createChildProcess (documentação) retorna um objeto com um write método. createChildProcess Porém, não é tão conveniente, porque não bobina o stdout e o stderr, então você precisará de manipuladores de eventos para ler a saída em pedaços.

var stdout = "", stderr = "";
var child = process.createChildProcess("someCommand");

child.addListener("output", function (data) {
    if (data !== null) {
        stdout += data;
    }
});
child.addListener("error", function (data) {
    if (data !== null) {
        stderr += data;
    }
});
child.addListener("exit", function (code) {
    if (code === 0) {
        sys.puts(stdout);
    }
    else {
        // error
    }
});

child.write("This goes to someCommand's stdin.");

Outras dicas

Isso é o que eu uso:

var escapeShell = function(cmd) {
  return '"'+cmd.replace(/(["\s'$`\\])/g,'\\$1')+'"';
};

Se você precisar de uma solução simples, pode usar isso:

function escapeShellArg (arg) {
    return `'${arg.replace(/'/g, `'\\''`)}'`;
}

Portanto, sua string será simplesmente escapada com citações únicas, como Chris Johnsen mencionou.

echo 'John'\''s phone';

Funciona bash por causa de citação forte, parece que também funciona em fish, mas não funciona em zsh e sh.

Se você tem bash Seu pode executar seu script em sh ou zsh com 'bash -c \'' + escape('all-the-rest-escaped') + '\''.

Mas na verdade ... Node.js escapará de todos os personagens necessários para você:

var child = require('child_process')
  .spawn('echo', ['`echo 1`;"echo $SSH_TTY;\'\\0{0..5}']);

child.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

child.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

Este bloco de código será executado:

echo '`echo 1`;"echo $SSH_TTY;'\''\\0{0..5}'

e será lançado:

stdout: `echo 1`;"echo $SSH_TTY;\'\\0{0..5}

ou algum erro.

Dar uma olhada em http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

A propósito, a solução simples para executar vários comandos é:

require('child_process')
  .spawn('sh', ['-c', [
    'cd all/your/commands',
    'ls here',
    'echo "and even" > more'
  ].join('; ')]);

Tenha um bom dia!

Você deve Nunca Confie em escapar de informações desconhecidas para um parâmetro de shell - Quase sempre haverá algum caso de ponta que você não pensou que permite ao usuário executar o código arbitrário no seu servidor.

O Node possui suporte para chamar um comando e passar cada argumento separadamente, sem escapar necessário. Esta é a maneira mais segura de fazer isso:

const { spawn } = require('child_process');
// Note that the arguments are in an array, not using string interpolation
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

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

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});

A documentação é aqui

Se você também precisar lidar com caráter especial (quebras de linha etc.), pode fazê-lo desta maneira:

str = JSON.stringify(str)
    .replace(/^"|"$/g,'') //remove JSON-string double quotes
    .replace(/'/g, '\'"\'"\'') //escape single quotes the ugly bash way

Isso pressupõe que você use o Bash citando forte via cotas únicas) e o receptor pode entender a fuga do tipo C da JSON.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top