使用nohup调用java应用程序时如何从控制台获取密码

时间:2013-05-18 01:12:47

标签: java console inputstream nohup

我想在验证用户启动服务器应用程序的授权后,启动一个用java编写的服务器应用程序。所以,我尝试使用System.console()实现它。问题是我的服务器应用程序是使用nohup启动的。因此,System.console()始终返回null ...

如何在以nohup启动的JVM中使用基于控制台的用户名和密码输入。

2 个答案:

答案 0 :(得分:6)

当你nohup java时,你强迫JVM 而不是使用控制台。当您使用java Console对象时,您尝试连接不存在的控制台,因此将始终获得null Console引用。

即。它无法完成:这是一个矛盾。


来自 nohup 手册页:

  

如果标准输入是终端,则从/ dev / null重定向。如果标准输出是终端,则在可能的情况下将输出附加到'nohup.out',否则为'$ HOME / nohup.out'。如果标准错误是终端,则将其重定向到标准输出。要将输出保存到FILE,请使用'nohup COMMAND> FILE”。

即。它将进程与交互式I / O(基于unix / linux字符的控制台设备)断开连接,并连接到文件系统I / O.

来自Java 7 javadoc 控制台

  

访问与当前Java虚拟机关联的基于字符的控制台设备(如果有)的方法。

     

虚拟机是否具有控制台取决于底层平台以及虚拟机的调用方式。如果从交互式命令行启动虚拟机而不重定向标准输入和输出流,则其控制台将存在,并且通常将连接到启动虚拟机的键盘和显示器。如果虚拟机是自动启动的,例如后台作业调度程序,那么它通常没有控制台。

     

如果此虚拟机具有控制台,则它由此类的唯一实例表示,可以通过调用System.console()方法获取该实例。如果没有可用的控制台设备,则调用该方法将返回null。


替代解决方案(减少偏好顺序):

  1. 不要使用nohup;将服务器作为Unix / Linux守护程序服务运行

    守护程序服务只能通过管理员(交互式)或管理配置(自动)启动/停止。然后您不需要以“java服务器管理员”身份登录,而是使用安全的Unix / Linux登录。我希望任何连接到服务器的客户端都需要执行应用层认证(可能/可能独立于unix用户帐户)。

    请参阅Tool for creating a Java daemon service on Linux

    http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html

    或您可靠的Unix / Linux管理员的教科书

  2. 不要使用java控制台;使用java UI屏幕提示

    使用以下方法之一提示输入用户名/密码:Swing / AWT / JavaFx 使用char []存储密码(请参阅http://javarevisited.blogspot.com.au/2012/03/why-character-array-is-better-than.htmlhttp://java.about.com/od/UsingDialogBoxes/a/How-To-Make-A-Password-Dialog-Box.htm以及http://www.devshed.com/c/a/Java/Javas-Basic-User-Interface-Components/8/

  3. Gnu Screen会话

    中运行没有nohup的命令

    Gnu屏幕继续运行程序,即使用户关闭终端窗口。服务器屏幕会话仍然处于分离模式。

  4. (有缺陷)将用户名/密码设置为命令行参数&系统属性-DXXX

    按如下方式运行启动脚本:

         <startupscriptname>.sh username password
    

    内部<startupscriptname>.sh

         #! /bin/sh
         nohup java MainClassName -Dadmin.username=$1 -Dadmin.password=$2 > myout.txt 2>&1 &
    

    在java中:

         String adminUsername = System.getProperty("admin.username");
         // Avoid String for password, so it can't be snooped in the String values pool
         char[] adminPassword = System.getProperty("admin.password").toCharArray();   
    

    问题:尝试避免使用 String 作为密码。但System.getProperty在转换为String之前将其作为char[]返回。

    此外,当提示用户输入密码时,具有更强的安全性,而不是将密码输入作为脚本命令行参数。

  5. (Hacky)在​​没有nohup的情况下运行服务器,但是然后手动“背景nohup”它

    将服务器运行为:

          java MainClassName 
    

    然后通过Console输入用户名和密码。

    然后运行以下之一:

          nohup -p <PID>
    

          disown -h <JOB>   
    

    问题:如果想在中间使用交互式用户名/密码,则无法完全编写脚本。因此,存在风险用户可能忘记执行所有步骤,这意味着应用程序在用户注销时死亡(HUP信号)。此外,disownstdin, stdout & stderr的问题将无效,不会被重定向:。

答案 1 :(得分:2)

nohup是守护进程的简单方法。太简单了你的需求。除了使用bashnohup之外,disown无法守护进程,这两者都不适合您的目的。 Java非常努力地远离操作系统级别的细节,例如daemonizing。

所以你需要做的是用另一种语言编写一个小包装器,从终端获取用户名和密码,然后自己进行守护,然后启动Java程序,通过管道将用户名和密码传递给它。 (我使用键值格式并在Java程序中从stdin读取以使事情变得更容易,但你可以通过其他方式实现。)PEP 3143在python中使这很容易,但你可以在{ {3}}或Cperl