2016-07-29 5 views
0

stdinにスクリプトとデータの両方をシェルとその子プロセスに渡したいと思っています。基本的には、シェルを起動し、"exec wc -c;\n<data>"のような文字列をstdin上のシェルに送ります。bash/sh/busyboxがstdinを子プロセスに渡す

私はサブプロセスを開始し、そのサブプロセスにデータを渡すことを検討しています。 を使用するexecwc -cは私のシェルを置き換え、stdin経由で送信されたバイト数を数えます。

例:

echo -ne 'exec wc -c;\nabc' | dash 
echo -ne 'exec wc -c;\nabc' | bash 
echo -ne 'exec wc -c;\nabc' | bash --posix 
echo -ne 'exec wc -c;\nabc' | busybox sh 

bashのではなく、ダッシュやbusybox shで一貫して動作するようです。両方とも断続的に失敗するようです。私が100ms待ってから<data>をstdinに送ると、それは動作します。しかし、睡眠は信頼できる解決策ではありません。

私は実際にはデータの量は少ないので、エンコードしたり、何らかの形でメモリに格納したりすることは望ましくありません。何か案は?

注:これを回避することができる多くのユースケースがあると確信しています。しかし、私はこれがなぜ一貫して機能しないのかを探しています。および/またはどのようなシェル魔法私は、それは好ましくはプラットフォーム間で、確実に動作させるために行うことができます:)

アップデート:私はshを実行して、/ stderrの標準入力/標準出力を公開するリモートシステムを持って明確にするために、私は希望そのような設定が何かを行うことができることを証明する。 "exec cat - > /myfile;\n<data>"を送信すると、私は<data>が含まれるように/myfileにストリームすることができます。再び<data>が大きいと想像してください。

本質的には、shのstdinを使用してシステムを制御できることを証明しようとしています。 shの代わりに非常に単純なものが、静的バイナリとしてプラットフォーム間で容易に利用できます。

これは完全に狂っているかもしれないと私はSSHまたは何かのようなプロトコルを採用すべきだと認めますが、それから私はそれを実装する必要があります。

+3

なぜ、 'echo -n 'abc' | wc -c'やもっと一般的には' generatedata | process'?シェルを起動して 'exec'を実行する利点は何ですか? – John1024

+3

ところで、移植性を気にしているなら、*任意の*フラグで 'echo'ではなく' printf'を使う傾向がありますが、 '-n'はPOSIXでは明示的に未定義の動作ですが、その引数リストに '-e'を渡したときに' -e'を出力する以外のものはjではない定義されていないスペースにあっても、標準に反して動作します。特にAPPLICATION USAGEセクションを含むhttp://pubs.opengroup.org/onlinepubs/009604599/utilities/echo.htmlを参照してください。 –

答えて

1

これはではなく、全くダッシュやbusyboxのshを持つ、bashのを私のために働くように見えます。私はそれがまったく動作して驚いています。シェルは、最初の行のコマンドとその後のデータの両方を含む、何らかの処理を行う前に、入力から大きな入力を読み込むことを期待します。そうすれば、エグゼクティブ・コマンドのスタンダードには何も残らないだろう。

実際には、改行を確認してすぐにexecを実行するまで、bashは1バイトずつ読むようです。

ダッシュとbusyboxのSHが最初に入力全体を読んで、私が予想を正確に何をすべきか。

は、あなたの代わりに

echo -ne "exec wc -c <<'END'\nabc" | sh 

を行うことができますか?あなたが入力に表示されることを心配している場合、おそらくENDをEND_adjfioe38999f3jf_ENDに置き換えていますか?

更新:それはあなたの "メモリにバッファしないでください"基準を満たしていません。 Err ... ok、難しいです。あなたは4Kに収まるを実行するコマンドを保証することができます場合は、このような恐ろしい何かがだろう「仕事」:

echo -ne "exec wc -c\nabc" | perl -e 'sysread(STDIN, $buf, 4096); $buf =~ s/([^\n]*)\n//; open(my $pipe, "|-", $1); syswrite($pipe, $buf); open(STDOUT, ">&", $pipe); exec("cat")' 

が、それはほとんどあなたが探していたポータブルシェルベースのソリューションません。 (これは4kの入力チャンクを読み込み、そこからコマンドを取得し、パイプで接続されたコマンドを実行しているシェルをforkして作成し、残りの最初のチャンクをパイプに送り、独自のstdoutをパイプにダンプしてからcatのexecを使ってパイプを一度に1つずつパイプにコピーし、それを標準入力に受け取ります。これは、単純なシェルベースの構文だけで、何が起こってしまったのかと思います。

+0

彼はこれは面白い質問です。@sfinkユースケースはシェルが実行するものである 'sh'に' cat -'を送信することでtaskcluster対話シェルをテストしています...理想的には、シェルを使ってファイルやその他のクレイジーなものを転送することもできます...しかし、埋め込みが簡単なsh/busyboxの代わりにbashを実行しなければならなくなる可能性があります。 – jonasfj

関連する問題