【问题标题】:Java Program that runs commands with Linux Terminal使用 Linux 终端运行命令的 Java 程序
【发布时间】:2013-09-16 23:19:02
【问题描述】:

我的问题是,我正在通过终端运行一些 adb 命令。我写了一个工具;这将有助于使事情变得更容易。所以回到问题,为了让命令运行,我必须在终端上输入一个“密码”。那么我该怎么做才能让“密码”部分出现在 JOptionPane.showInputDialog 框上呢?

这是我目前所拥有的:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;


public class flash implements ActionListener {
    private File runfile;
    @Override
    public void actionPerformed(ActionEvent arg0) {
        {


            JFileChooser adbflashfile = new JFileChooser("/home/local/ANT/arthm/Desktop/os"); 
           FileNameExtensionFilter filter = new FileNameExtensionFilter(".py", "py");

                adbflashfile.setFileFilter(filter);

            int returnVal = adbflashfile.showOpenDialog(null);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                runfile = adbflashfile.getSelectedFile();

                try {
                    Runtime.getRuntime().exec("sudo python ./flashimage.py");
                } catch (IOException e1) {

                    e1.printStackTrace();
                }
                //This is where a real application would open the file.
                System.out.println("File: " + runfile.getName() + ".");    
            } else {
                JOptionPane.showMessageDialog(null, "Open command cancelled by user.");
            }
            System.out.println(returnVal);
        }
    };
    }

【问题讨论】:

    标签: java linux terminal


    【解决方案1】:

    您“可以”读取进程输入,当您“检测”密码提示时,显示JOptionPane 并要求用户输入密码。

    您“可以”在启动流程之前提示用户输入密码,因为您知道您需要将密码发送到流程。

    您可能仍需要监视进程的输出以确定何时需要发送密码。

    让我们开始吧……

    Runtime.getRuntime().exec("sudo python ./flashimage.py");
    

    您完全忽略了Process。你也没有处理输出,但你没有办法为过程提供输入......

    一般来说,Runtime#exec 充其量是有问题的。你最好使用ProcessBuilder....

    // Build the command to be executed.  Note that each parameter becomes
    // it's own argument, this deals with parameters that contain spaces
    // much better then Runtime#exec alone...
    ProcessBuilder pb = new ProcessBuilder("sudo", "python", "./flashimage.py");
    pb.redirectError();
    
    InputStream is = null;
    try {
        Process p = pb.start();
        is = p.getInputStream();
        StringBuilder output = new StringBuilder(80);
        int in = -1;
        while ((in = is.read()) != -1) {
            if (in != '\n') {
                output.append((char)in);
                // You will need to define PASSWORD_PROMPT
                if (PASSWORD_PROMPT.equals(output.toString())) {
                    String text = JOptionPane.showInputDialog("Password");
                    OutputStream os = p.getOutputStream();
                    os.write(text.getBytes());
                }
            } else {
                System.out.println(output.toString());
                output.delete(0, output.length());
            }
        }
    } catch (IOException exp) {
        exp.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (Exception e) {
        }
    }
    

    现在,毫无疑问,有人会指出(至少)这种方法的两个问题......

    1. JOptionPane.showInputDialog("Password"); 将呈现一个普通的JTextField,它不会隐藏密码字符并且
    2. String 不是存储密码的最安全方式...

    相反,我们应该使用JPasswordField 并将生成的char 数组转换为byte 数组...

    JPasswordField password = new JPasswordField(10);
    JLabel label = new JLabel("Password: ");
    JPanel panel = new JPanel();
    panel.add(label);
    panel.add(password);
    
    int option = JOptionPane.showConfirmDialog(null, panel, "Password", JOptionPane.OK_CANCEL_OPTION);
    if (option == JOptionPane.OK_OPTION) {
        char[] userPassword = password.getPassword();
        byte[] bytes = new byte[userPassword.length * 2];
        for (int i = 0; i < userPassword.length; i++) {
            bytes[i * 2] = (byte) (userPassword[i] >> 8);
            bytes[i * 2 + 1] = (byte) userPassword[i];
        }
        os.write(bytes);
    }
    

    【讨论】:

    • 这有点临时,但应该为您提供一些实现目标的指导
    【解决方案2】:

    可以使用Process 类重定向子进程I/O。您应该能够监控输出并将输入(密码)提供给子进程。

    见:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-27
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 2018-08-21
      • 1970-01-01
      相关资源
      最近更新 更多