2009-11-22 8 views
35

In nodejs können externe Befehle nur über sys.exec (cmd) ausgeführt werden. Ich möchte einen externen Befehl aufrufen und geben Sie Daten über Stdin. In nodejs scheint es immer noch keine Möglichkeit zu geben, einen Befehl zu öffnen und dann Daten dorthin zu schieben (nur um exec auszuführen und seine Standard + Fehlerausgaben zu erhalten), so scheint es, dass die einzige Möglichkeit, dies jetzt zu tun, ist über einen einzelnen String-Befehl wie:Wie kann ich einen String für einen Shell-Befehl im Knoten entkommen lassen?

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

die meisten Antworten auf Fragen wie diese auf entweder regex konzentriert haben, die für mich nicht in NodeJS arbeiten oder nativen Funktionen aus anderen Sprachen (die V8 Javascript-Engine von Google verwendet) wie Python.

Ich möchte dangerStr entkommen, so dass es sicher ist, eine Exec-Zeichenfolge wie die oben zu komponieren. Wenn es hilft, enthält dangerStr JSON-Daten.

+9

Für Bourne-Shells können Sie den folgenden Algorithmus verwenden, um Strings sicher zu entgehen: 1) ersetzen Sie alle Vorkommen von einzelnen Anführungszeichen (') durch die vier Zeichenfolgen, einfache Anführungszeichen, Backslash, einfache Anführungszeichen, einfache Anführungszeichen (' \ '') 2) füge am Anfang und am Ende der modifizierten Zeichenkette ein zusätzliches einfaches Anführungszeichen hinzu. Führende und abschließende einfache Anführungszeichen werden nicht perfekt effizient codiert, funktionieren aber immer noch - "wird" "\" ", wenn es einfach sein könnte". –

+0

Zur Verdeutlichung: Es hat eine Weile gedauert, bis ich @ ChrisJohnsens Ratschlag verstanden habe, aber es sieht aus. Wenn du das auf der Shell nicht machen willst, dann tu 'echo' don 't do that', um 'do not do' zu erzeugen. – mikemaccana

Antwort

4

Es gibt eine Möglichkeit, in einen externen Befehl zu schreiben: process.createChildProcess (documentation) gibt ein Objekt mit einer write Methode zurück. createChildProcess ist jedoch nicht so praktisch, da es stdout und stderr nicht puffert, also benötigen Sie Event-Handler, um die Ausgabe in Chunks zu lesen.

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."); 
+0

Sie rocken! Danke für das detaillierte Beispiel. – Maciek

+0

Interessant .. Danke! BTW, Die neue URI ist http://nodejs.org/api/child_process.html – grilix

+29

Sie erklären nichts über entweichende Argumente. – Will

33

Dies ist, was ich benutze:

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

Was macht den ersten $? In der API-Referenz sagt, dass nur passt, wenn das Ende der Zeichenfolge ist, aber es ist nicht dieser Fall. Ich habe versucht die Zeichenfolge "/ aPath '/ mit/qu'otes'" (beachten Sie, dass es mit einfachen Anführungszeichen + double endet), mit $ und ohne $. Das Ergebnis ist das gleiche. –

+1

@DavidTorres 'abc $ abc' wird' abc \ $ abc' –

+1

Keine Notwendigkeit zu esacpe '$' wenn Apostroph '' ' –

14

Wenn Sie einfache Lösung benötigen, können Sie diese verwenden:

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

So wird Ihre Saite einfach mit einfachen Anführungszeichen als Chris Johnsen entwertet werden erwähnt.

echo 'John'\''s phone'; 

Es funktioniert in bash wegen strong quoting, fühlt sich an wie es funktioniert auch in fish, funktioniert aber nicht in zsh und sh.

Wenn Sie bash haben, können Sie Ihr Skript in sh oder zsh mit 'bash -c \'' + escape('all-the-rest-escaped') + '\'' ausführen.

Aber eigentlich ... node.js werden alle benötigten Zeichen für Sie entkommen:

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); 
}); 

dieser Block von Code ausgeführt wird:

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

und AUSGABE:

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

oder ein Fehler.

Werfen Sie einen Blick auf http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

Durch die Art und Weise einfache Lösung eine Reihe von Befehlen auszuführen ist:

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

einen schönen Tag!

-1

Wenn Sie auch mit Sonderzeichen umgehen müssen (Zeilenumbrüche usw.)) Sie können es auf diese Weise tun:

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

Diese Sie strong-quoting über Apostrophe verwenden Bash annimmt) und der Empfänger kann JSON den C-like Entkommen verstehen.

-1

Eine Variation Sylvain Antwort:

var escapeShell = function(string) { 
    // Sanitise all space (newlines etc.) to a single space 
    string.replace(/\s+/g, " "); 
    // Optionally remove leading and trailing space 
    string.replace(/^\s+|\s+$/g, " "); 
    // Quote with single quotes, escaping backslashes and single quotes 
    return "'" + string.replace(/(['\\])/g, '\\$1') + "'"; 
}; 

Unter der Prämisse, dass $ nicht in einem einzigen String in Anführungszeichen entgangen werden muss (als Alex wies darauf hin) und die anderen Kurstypen brauchen nicht zu sei entweder.

Verwandte Themen