¿Cómo puedo escapar una cadena para un comando de shell en node?
En nodejs, la única forma de ejecutar comandos externos es a través de sys.exec (cmd). Me gustarÃa llamar a un comando externo y darle datos a través de stdin. En nodejs todavÃa no parece haber una manera de abrir un comando y luego enviar datos a él (solo para exec y recibir sus salidas de error estándar+), por lo que parece que la única manera que tengo que hacer esto ahora es a través de un solo comando de cadena como:
var dangerStr = "bad stuff here";
sys.exec("echo '" + dangerStr + "' | somecommand");
La mayorÃa de las respuestas a preguntas como esta se han centrado en cualquiera de las expresiones regulares que no trabaja para mà en nodejs (que utiliza el motor Javascript V8 de Google) o funciones nativas de otros lenguajes como Python.
Me gustarÃa escapar de dangerStr para que sea seguro componer una cadena exec como la anterior. Si ayuda, dangerStr contendrá datos JSON.
5 answers
Hay una manera de escribir en un comando externo: process.createChildProcess
(documentation ) devuelve un objeto con un método write
. createChildProcess
no es tan conveniente, sin embargo, porque no almacena en búfer stdout y stderr, por lo que necesitará controladores de eventos para leer la salida en trozos.
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.");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-09 21:14:09
Esto es lo que uso:
var escapeShell = function(cmd) {
return '"'+cmd.replace(/(["\s'$`\\])/g,'\\$1')+'"';
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-10 19:45:14
Si necesita una solución simple, puede usar esto:
function escapeShellArg (arg) {
return `'${arg.replace(/'/g, `'\\''`)}'`;
}
Asà que tu cadena simplemente se escapará con comillas simples como mencionó Chris Johnsen.
echo 'John'\''s phone';
Funciona en bash
porque a fuerte citando, se siente como que también funciona en fish
, pero no funciona en zsh
y sh
.
Si tienes bash
puedes ejecutar tu script en sh
o zsh
con 'bash -c \'' + escape('all-the-rest-escaped') + '\''
.
Pero en realidad... nodo.js escapará de todos los personajes necesarios para usted:
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 bloque de código se ejecutará:
echo '`echo 1`;"echo $SSH_TTY;'\''\\0{0..5}'
Y producirá:
stdout: `echo 1`;"echo $SSH_TTY;\'\\0{0..5}
O algún error.
Echa un vistazo a http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
Por cierto, la solución simple para ejecutar un montón de comandos es:
require('child_process')
.spawn('sh', ['-c', [
'cd all/your/commands',
'ls here',
'echo "and even" > more'
].join('; ')]);
Que tenga un buen dÃa!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-02 23:14:05
Usted debe nunca confiar en escapar de la entrada desconocida que va a un parámetro de shell - casi siempre habrá algún caso de borde que no haya pensado que permite al usuario ejecutar código arbitrario en su servidor.
Node tiene soporte para llamar a un comando y pasar cada argumento por separado, sin necesidad de escapar. Esta es la forma más segura de hacerlo:
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}`);
});
La documentación está aquÃ
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-19 11:50:47
Si también necesita tratar con caracteres especiales (saltos de lÃnea, etc.) puedes hacerlo de esta manera:
str = JSON.stringify(str)
.replace(/^"|"$/g,'') //remove JSON-string double quotes
.replace(/'/g, '\'"\'"\'') //escape single quotes the ugly bash way
Esto supone que se usa la comilla fuerte de Bash a través de comillas simples) y el receptor puede entender el escape tipo C de JSON.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-04 06:25:28