4

Python、Perl、PHP、Rubyなどと同じ「システム」関数呼び出しが必要です。これは、Java で実行される Rhino JavaScript エンジンで実行されると、Narwhal と呼ばれる JavaScript 標準ライブラリのコンポーネントになります。

問題は、Java の標準ライブラリが、親プロセスの stdio を共有するサブプロセスを生成する機能を抽象化したように見えることです。これは、インタラクティブ性をサブプロセスに任せることができないことを意味します。

これに対する私の最初のクラックは、Python の subprocess.popen を実装することでした。これは、3 つの「パンパー」スレッドを使用して、親プロセスの stdio を個別にアクティブにコピーします (デッドロックを防ぐため)。残念ながら、これは 2 つの問題を引き起こしています。まず、サブプロセスが自発的に終了したときに入力が自動的に閉じられません。次に、子プロセスへのストリームが適切にバッファリングおよびフラッシュされません。

require("os").system() コマンドを期待どおりに機能させるソリューションを探しています。

プロジェクトはhttp://narwhaljs.orgにあります

関連コード:

4

4 に答える 4

2

これが探しているものかどうかはわかりませんが、 JNA ライブラリsystemを介して C 関数を呼び出すことができます。

public class System {
  public interface C extends Library {
    C INSTANCE = (C) Native.loadLibrary(
        (Platform.isWindows() ? "msvcrt" : "c"), C.class);

    public int system(String format);
  }

  public static void main(String[] args) {
    C.INSTANCE.system("vi");
  }
}

とにかく、おおざっぱなテストは Windows で機能しました。

于 2009-09-02T22:08:27.667 に答える
1

私があなたを正しく理解しているなら、あなたはそのようなものが欲しいです:

import java.util.*;
import java.io.*;
class StreamGobbler extends Thread
{
    InputStream is;
    String type;
    OutputStream os;

    StreamGobbler(InputStream is, String type)
    {
        this(is, type, null);
    }
    StreamGobbler(InputStream is, String type, OutputStream redirect)
    {
        this.is = is;
        this.type = type;
        this.os = redirect;
    }

    public void run()
    {
        try
        {
            PrintWriter pw = null;
            if (os != null)
                pw = new PrintWriter(os);

            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
            {
                if (pw != null)
                    pw.println(line);
                System.out.println(type + ">" + line);    
            }
            if (pw != null)
                pw.flush();
        } catch (IOException ioe)
            {
            ioe.printStackTrace();  
            }
    }
}
public class GoodWinRedirect
{
    public static void main(String args[])
    {
        if (args.length < 1)
        {
            System.out.println("USAGE java GoodWinRedirect <outputfile>");
            System.exit(1);
        }

        try
        {            
            FileOutputStream fos = new FileOutputStream(args[0]);
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec("java jecho 'Hello World'");
            // any error message?
            StreamGobbler errorGobbler = new 
                StreamGobbler(proc.getErrorStream(), "ERROR");            

            // any output?
            StreamGobbler outputGobbler = new 
                StreamGobbler(proc.getInputStream(), "OUTPUT", fos);

            // kick them off
            errorGobbler.start();
            outputGobbler.start();

            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);
            fos.flush();
            fos.close();        
        } catch (Throwable t)
          {
            t.printStackTrace();
          }
    }
}

このコードは、JavaWorldで、いくつかのexeファイルへのシステムコールをラップするための同様のソリューションを探していたときに見つけました。

それ以来、私のコードは少し進化しましたが、良い例だと思います。

于 2009-09-03T08:39:48.557 に答える
1

終了コードをポーリングするか、メソッドで別のスレッドを待機させることにより、プロセスの終了ステータスを個別に監視する必要がありますProcess.waitFor()

ストリームのバッファリングとフラッシュの問題については、簡単な解決策があるとは思いません。さまざまな形式 (BufferedInputStreamなど) でバッファリングを行う Java クラスがいくつかあります。多分それらの1つが助けることができますか?

于 2009-09-02T20:20:19.117 に答える
0

プロセスの標準出力とエラーを同時に消費することは非常に重要です。Carlos Tasada のサンプル コードは、こちらの別の場所にあります。

これを行わないと、生成されたプロセスからの出力に応じて、コードが機能する (または機能しない) 場合があります。その出力が変更されると(生成されたプロセスでエラーが発生した場合など)、同時消費がなければ、プロセスはデッドロックします。私がSOに関連して目にする問題のほとんどは、関連するProcess.exec()ブロッキングです。

于 2009-09-03T10:10:41.207 に答える