Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.out being swallowed #37

Closed
beirtipol opened this issue Feb 3, 2016 · 8 comments
Closed

System.out being swallowed #37

beirtipol opened this issue Feb 3, 2016 · 8 comments

Comments

@beirtipol
Copy link

The System.out prints are getting swallowed by the getdown app. I can see that my application is launching successfully and writing a test file to the filesystem but can't see any stdout in either the launcher.log or in the console I launch the app from. I guess it's something to do with log4j config?

@beirtipol
Copy link
Author

Here's the output from the launcher.log

2016/02/03 12:25:09:935 INFO n.a: ------------------ VM Info ------------------
2016/02/03 12:25:09:938 INFO n.a: -- OS Name: Windows 7
2016/02/03 12:25:09:938 INFO n.a: -- OS Arch: amd64
2016/02/03 12:25:09:938 INFO n.a: -- OS Vers: 6.1
2016/02/03 12:25:09:938 INFO n.a: -- Java Vers: 1.6.0_45
2016/02/03 12:25:09:938 INFO n.a: -- Java Home: C:\dev\java\jdk1.6.0_45_x64\jre
2016/02/03 12:25:09:938 INFO n.a: -- User Name: myUsername
2016/02/03 12:25:09:939 INFO n.a: -- User Home: C:\Users\myUsername
2016/02/03 12:25:09:939 INFO n.a: -- Cur dir: C:\Temp
2016/02/03 12:25:09:939 INFO n.a: ---------------------------------------------
2016/02/03 12:25:09:982 INFO n.a: Failed to find proxy settings in Windows registry [error=java.lang.UnsatisfiedLinkError: no     jRegistryKey in java.library.path]
2016/02/03 12:25:09:987 INFO n.a: ---------------- Proxy Info -----------------
2016/02/03 12:25:09:987 INFO n.a: -- Proxy Host: null
2016/02/03 12:25:09:987 INFO n.a: -- Proxy Port: null
2016/02/03 12:25:09:987 INFO n.a: ---------------------------------------------
2016/02/03 12:25:10:001 INFO n.a: Able to lock for updates: true
2016/02/03 12:25:10:038 INFO n.a: Verifying application: http://localhost:8000/
2016/02/03 12:25:10:038 INFO n.a: Version: -1
2016/02/03 12:25:10:038 INFO n.a: Class: com.myapp.GetDownVerifier
2016/02/03 12:25:10:040 INFO n.a: Dropping status 'm.validating'.
2016/02/03 12:25:10:059 INFO n.a: Attempting to refetch 'digest.txt' from 'http://localhost:8000/digest.txt'.
2016/02/03 12:25:10:231 INFO n.a: No signers, not verifying file [path=digest.txt]
2016/02/03 12:25:10:234 INFO n.a: Unversioned digest changed. Revalidating...
2016/02/03 12:25:10:254 INFO n.a: Resource failed digest check [rsrc=myapptest-getdown-2016.02.20.1-SNAPSHOT.jar,     computed=2caaf642e6c687de42fde75d0f86ca52, expected=d63837dfdb5f127a849c8d2a3480c2fa]
2016/02/03 12:25:10:304 INFO n.a: 1 of 2 rsrcs require update (0 assumed valid).
2016/02/03 12:25:10:335 INFO n.a: Downloading 3322 bytes...
2016/02/03 12:25:10:338 INFO n.a: Downloading resource [url=http://localhost:8000/myapptest-getdown-2016.02.20.1-SNAPSHOT.jar,     size=3322]
2016/02/03 12:25:10:339 INFO n.a: Verifying application: http://localhost:8000/
2016/02/03 12:25:10:339 INFO n.a: Version: -1
2016/02/03 12:25:10:340 INFO n.a: Class: com.myapp.GetDownVerifier
2016/02/03 12:25:10:341 INFO n.a: Attempting to refetch 'digest.txt' from 'http://localhost:8000/digest.txt'.
2016/02/03 12:25:10:344 INFO n.a: No signers, not verifying file [path=digest.txt]
2016/02/03 12:25:10:350 INFO n.a: Resources verified.
2016/02/03 12:25:10:352 INFO n.a: Didn't find any custom environment variables, not setting any.
2016/02/03 12:25:10:352 INFO n.a: Running C:\dev\java\jdk1.6.0_45_x64\jre\bin\javaw.exe
  -classpath
  C:\Temp\myapptest-getdown\myapptest-getdown-2016.02.20.1-SNAPSHOT.jar;C:\Temp\myapptest-getdown\getdown\getdown.jar
  -Dcom.threerings.getdown=true
  com.myapp.GetDownVerifier

@samskivert
Copy link
Member

Unfortunately, Getdown can't pass through stdout and stderr because it needs to eventually terminate its own process and leave the app process running. If it did not immediately close stdout and stderr, then the app process would hang on some platforms as soon as the Getdown launcher process exited.

This means that your app has to redirect System.out and System.err to a file when it starts up if you want to use those for logging.

The alternative would be to have the Getdown process stay alive for the lifetime of the app process, but then you'd have two whole JVMs running instead of just one, which is a huge memory waste.

@octane100
Copy link

I am confronted to the same problem.

I tried to add output redirects on the javaw.exe command line but it doesn't seem to work:

apparg = >
apparg = console.log
apparg = 2>&1

Perhap's it will work if we launch cmd.exe instead of direct javaw.exe ?

@samskivert
Copy link
Member

You can't use shell mechanisms to redirect your app's output because Getdown does not use a shell to run your app. You have to redirect the output from inside your Java program. Here's an example from the Bang! Howdy client which should give you the idea:

    /**
     * Redirects the output of the application to the specified log file and configures our various
     * logging systems.
     */
    public static void configureLog (String logfile)
    {
        // potentially redirect stdout and stderr to a log file
        File nlog = null;
        if (System.getProperty("no_log_redir") == null) {
            // first delete any previous previous log file
            File olog = new File(BangClient.localDataDir("old-" + logfile));
            if (olog.exists()) {
                olog.delete();
            }

            // next rename the previous log file
            nlog = new File(BangClient.localDataDir(logfile));
            if (nlog.exists()) {
                nlog.renameTo(olog);
            }

            // and now redirect our output
            try {
                PrintStream logOut = new PrintStream(new FileOutputStream(nlog), true);
                System.setOut(logOut);
                System.setErr(logOut);

            } catch (IOException ioe) {
                log.warning("Failed to open debug log", "path", nlog, "error", ioe);
            }
        }
        // ...
        // if we've redirected our log output, note where to
        if (nlog != null) {
            log.info("Logging to '" + nlog + "'.");
        }
    }

    public static void main (String[] args)
    {
        // configure our debug log
        configureLog("bang.log");

        // ...
    }

@beirtipol
Copy link
Author

That's a big issue unfortunately. If the logging system fails to initialise
due to misconfiguration or classpath errors, or indeed if the app falls
over before that, devs rely on the program's console output to diagnose
startup problems.

I think it's already been suggested but I would also suggest allowing
invocation of a system shell (ksh; bash; cmd; ps; etc) if not even as the
default action, to contain the java/javaw process

On Thu, 11 Feb 2016, 20:36 Michael Bayne notifications@github.com wrote:

You can't use shell mechanisms to redirect your app's output because
Getdown does not use a shell to run your app. You have to redirect the
output from inside your Java program. Here's an example from the Bang!
Howdy client which should give you the idea:

/**     * Redirects the output of the application to the specified log file and configures our various     * logging systems.     */
public static void configureLog (String logfile)
{
    // potentially redirect stdout and stderr to a log file
    File nlog = null;
    if (System.getProperty("no_log_redir") == null) {
        // first delete any previous previous log file
        File olog = new File(BangClient.localDataDir("old-" + logfile));
        if (olog.exists()) {
            olog.delete();
        }

        // next rename the previous log file
        nlog = new File(BangClient.localDataDir(logfile));
        if (nlog.exists()) {
            nlog.renameTo(olog);
        }

        // and now redirect our output
        try {
            PrintStream logOut = new PrintStream(new FileOutputStream(nlog), true);
            System.setOut(logOut);
            System.setErr(logOut);

        } catch (IOException ioe) {
            log.warning("Failed to open debug log", "path", nlog, "error", ioe);
        }
    }
}

public static void main (String[] args)
{
    // configure our debug log
    configureLog("bang.log");

    // ...
}


Reply to this email directly or view it on GitHub
#37 (comment).

@samskivert
Copy link
Member

If the first action in main() is to redirect stdout/stderr then any output will go there from any logging system or whatnot. Wrapping the process in a shell is not something that can be done in a cross-platform way. There is no shell that exists on all platforms.

@beirtipol
Copy link
Author

You're right of course, the dev would need to define which shell is to be
used on all platforms they are deploying to.

The problem with some apps (one of my current ones) is that the main()
entry point is third party code which does its own crud before touching
user code. This can (and does) fail to initialise and quietly fails to the
console log before getting any logging set up.

It's possibly getting beyond the scope of what you originally intended for
this app but I'm hoping to replace a significant chunk of other (rather
more expensive and shall remain nameless) deployment software with this
tool so I'm eager to get a lot out of it:)

On Sat, 13 Feb 2016, 22:13 Michael Bayne notifications@github.com wrote:

If the first action in main() is to redirect stdout/stderr then any output
will go there from any logging system or whatnot. Wrapping the process in a
shell is not something that can be done in a cross-platform way. There is
no shell that exists on all platforms.


Reply to this email directly or view it on GitHub
#37 (comment).

@samskivert
Copy link
Member

Even in a situation like that, you should be able to write a shim class:

public class RedirectAndRun {
  public static void main (String[] args) {
    // redirect System.out, System.err
    RealApp.main(args);
  }
}

and bundle that with your app and run that class instead of having Getdown
run RealApp directly.

And as an added bonus, the log redirecting will be cross-platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants