使用Linux终端运行命令的Java程序

时间:2021-03-04 17:31:08

My question is this, I am running some adb commands through the terminal. I wrote a tool; that will help make things easier. So back to the question, in order to make the command run, I have to enter a "password" on the terminal. So how do I what do I do to make the "password" part appear on a JOptionPane.showInputDialog box?

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

Here is what I have so far:

这是我到目前为止:

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);
        }
    };
    }

2 个解决方案

#1


1  

You "could" read the process input and when you "detect" the password prompt, display a JOptionPane and request that the user enter the password.

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

You "could" prompt the user for the password before you start the process, knowing that you are going to need to send it to the process.

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

You would probably still need to monitor the output of the process to determine when you need to send the password though.

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

Let's start with...

让我们从...开始

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

You are ignoring the Process completely. Neither are you processing the output, but you have no means to provide input to the process...

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

Generally, Runtime#exec is problematic at best. You are far better of using ProcessBuilder....

通常,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) {
    }
}

Now, undoubtedly, someone will point out (at least) two problems with this approach...

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

  1. JOptionPane.showInputDialog("Password"); will present a normal JTextField, which won't hide the password characters and
  2. JOptionPane.showInputDialog( “密码”);将呈现一个普通的JTextField,它不会隐藏密码字符和

  3. String is not the safest way to to store a password...
  4. 字符串不是存储密码最安全的方法......

Instead, we should use a JPasswordField and convert the resulting char array to a byte array...

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

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


0  

Child process I/O can be redirected, using Process class. You should be able to monitor the output & provide input (the password) into the child process.

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

See:

#1


1  

You "could" read the process input and when you "detect" the password prompt, display a JOptionPane and request that the user enter the password.

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

You "could" prompt the user for the password before you start the process, knowing that you are going to need to send it to the process.

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

You would probably still need to monitor the output of the process to determine when you need to send the password though.

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

Let's start with...

让我们从...开始

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

You are ignoring the Process completely. Neither are you processing the output, but you have no means to provide input to the process...

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

Generally, Runtime#exec is problematic at best. You are far better of using ProcessBuilder....

通常,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) {
    }
}

Now, undoubtedly, someone will point out (at least) two problems with this approach...

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

  1. JOptionPane.showInputDialog("Password"); will present a normal JTextField, which won't hide the password characters and
  2. JOptionPane.showInputDialog( “密码”);将呈现一个普通的JTextField,它不会隐藏密码字符和

  3. String is not the safest way to to store a password...
  4. 字符串不是存储密码最安全的方法......

Instead, we should use a JPasswordField and convert the resulting char array to a byte array...

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

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


0  

Child process I/O can be redirected, using Process class. You should be able to monitor the output & provide input (the password) into the child process.

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

See: