【问题标题】:Achieving Terminal Commands using processbuilder使用 processbuilder 实现终端命令
【发布时间】:2018-01-31 06:26:52
【问题描述】:

我正在尝试执行以下链接中作为解决方案提供的命令:https://apple.stackexchange.com/questions/258020/why-does-find-certificates-have-some-missing 我正在使用 java 中的 processbuilder 执行命令,但由于某种原因,即使命令运行完美,我也无法从 stringbuffer 获取值在终端。 这是可能的java命令:

    ArrayList<String> lcommands = new ArrayList<String>();
        ArrayList<ArrayList<String>> lcommandsets = new ArrayList<ArrayList<String>>();
        lcommands = new ArrayList<String>(); 
        //lcommands.add("security find-identity -p codesigning -v");
//        lcommands.add("security");
//        lcommands.add("find-identity");
//        lcommands.add("-p");
//        lcommands.add("codesigning");
//        lcommands.add("-v");
        lcommands.add("security find-certificate -a -p codesign ~/Library/Keychains/login.keychain \\\n| awk '/-----BEGIN CERTIFICATE-----/ { cert = \"\" } \\\n{ cert = cert $0 \"\\n\" } \\\n/-----END CERTIFICATE-----/ { \\\nopenssl = \"openssl x509 -text -enddate -noout\"; \\\nprint cert | openssl; \\\nclose(openssl) \\\n}'");
//        lcommands.add("find-certificate");
//        lcommands.add("-a");
//        lcommands.add("-p");
//        lcommands.add("codesign");
        //lcommands.add("~/Library/Keychains/login.keychain \\\n| awk '/-----BEGIN CERTIFICATE-----/ { cert = \"\" } \\\n{ cert = cert $0 \"\\n\" } \\\n/-----END CERTIFICATE-----/ { \\\nopenssl = \"openssl x509 -text -enddate -noout\"; \\");
//        lcommands.add("~/Library/Keychains/login.keychain \\");
//        lcommands.add("| awk '/-----BEGIN CERTIFICATE-----/ { cert = \"\" } \\");
//        lcommands.add("{ cert = cert $0 \"\\n\" } \\");
//        lcommands.add("/-----END CERTIFICATE-----/ { \\");
//        lcommands.add("openssl = \"openssl x509 -text -enddate -noout\"; \\");
//        lcommands.add("print cert | openssl; \\");
//        lcommands.add("close(openssl) \\");
//        lcommands.add("}'");
        System.out.println();
        lcommandsets.add(lcommands);
        for (int i = 0; i < lcommandsets.size(); i++) {
            Process process = null;
            try {
                ArrayList lruncommands = (ArrayList) lcommandsets.get(i);
                ProcessBuilder lprocessbuilder = new ProcessBuilder(lruncommands);
            //    lprocessbuilder.directory(new File("/Users/"));
            //     lprocessbuilder.directory(new File("/Users/Admin/Library/Keychains"));
                 lprocessbuilder.redirectErrorStream(true);
                process = lprocessbuilder.start();
                try (BufferedReader bri = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                    String line;
                    while ((line = bri.readLine()) != null) {
                        //System.out.println(line);

                        if (line.contains(":") && line.contains("(")) {
                            lcertname = line.substring(line.indexOf(":") + 1, line.indexOf("(")).trim();
                            lteamid = line.substring(line.indexOf("(") + 1, line.lastIndexOf(")")).trim();
                            String ltrim=line.trim().substring(line.indexOf(')')+1);
                            luuid=ltrim.substring(0,ltrim.indexOf(" "));
                            //System.out.println("");
                            ArrayList<String> lval=new ArrayList<String>();
                            lval.add(0, luuid);
                            lval.add(1, lcertname);
                            lkeys.put(lteamid,lval );
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

所有注释行都是我尝试过的不同组合。如果有人知道如何拆分命令,那将非常有用。提前致谢。

【问题讨论】:

    标签: java process terminal


    【解决方案1】:

    问题似乎出在命令中的“管道”上。 据我所知,您必须启动一个 shell(Windows 上的 cmd)并将您的命令字符串作为参数传递。

    以下代码在windows下启动一个“git bash”,执行命令“dig www.kde.org | grep kde”。

        public static void main(String[] args) throws IOException {
        ArrayList<String> lst = new ArrayList<String>();
    
        lst.add("c:\\Anwendungen\\git\\bin\\bash");
        lst.add("-c");
        lst.add("dig www.kde.org |grep kde");
        ProcessBuilder bld = new ProcessBuilder(lst);
    
        Process proc = bld.start();
    
        BufferedReader bfRdr = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        bfRdr.lines().forEach((String line) -> {
            System.out.println(line);
        });
    }
    

    【讨论】:

    • 在 ios 上,shell 的通行证会有所不同(/usr/bin/sh ?)。只需打开控制台并输入“which bash”或“which sh”。然后,您可以将给定的路径复制并粘贴为 processbuilder 的命令。
    • 它只是查找“www.kde.org”的 DNS 记录,然后执行 grep。只是一个使用管道的例子......
    • 对于你想要完成的事情,我会构建一个包含要执行的命令的列表,并在循环内迭代列表我会做类似“ProcessBuilder bld = new ProcessBuilder(”/bin/ sh", "-c", cmdString);"
    【解决方案2】:

    作为替代方案,您可以尝试使用我在项目中使用的另一种方法。

        public static void main(String args[]) throws IOException
    
    {
        String line = null;
        InputStream in = null;
        String logFilePath = System.getProperty("user.dir") + "/logs/log1.log";
        String s1 = "grep -n 'Start' " + logFilePath + "  | tail -n 1 | cut -d : -f 1";
        String[] cmd = { "/bin/sh", "-c", s1 };
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(cmd);
            in = proc.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            line = br.readLine();
    
            // operations to be performed on matched line
        } finally {
            if (in != null)
                in.close();
        }
    }
    

    }

    【讨论】:

    • 告诉我一件事,我可以使用同一个字符串运行多个命令吗?在您的示例中,如果我将 'mvn clean install' 作为 s1 并将其传递给 cmd,它会起作用吗?
    • 命令不会是多个。该数组只允许我们以更易读的方式配置命令。您可以参考类 Runtime 的文档以获取更多详细信息:
    猜你喜欢
    • 2019-03-18
    • 1970-01-01
    • 2019-01-06
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 2018-10-02
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多