2009-11-22 24 views
35

nodejsでは、外部コマンドを実行する唯一の方法はsys.exec(cmd)です。私は外部コマンドを呼び出し、stdin経由でデータを与えたいと思います。 nodejsでは、まだコマンドを開いてデータをpushする方法はないようです(標準とエラーの出力をexecして受け取るだけです)ので、私はこれを行うしかありません。ノードでシェルコマンドの文字列をエスケープするにはどうすればよいですか?

このような質問にほとんど答えはnodejsに私のために動作しません正規表現(GoogleのV8 JavaScriptエンジンを使用している)などの他の言語からのネイティブ機能のいずれかに焦点を当てている
var dangerStr = "bad stuff here"; 
sys.exec("echo '" + dangerStr + "' | somecommand"); 

次のような単一の文字列コマンドを経由してPython。

私は上記のようなexec文字列を作成するのが安全なようにdangerStrから脱出したいと思います。役立つ場合、dangerStrにはJSONデータが格納されます。

+9

文字列を安全にエスケープするために、以下のアルゴリズムを使用できます:1)すべての一重引用符( ')を、 )2)変更された文字列の最初と最後に一重引用符を追加します。先頭と末尾の一重引用符は完全に効率的にエンコードされませんが、それはまだ機能します。 –

+0

明確化のために:@ ChrisJohnsenのアドバイスを理解するのに少し時間がかかりましたが、それはチェックアウトしています。シェルで 'do not do 'をしたいなら、' echo'は 'do not 'は' do not that'を生成するために 'do 'を行います。 – mikemaccana

答えて

4

外部コマンドに書き込む方法があります。process.createChildProcessdocumentation)は、writeメソッドを持つオブジェクトを返します。 createChildProcessはstdoutとstderrをバッファしないので便利ではないので、出力をチャンクで読むにはイベントハンドラが必要です。

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

あなたは揺れます!詳細な例をありがとう。 – Maciek

+0

興味深い..ありがとう! BTW、新しいURIはhttp://nodejs.org/api/child_process.html – grilix

+29

あなたは引数をエスケープすることについて何も説明しません。 – Will

33

これは私が使用するものです。

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

最初の$は何をしていますか? APIのリファレンスでは、文字列の終わりがifである場合にのみ一致しますが、この場合は一致しません。私は、文字列 "/ aPath '/ with/qu'otes'"(一重引用符+二重で終わることに注意してください)、$付きで、$なしで試しました。結果は同じです。 –

+1

@DavidTorres 'abc $ abc'は' abc \ $ abc'になります –

+1

アポストロフィー '' 'を使用する場合、' $ 'をエスケープする必要はありません –

14

あなたがこれを使用することができます簡単な解決策が必要な場合:

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

をだからあなたの文字列が単にクリスヨンセンとして単一引用符でエスケープされますと述べた。

echo 'John'\''s phone'; 

それは、理由strong quotingbashで動作し、それはまたfishで働くように感じますが、zshshでは動作しません。

bashの場合は、またはzsh'bash -c \'' + escape('all-the-rest-escaped') + '\''のスクリプトを実行できます。

しかし、実際には... Node.jsのはあなたのために必要なすべての文字をエスケープします:

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

このコードブロックが実行されます:

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

と意志出力:

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

または多少の誤り。

コマンドの束を実行する方法の簡単な解決策では​​

を見てみましょうです:

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

は良い一日を!

-1

また、特殊文字(改行など)に対処する必要がある場合は、これは、あなたが一重引用符を経由してバッシュのstrong-quotingを使用すると仮定し

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

)と受信機は、JSONのCのようなエスケープを理解することができます。)あなたは、このようにそれを行うことができます。

-1

シルヴァンの答えのバリエーション:(アレックスが指摘したように)$は、単一引用符で囲まれた文字列にエスケープする必要がないことを前提として

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') + "'"; 
}; 

およびその他の引用の種類はする必要はありませんいずれかである。

関連する問題