2

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

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

4

2 回答 2

6

当 you 时nohup java,您会强制 JVM使用控制台。当你使用 javaConsole对象时,你试图连接一个不存在的控制台,因此总是会得到一个空Console引用。

即它不能完成:这是一个矛盾。


nohup手册页:

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

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

从 Java 7 javadoc for Console开始:

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

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

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


替代解决方案(优先顺序递减):

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

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

    请参阅在 Linux 上创建 Java 守护程序服务的工具

    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.htmhttp://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将其返回为. Stringchar[]

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

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

    将服务器运行为:

          java MainClassName 
    

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

    然后运行以下之一:

          nohup -p <PID>
    

    或者

          disown -h <JOB>   
    

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

于 2013-05-21T07:17:18.320 回答
2

nohup是一种守护进程的简单方法。太简单了,无法满足您的需求。 除了使用orbash之外,无法守护进程,这都不适合您的目的。Java 非常努力地远离操作系统级别的细节,如守护进程。 nohupdisown

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

于 2013-05-21T09:40:31.670 回答