简体   繁体   中英

How to get password from console when java application is invoked using nohup

I want to start a sever application, written in java, after verifying the users authorization to start the server app. So, I tried implementing it using System.console() . The problem is my server app is started using nohup . So, System.console() always returns null...

How can I have console based username and password inputs in a JVM started with nohup.

When you nohup java , you're forcing the JVM not to use a console. When you use the java Console object, you're attempting to interface a non-existent console and hence will always get a null Console reference.

ie it can't be done: it's a contradiction.


From nohup man page:

If standard input is a terminal, redirect it from /dev/null. If standard output is a terminal, append output to 'nohup.out' if possible, '$HOME/nohup.out' otherwise. If standard error is a terminal, redirect it to standard output. To save output to FILE, use 'nohup COMMAND > FILE'.

ie it disconnects the process from interactive I/O (the unix/linux character-based console device) and connects to filesystem I/O.

From Java 7 javadoc for Console :

Methods to access the character-based console device, if any, associated with the current Java virtual machine.

Whether a virtual machine has a console is dependent upon the underlying platform and also upon the manner in which the virtual machine is invoked. If the virtual machine is started from an interactive command line without redirecting the standard input and output streams then its console will exist and will typically be connected to the keyboard and display from which the virtual machine was launched. If the virtual machine is started automatically, for example by a background job scheduler, then it will typically not have a console.

If this virtual machine has a console then it is represented by a unique instance of this class which can be obtained by invoking the System.console() method. If no console device is available then an invocation of that method will return null.


Alternative Solutions (Decreasing Order of Preference):

  1. Don't use nohup; Run server as Unix/Linux daemon service

    Daemon service can only be started/stopped via administrator (interactive) or administrative configuration (automated). Then you wouldn't need to login as a "java server admin", but instead use the secure Unix/Linux login. I would expect any client connecting to server would need to carry out application-layer authentication (possibly/probably independent of unix user accounts).

    See Tool for creating a Java daemon service on Linux and

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

    or your trusty Unix/Linux Administrator's Text Book

  2. Don't use java Console; Use java UI screen to Prompt

    Prompt for username/password using one of: Swing / AWT / JavaFx.
    Use char[] to store the password (see http://javarevisited.blogspot.com.au/2012/03/why-character-array-is-better-than.html and http://java.about.com/od/UsingDialogBoxes/a/How-To-Make-A-Password-Dialog-Box.htm and http://www.devshed.com/c/a/Java/Javas-Basic-User-Interface-Components/8/ )

  3. Run command without nohup, within Gnu Screen session

    Gnu screen continues to run programs, even when user closes terminal window. The server screen session still exists in a detached mode.

  4. (Flawed) Set username/password as command-line args & system properties -DXXX :

    Run a startup script as follows:

      <startupscriptname>.sh username password 

    Inside <startupscriptname>.sh :

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

    In 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(); 

    Problem: Tried to avoid using String for password. But System.getProperty returns it as String , before it's converted to char[] .

    Also, have stronger security when user is prompted for password, rather than having password input as script command line argument.

  5. (Hacky) Run the server without nohup, but then manually "background nohup" it

    Run the server as:

      java MainClassName 

    Then enter username and password through Console .

    Then run one of:

      nohup -p <PID> 

    or

      disown -h <JOB> 

    Problem: Can't script this altogether, if want interactive username/password in the middle. Hence, there's a risk user may forget to do all steps, meaning app dies when user logs out (HUP signal). Also, a problem for disown : stdin, stdout & stderr will be non-functional and won't be redirected: .

nohup is a simple way of daemonizing a process. Too simple for your needs. bash is not able to daemonize a process except for using nohup or disown , neither of which suits your purpose. Java tries very hard to stay away from OS-level details like daemonizing.

So what you need to do is write a small wrapper in another language that gets the username and password from the terminal, then daemonizes itself, then launches the Java program, passing username and password to it via a pipe. (I'd use a key-value format and read from stdin in the Java program to make things easier, but you can do it other ways.) PEP 3143 makes this easy in python, but you can do it in C or perl or Ruby .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM