Comment puis-je échapper à une chaîne pour une commande shell dans le nœud?
-
21-09-2019 - |
Question
nodejs , la seule façon d'exécuter des commandes externes est par sys.exec (cmd). Je voudrais appeler une commande externe et lui donner des données via stdin. En nodejs il ne semble pas encore être un moyen d'ouvrir une commande, puis appuyez données (seulement exec et recevoir ses sorties d'erreur standard +), il semble que la seule façon que je dois faire ce droit est maintenant par l'intermédiaire d'une seule commande de chaîne, tels que:
var dangerStr = "bad stuff here";
sys.exec("echo '" + dangerStr + "' | somecommand");
La plupart des réponses à des questions comme celle-ci ont mis l'accent sur une ou l'autre regex qui ne fonctionne pas pour moi dans nodejs (qui utilise le moteur JavaScript V8 de Google) ou fonctionnalités natives d'autres langages comme Python.
Je voudrais échapper dangerStr afin qu'il soit sûr de composer une chaîne exec comme celle-ci. Si elle aide, dangerStr contiendra des données JSON.
La solution
Il y a un moyen d'écrire une commande externe: process.createChildProcess
( ) renvoie une objet avec un procédé de write
. createChildProcess
est pas aussi pratique cependant, car il ne cache pas stdout et stderr, vous aurez donc besoin de gestionnaires d'événements pour lire la sortie en morceaux.
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.");
Autres conseils
Voici ce que j'utilise:
var escapeShell = function(cmd) {
return '"'+cmd.replace(/(["\s'$`\\])/g,'\\$1')+'"';
};
Si vous avez besoin de solution simple, vous pouvez utiliser ceci:
function escapeShellArg (arg) {
return `'${arg.replace(/'/g, `'\\''`)}'`;
}
Donc, comme mentionné Chris Johnsen votre chaîne sera tout simplement échappé avec des guillemets simples.
echo 'John'\''s phone';
Il travaille en bash
à cause de forte citant , se sent comme elle a aussi travaille à fish
, mais ne fonctionne pas dans zsh
et sh
.
Si vous avez bash
votre peut exécuter votre script dans sh
ou zsh
avec 'bash -c \'' + escape('all-the-rest-escaped') + '\''
.
Mais en fait ... Node.js échapperont à tous les caractères nécessaires pour vous:
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);
});
ce bloc de code exécutera:
echo '`echo 1`;"echo $SSH_TTY;'\''\\0{0..5}'
et la volonté de sortie:
stdout: `echo 1`;"echo $SSH_TTY;\'\\0{0..5}
ou une erreur.
Jetez un oeil à http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
Par la solution simple moyen d'exécuter un tas de commandes est:
require('child_process')
.spawn('sh', ['-c', [
'cd all/your/commands',
'ls here',
'echo "and even" > more'
].join('; ')]);
Passez une bonne journée!
devrait jamais se fondent sur échapper entrée inconnue va à un paramètre shell -. il y aura presque toujours certains que vous avez bord cas pas pensé permet à l'utilisateur d'exécuter du code arbitraire sur votre serveur
Node a un support pour appeler une commande et passer chaque argument séparément, sans échappements demandé. Ceci est la meilleure façon de le faire:
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}`);
});
Si vous devez également faire face à caractère spécial (sauts de ligne-etc.), vous pouvez le faire de cette façon:
str = JSON.stringify(str)
.replace(/^"|"$/g,'') //remove JSON-string double quotes
.replace(/'/g, '\'"\'"\'') //escape single quotes the ugly bash way
Cela suppose que vous utilisez forte citant par simple -quotes) et le récepteur peut comprendre de JSON de Escaping C-like.