如何将字符串发送到终端而无需使其成为标准命令?

3

我正在使用Java编写一个需要使用终端命令的程序。我的函数基本上是这样的:

public void sendLoginCommand() throws IOException
{
    System.out.println("\n------------Sending Login Command------------\n");
    String cmd="qskdjqhsdqsd";
    Runtime rt = Runtime.getRuntime();
    Process p=rt.exec(cmd);
}
public Process sendPassword(String password) throws IOException
{
    System.out.println("\n------------Sending Password------------\n");
    String cmd=password;
    Runtime rt = Runtime.getRuntime();
    Process p=rt.exec(cmd);
    return p;
}
public void login(String password) throws IOException
{
    sendLoginCommand();
    Process p = sendPassword(password);
    System.out.println("\n------------Reading Terminal Output------------\n");
    Reader in = new InputStreamReader(p.getInputStream());

    in = new BufferedReader(in);
    char[] buffer = new char[20];
    int len = in.read(buffer);
    String s = new String(buffer, 0, len);
    System.out.println(s);
    if(s.equals("Password invalid.")) loggedIn=false;
    else loggedIn=true;
}

在这里,程序发送了正确的p4登录命令,但是终端随后要求输入密码。 当我使用与sendLoginCommand()相同的行时,程序返回错误。 显然,我们只能通过Process发送标准命令。 我希望有人知道如何向终端发送普通字符串。
提前感谢您。

1
我必须说,你搞得一团糟做得很好。你实际上正在尝试使用登录名和密码作为启动该进程的命令行。这是完全错误的。 - Marko Topolnik
不,这里的“main”函数是login()。首先,它调用sendlogincommand()成功发送命令,但当调用下一个函数sendpassword()时,我无法发送密码,因为它不是一个命令。而且,你可能会说命令“qsdqsdsdkqsdq”不是一个命令,那么这是真的,原始命令是“p4 login”。 - Mtrompe
4个回答

3
你现在面临的问题是,你为每个“命令”启动了单独的进程。密码“命令”被发送到一个完全不知道之前“登录”命令的进程中。
话虽如此,你更加紧迫的问题是对 Process 类的用途和如何从 Java 中与外部程序交互存在严重误解。
这里有一个 tutorial 可以帮助你进一步学习这个主题,我建议你搜索其他教程。

1

我已经找到了我的问题的答案。

问题在于终端的第二个响应实际上在第一个响应中,并且密码必须在其中间发送。 这是代码(我同意,我的解释有点含糊):

    String s="";
    Process p = Runtime.getRuntime().exec("p4 login");     
    BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));    
    char a=(char)in.read();
    while(a>0 && a<256)
    {

        a=(char)in.read();
        if(nb==14) new PrintWriter(p.getOutputStream(),true).println(password); 
        if(nb>16) s=s+a;
        nb++;
    }
    if(s.startsWith("User")) loggedIn=true;
    else loggedIn=false;

0
为了与进程通信,您不需要启动另一个进程,而是要写入其标准输入。实际上,有一些代码可以尝试这样做。让sendLoginCommand返回创建的进程;删除sendPassword中的所有代码,事实上删除整个方法。在您的主要代码中,将密码写入进程的输出流。所以我的意思是:
new PrintWriter(sendLoginCommand().getOutputStream()).println(password);

我不理解应该如何使用p.getOutputStream()和PrintWriter。你能否详细说明一下? - Mtrompe
实际上,很抱歉,它不起作用。我以为它能够工作是因为没有返回错误,但是new PrintWriter(sendLoginCommand().getOutputStream()).println(password);根本没有任何作用,因为当我尝试在之后检索终端的输出时,我得到的是“输入密码”,这是先前命令“p4 login”的输出。 - Mtrompe
即使我已经发送了密码,为什么我仍然可以看到“输入密码”?因为我的程序需要能够读取终端的输出,以判断密码是否正确。 - Mtrompe
这是由于缓冲机制所造成的。当你的p4进程执行输出该字符串的代码时,这个瞬间和你的Java代码读取它的瞬间并不相同。想一想,这怎么可能呢? - Marko Topolnik
我同意这个事实,即我不能同时阅读,但即使在我发送“p4 login”之后等待一段时间再检索输出,我仍然会看到“输入密码”,甚至无法确定密码是否已被发送。 - Mtrompe
显示剩余8条评论

0
作为附注,我强烈建议使用预打包的库来封装Java中有关进程通信的所有技术细节。
一个很好的库是commons-exec(http://commons.apache.org/exec/)。
它带有命令行助手、后台线程来读取sysout/syserr输出、可选的看门狗在给定时间后杀死进程等等(当然它可以在几乎所有操作系统上运行)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接