Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Redirecting standard output using the -logFile parameter when in batchmode

Discussion in 'Windows' started by DanLevi, Apr 2, 2016.

  1. DanLevi

    DanLevi

    Joined:
    Nov 24, 2013
    Posts:
    9
    Hi,

    I am trying to redirect the standard output when running batch mode but it does not output, am i missing something out? I was under the impression that if i the executable was started with the -logFile parameter withput specifying a filename it would use StandardOutput. If that is the case i am doing something wrong, if not, how can i accomplish with i need?

    I have a simple project setup in Visual Studio where i spawn a process of a unity game called Rust, or rather, its dedicated server.

    As of now the only thing that shows up in the console (in VS) is these three lines:

    Code (Console Output):
    1. Mono path[0] = 'E:/SteamCMD/servers/rust/RustDedicated_Data/Managed'
    2. Mono path[1] = 'E:/SteamCMD/servers/rust/RustDedicated_Data/Mono'
    3. Mono config path = 'E:/SteamCMD/servers/rust/RustDedicated_Data/Mono/etc'
    Here are some code:

    Code (CSharp):
    1. Process serverProcess;
    2. private void StartServerThread()
    3. {
    4.     var serverArguments = GenerateServerArguments();
    5.     var serverExecutable = Properties.Settings.Default.Rustserverexecutable;
    6.     try
    7.     {
    8.         serverProcess = new Process {
    9.             StartInfo = new ProcessStartInfo
    10.             {
    11.                 WorkingDirectory = System.IO.Path.GetDirectoryName(serverExecutable),
    12.                 FileName = serverExecutable,
    13.                 Arguments = serverArguments,
    14.                 RedirectStandardInput = true,
    15.                 RedirectStandardOutput = true,
    16.                 RedirectStandardError = true,
    17.                 UseShellExecute = false
    18.             }
    19.         };
    20.         serverProcess.OutputDataReceived += ServerProcess_OutputDataReceived;
    21.         serverProcess.ErrorDataReceived += ServerProcess_ErrorDataReceived;
    22.         serverProcess.Start();
    23.         serverProcess.BeginOutputReadLine();
    24.         serverProcess.BeginErrorReadLine();
    25.         }
    26.     catch (Exception e)
    27.     {
    28.         Console.WriteLine("Exception: " + e.Message);
    29.     }
    30. }
    31.  
    32. private void ServerProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    33. {
    34.     OutputToConsole(e.Data);
    35. }
    36. private void ServerProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
    37. {
    38.     OutputToConsole(e.Data);
    39. }
    40. void OutputToConsole(string msg)
    41. {
    42.     if (!string.IsNullOrEmpty(msg))
    43.     {
    44.         Console.WriteLine(msg);
    45.     }  
    46. }
     
    AdamFoster likes this.
  2. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    Hi,

    passing "-logPath" argument without any path has no effect.

    There isn't a parameter that you can make Unity print everything to stdout by default, but you can subscribe to Application.logMessageReceivedThreaded callback and then print it anywhere you want.
     
  3. mdrotar

    mdrotar

    Joined:
    Aug 26, 2013
    Posts:
    377
    Can you confirm that attaching to Application.logMessageReceived (the non-threaded version) will NOT trigger for Debug.Log calls performed on a background thread? That seems to be what I'm observing. If this is intended behaviour, the documentation should make it clear that you will miss background thread messages using Application.logMessageReceived.
     
    ModLunar likes this.
  4. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    Correct.
     
  5. TechCor

    TechCor

    Joined:
    Apr 3, 2015
    Posts:
    56
    I have this exact problem. Three mono lines and then nothing. What is the solution?

    When I use console.writeline it outputs to the log file and not the starting process.

    Setting the console to OpenStandardOutput does not appear to work either.
     
  6. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    There is no way to redirect output to actual stdout. But as I mentioned, you can subscribe to that event and then send the output to your parent process whatever way you want.
     
  7. Stormy102

    Stormy102

    Joined:
    Jan 17, 2014
    Posts:
    495
    Apart from the method that you suggested, is there going to be a way to output Unity's log to stdout by default with Unity? Because many different forum posts, answers and blogs say that adding -logFile with no path produces this. As we are running TeamCity under the SYSTEM account on our build server, this makes the log inaccessible. We've redirected the path to the checkout directory, but it would make more sense if we could output to stdout so that the log is collected in TeamCity's build log.
    Cheers
    Stormy
     
  8. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    You can submit a feature request if you wish, but I don't think we had anything planned.

    For a short term solution, you subscribe to Application.logMessageReceivedThreaded and write to stdout from the callback.
     
    Stormy102 likes this.
  9. Stormy102

    Stormy102

    Joined:
    Jan 17, 2014
    Posts:
    495
    Thanks for the suggestion @Tautvydas-Zilys
     
  10. rkoshak

    rkoshak

    Joined:
    Dec 1, 2014
    Posts:
    9
    Has anybody gotten
    to work?

    Ive tried putting the following code in my -executeMethod method:
    Code (CSharp):
    1. Application.logMessageReceivedThreaded += (logString, stackTrace, logType) =>
    2.         {
    3.             System.IO.TextWriter writer = Console.Out;
    4.             writer.WriteLine(logString);
    5.             writer.WriteLine(stackTrace);
    6.         };
    I get no build logs to print out in the TeamCity build log window.

    Passing "-logPath" in as an argument does work on Mac build machines. I get full logs in TC on mac with that.

    Passing "-logPath -" will print build logs within a command window or powerShell window on a Windows machine, but I cant get any output to TeamCity on those Windows machines.

    Anyone have any suggestions?

    Thanks
     
  11. Stormy102

    Stormy102

    Joined:
    Jan 17, 2014
    Posts:
    495
    https://github.com/Facepunch/Facepunch.UnityBatch
    Try taking this and modifying it to your own needs. It means wrapping Unity's output in a custom executable, but tbh it's the easy way without having to do some seriously dodgy code within Unity :p
     
  12. rkoshak

    rkoshak

    Joined:
    Dec 1, 2014
    Posts:
    9
    Stormy102 likes this.
  13. yossi_horowitz_artie

    yossi_horowitz_artie

    Joined:
    Jan 30, 2019
    Posts:
    87
    I'm necroing this, now that the `-logfile` bug is reported fixed for 2019.1:

    https://issuetracker.unity3d.com/is...-outputs-to-screen-on-os-x-but-not-on-windows

    I've got some questions:

    1) They say "Logging now defaults to stdout on all platforms when running in batchmode. Note that on Windows, this still means output won't go to console by default as Windows applications don't have stdout handle by default. Output will, however, go to stdout if you launch Unity with a valid stdout handle. I.e. launching as a child process of a build system with redirected handles" Is there a way to launch Unity with a valid stdout handle from the Windows console or from a batch file, or is this feature only usable by writing a Windows application that spawns Unity as a child process?

    2) As implied by one of the comments on that page, is this feature only usable if the "-nographics" command line parameter is also used?
     
  14. nickrapp

    nickrapp

    Unity Technologies

    Joined:
    Oct 5, 2015
    Posts:
    54
    1. Depends if you mean editor or player? For editor, I don't know of an easy way to do this from Windows without spawning as a child process. We do have some ideas how to solve for this scenario in the future, so stay tuned on that. For player, if you build with "server build" option, the entry point executable used is built with /SUBSYSTEM:CONSOLE so Windows will create std handles for you by default, that direct to the console

    2. No, you can use logfile parameter on it's own.
     
  15. yossi_horowitz_artie

    yossi_horowitz_artie

    Joined:
    Jan 30, 2019
    Posts:
    87
    I did mean the editor. Thanks for the clarification!
     
  16. nspilanis

    nspilanis

    Joined:
    Sep 14, 2013
    Posts:
    4
    I was able to tail an output file on my windows script:

    "C:\Program Files\Unity\Hub\Editor\2019.2.21f1\Editor\Unity.exe" ^
    -projectPath ../unity ^
    -quit ^
    -batchmode ^
    -buildTarget %BUILD_TARGET% ^
    -customBuildTarget %BUILD_TARGET% ^
    -customBuildName %BUILD_NAME% ^
    -customBuildPath %BUILD_PATH% ^
    -executeMethod BuildCommand.PerformBuild ^
    -logFile myTestLog.log | powershell -Command "& {Get-Content myTestLog.log -Wait}"
     
  17. scottrmathews

    scottrmathews

    Joined:
    Jun 12, 2017
    Posts:
    7

    This worked for me in my pipeline in an Azure DevOps build agent, my script included this to write logs to the output window:
    Redirect STDOUT and STDERR on the Unity process when launching the build job:

    Code (csharp):
    1. $unityArgs = @{
    2.             'FilePath' = $editor
    3.             'PassThru' = $true
    4.             'ArgumentList' = $psi.Arguments
    5.             'ErrorAction' = 'Stop'
    6.             'RedirectStandardOutput' = New-TemporaryFile
    7.             'RedirectStandardError' = New-TemporaryFile
    8.         }
    Then added the PowerShell command after the process starts to read out to the Azure DevOps log window:

    Code (csharp):
    1. while ((Get-Process -Id $process.Id -ErrorAction SilentlyContinue) -ne ( $null )) {
    2.             powershell -Command "& {Get-Content $logFile -Wait}"
    3.             }
     
    Last edited: Sep 10, 2020
  18. RambosRide

    RambosRide

    Joined:
    Nov 8, 2020
    Posts:
    24
    Specify where Unity writes the Editor or Windows/Linux/OSX standalone log file. To output to the console, specify - for the path name. On Windows, specify the - option to direct the output to stdout, which by default is not the console.

    Unity Command line help says this is possible..but cannot get it to work.​
     
  19. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    Can you elaborate on this? What are you doing and what happens?
     
  20. RambosRide

    RambosRide

    Joined:
    Nov 8, 2020
    Posts:
    24
    I was trying to test this via a simple Windows cmd. And with the -logFile - theres no redirect to stdout as the picture shows.. CL1.jpg

    I put the same args thru a C# console app and now it works..note how with C# I can change the RedirectStandardOutput.

    Process p = new Process();
    p.StartInfo.FileName = ConfigurationManager.AppSettings["UnityEditorPath"];
    p.StartInfo.Arguments = Arguments;
    p.StartInfo.UseShellExecute = false;
    p.StartInfo.RedirectStandardOutput = true;
    p.OutputDataReceived += (sender, a) => ConsoleHelper.WriteText(" " + a.Data);
    p.Start();
    p.BeginOutputReadLine();
    p.WaitForExit(); // This waits until the program called is closed

    CL2.jpg

    It really should be the default output to stdout - it's what most command line utilities I've worked with do by default.

    I hope this helps someone!
     
  21. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    It does redirect to stdout, but as documentation says, stdout on Windows for GUI applications is not the console. Console is stdout for console applications, and as you observe, if you capture stdout from Unity in a standard application, and then write it to console, it appears just fine (which proves that Unity does output to stdout).
     
  22. lsegal

    lsegal

    Joined:
    Oct 17, 2015
    Posts:
    5
    This is not exactly accurate. A Windows GUI process, will, by default, not inherit stdout handles, but the important caveat here is that they can, and more importantly, it should. It is absolutely be Unity's job to use these available APIs to redirect stdout correctly and have a functioning build system. You have a command that is expected to be used from the console, it should be expected to behave like a console app. It doesn't matter that it's running a GUI behind the scenes, it's your job to figure out the correct APIs to use and fix this objectively broken behavior. This is why Windows API exposes these process flags.
     
  23. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    The handle inheritance is set up by whatever launches a process, not the process itself. If whatever launches Unity makes it inherit stdout handle, then Unity will happily use it (as https://forum.unity.com/threads/red...ameter-when-in-batchmode.395339/#post-8035808 shows). Cmd.exe doesn't set up stdout inheritance for GUI programs and that's why you don't see it there.

    By the way, Unity 2023.1 contains a second executable (unity.com) that's compiled as a console application, which will make cmd.exe pass stdout to Unity correctly. So you can now invoke that instead of you want it to run synchronously through cmd.exe.
     
  24. Hayden-Verbrec

    Hayden-Verbrec

    Joined:
    Sep 14, 2022
    Posts:
    10
    Is documentation available anywhere for this functionality?

    I am interested but encountering some issues and can't find any documentation actually detailing what's going on here.

    Thanks
     
  25. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    What issues are you seeing?
     
  26. Hayden-Verbrec

    Hayden-Verbrec

    Joined:
    Sep 14, 2022
    Posts:
    10
    I've redirected my pointer from the .exe to the .com, trying with and without -logfile, and I'm getting what appears to be a total activity freeze.

    No response, no output, nothing.

    Our existing pipeline is running through Powershell Start-Process, so I'm wondering if that has something to do with it, but at the moment I haven't been able to test that yet.
     
  27. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    Are you able to capture the dump of the process through task manager when it freezes? Does it only happen via .com and not .exe?
     
  28. Hayden-Verbrec

    Hayden-Verbrec

    Joined:
    Sep 14, 2022
    Posts:
    10
    The .exe works and outputs to the output log file in realtime. Had no issues.

    This is the code;

    Code (csharp):
    1. Start-Process -FilePath $unity -Wait -NoNewWindow -ArgumentList `
    2. "-batchmode", `
    3. "-quit", `
    4. "-projectPath $unityProjectPath", `
    5. "-logfile $unityLogFile", `
    6. "-buildWindowsPlayer $clientBuildDestination"
    When I redirected it towards the .com I removed the -logfile argument, trying both -logfile ` and no argument at all.

    I'll try and capture a dump for you now, the tricky thing is that I'm not getting any visible errors at all. It just sort of goes into some kind of standby like nothing is happening and no output is being redirected.

    I imagine there may be something I'm missing here, but I'm not sure what.

    Edit:

    Further investigation leads me to believe that Unity is indeed finishing compiling and completing the builds.

    However, not only is my implementation not reading back to the console, but the console doesn't receive a completion record and as such gets stuck at that part of the script while it endlessly waits for one.
     
    Last edited: Jul 7, 2023
  29. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    Try using "-logfile -". That will make Unity output to stdout.
     
  30. frekons_unity

    frekons_unity

    Joined:
    Sep 6, 2018
    Posts:
    20
    @Tautvydas-Zilys We want to log our logs to file but log some specific messages to console in Linux. We want to log specific messages to console like FPS statistiscs etc.

    Currently we use "-nographics -logFile game_server.log" as parameter and we want to keep this while only outputting statistics to console in Linux. Is there any way to accomplish this?
     
  31. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    That'd be pretty hard, -logFile argument quite literally overrides the stdout handle in order to capture everything in the log file.
     
  32. Hayden-Verbrec

    Hayden-Verbrec

    Joined:
    Sep 14, 2022
    Posts:
    10
    Hey, this has worked for the most part now.

    Output is being correct passed back to Powershell, however—now it forcefully closes the powershell instance when it returns rather than allowing it to continue executing.

    I've tried `-Wait` and also `$process.WaitForExit()` with `-Passthru` neither of which work as expected.

    Using `-NoNewWindow` is also mandatory since otherwise it flashes a cmd on the screen for half a second and then forcefully closes the cmd and the powershell.

    So far, this is the currently working code with the unexpected application exit.

    Code (CSharp):
    1. $unityBuildProcess = Start-Process -FilePath $unity -NoNewWindow -PassThru -ArgumentList `
    2.     "-batchmode", `
    3.     "-quit", `
    4.     "-projectPath $unityProjectPath", `
    5.     "-logFile -", `
    6.     "-buildWindowsPlayer $clientBuildDestination"
    7.  
    8. $unityBuildProcess.WaitForExit()
    9.  
    10. Read-Host -prompt "`nFinished! Press any key to exit...`n"
    The Read-Host following will never execute.
     
    Last edited: Jul 12, 2023
  33. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,504
    That is weird, we don't really interact with the parent process. Does the same thing happen if you start Unity from cmd.exe?