Java实现了“系统”命令(Implementing the “system” command in

2019-07-04 11:44发布

我已经需要一个“系统”功能调用,同那些在Python,Perl和PHP,Ruby中,&C。 这将是所谓的独角鲸一个JavaScript标准库的一个组成部分,当它在Rhino JavaScript引擎,它是基于Java运行依次运行。

麻烦的是,Java的标准库似乎已经抽离产卵共享父进程的标准输入输出的子进程的能力。 这意味着,你不能推迟交互的子进程。

我在这第一条裂缝是实现Python的subprocess.popen。 这使用了三个“消防车”主题,积极自主复制父进程的标准输入输出(防止死锁)。 不幸的是,这是给我们的两个问题。 首先,输入不自动当子进程退出自动关闭。 其次,流子进程没有缓冲和适当清空。

我在寻找解决办法,使我们的要求(“OS”)。系统()命令工作,正如人们所期望。

该项目是在http://narwhaljs.org

相关的代码:

  • http://github.com/tlrobinson/narwhal/blob/d147c160f11fdfb7f3c0763acf352b2b0e2713f7/lib/os.js#L10
  • http://github.com/tlrobinson/narwhal/blob/d147c160f11fdfb7f3c0763acf352b2b0e2713f7/engines/rhino/lib/os-engine.js#L37

Answer 1:

不知道这是你在寻找什么,而是你可以调用的C system通过功能JNA库 :

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,无论如何。



Answer 2:

如果我正确理解你,你想这样的事情:

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文件。

我的代码已经发展了不少自那时起,但我认为这是一个很好的例子。



Answer 3:

需要分别监视该过程退出状态,或者通过轮询的退出代码或由具有一个单独的线程处于等待Process.waitFor()方法。

在缓冲和冲洗流的问题,我没有事情有一个简单的解决方案。 有几个Java类里面做缓冲以不同的形式( BufferedInputStream ,等等)。 也许他们中的一个可以帮助?



Answer 4:

它消耗的过程标准输出,并同时错误是非常重要的。 见卡洛斯Tasada的示例代码的其他地方在这里。

如果不依赖于您的催生过程的输出做你的代码可能(也可能不会)工作。 随着并且当输出变化(如果你的催生过程中遇到错误,说),那么没有并发消费的过程中会发生死锁。 大部分时间我对SO相关看到问题Process.exec()被阻塞相关。



文章来源: Implementing the “system” command in Java