首页 / JAVA / 从Java进程访问子进程控制终端
从Java进程访问子进程控制终端
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了从Java进程访问子进程控制终端,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含1991字,纯文字阅读大概需要3分钟。
内容图文
![从Java进程访问子进程控制终端](/upload/InfoBanner/zyjiaocheng/963/8f22b6d5fd974d4db4e2ef43392d31dc.jpg)
我有一个长期运行的Java服务器应用程序,它启动一个子进程来执行特定任务(在这种情况下,使用7z命令行实用程序提取7zip文件的内容,但这个特定的细节在这里不应该相关).
>服务器应用程序在Ubuntu 14下使用Java 8运行.
>子流程正在通过Java ProcessBuilder API启动.
>子进程正在访问的文件可能受密码保护.
>如果文件受密码保护且没有提供密码作为命令行参数,则7z程序将尝试向终端显示提示输入密码的消息,然后从终端读取密码.
>此时,子流程挂起并且不会完成,除非我点击< Enter>在控制Java进程的终端中两次.
基本问题似乎是7z实用程序使用getpass系统调用来显示提示和读取用户输入.根据文件:
The getpass() function opens /dev/tty (the controlling terminal of the process), outputs the string prompt, turns off echoing, reads one line (the “password”), restores the terminal state and closes /dev/tty again.
由于这是一个服务器应用程序,因此让子进程块等待来自Java终端的输入是不可接受的.我想要的是以编程方式关闭子进程终端上的输入,以便getpass调用立即返回而没有输入,并且子进程以错误代码退出.不幸的是,我关闭输入到子进程终端的所有尝试都产生了与上面相同的行为:
>我尝试在启动子流程后立即手动关闭Process.getOutputStream()返回的流.
>我尝试使用ProcessBuilder.redirectInput将子进程输入重定向到从空文件和/ dev / null读取.
>为了更好的衡量,我甚至尝试将Redirect.INHERIT传递给ProcessBuilder,即使这看起来不像我想要的远程.
看起来这应该是可行的,因为我已经观察到7z启动时所需的行为与完全相同的命令行作为守护进程的socat进程的子进程,其中终端输入连接到/ dev / null,但是我无法使用我所掌握的工具在Java中实现这一目标.
解决方法:
为了排除getpass()函数打开/ dev / tty(进程的控制终端),我们必须安排该实用程序没有控制tty,这是通过调用setsid()实现的.这个C程序(让我们命名一下) notty)进行此调用,然后执行给定的实用程序:
int main(int argc, char *argv[])
{
setsid(); // get rid of the controlling tty
close(0); // preclude reading STDIN as well
execvp(argv[1], argv+1); // execute the given program file
}
我们可以通过将它添加到ProcessBuilder命令,例如,在Java应用程序中使用它. G.:
ProcessBuilder pb = new ProcessBuilder("notty", "7z", … /*arguments*/);
内容总结
以上是互联网集市为您收集整理的从Java进程访问子进程控制终端全部内容,希望文章能够帮你解决从Java进程访问子进程控制终端所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。