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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

System.Diagnostics.Process() bin/sh not opening Terminal window.

Discussion in 'Scripting' started by fingersbleeding, Feb 2, 2017.

  1. fingersbleeding

    fingersbleeding

    Joined:
    Jun 10, 2013
    Posts:
    24
    I cannot get a Terminal window to open from Process.Start().

    The following should execute a shell script in a new Terminal window.

    using(var process=new Process())
    {
    process.StartInfo.FileName="/bin/sh";
    process.StartInfo.Arguments="shell.sh;
    process.StartInfo.WorkingDirectory="path/to/working/directory";
    process.StartInfo.CreateNoWindow=false;
    process.StartInfo.UseShellExecute=false;
    process.StartInfo.RedirectStandardOutput=false;

    process.Start();
    process.WaitForExit();
    process.Close();
    }

    This SHOULD open Terminal and run shell.sh.
    Instead, it runs shell.sh silently without opening Terminal.

    Yes, I could reroute the output from shell.sh back into Unity. But if I'm running something like npm install or pod install, or something like fastlane sigh where I need to enter app store credentials, running silently isn't an option.

    The ONLY way I can get Terminal to open is by using
    process.StartInfo.FileName="open";
    and ensuring that my .sh files are set to open in Terminal by default.

    2 downsides to this method:
    1. This instance ignores the WorkingDirectory argument and defaults to my home directory.
    2. I cannot pass parameters into the shell script by appending onto the end of the Arguments string.
    And as a result, I can't pass in my working directory in order to cd to the appropriate location from within the shell script.

    What am I missing here? Why isn't Terminal opening when I using FileName="/bin/sh", and how should I pass params using FileName="open"?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    use code tags:
    https://forum.unity3d.com/threads/using-code-tags-properly.143875/

    No it shouldn't... it should open /bin/sh and run shell.sh

    /bin/sh is not a terminal, it's the shell, which is by design headless. You must capture input and output in linux for the shell... this is what programs like 'xterm' or 'terminal' or the sort do. They give a gui to the shell display output, and directing input.

    Yep, because 'open' tells your OS to open the file with the program it thinks it aught to. So in your desktop environment it's probably defaulted to use something like 'xterm' or another terminal emulator and then runs the script.
     
    Last edited: Feb 2, 2017
  3. fingersbleeding

    fingersbleeding

    Joined:
    Jun 10, 2013
    Posts:
    24
    Thanks for your reply @lordofduct. I was under the impression that running /bin/sh (or /bin/bash) out of Unity with certain params set on the Process.StartInfo object would open the shell in Terminal. But as you've explained, that is not the case.

    Do you know of a way to pass arguments to a file when using open? Appending --args to the Arguments string passes those arguments to the default application (in this case Terminal) and not to the shell script.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    well, for one, don't use 'open'. That just asks the OS to figure out what should be used to open some given file based. In your case a *.sh file, which the OS says to use your terminal.

    Instead, open the terminal, and pass arguments to that. You can tell a terminal to execute something with the -e command:

    In my case, I use Linux Mint, so I used 'mate-terminal':
    Code (csharp):
    1.  
    2. using (var proc = new Process ()) {
    3.    proc.StartInfo.FileName = "mate-terminal";
    4.    proc.StartInfo.Arguments = "-e ./test.sh";
    5.    proc.StartInfo.WorkingDirectory = "/home/dylan/Temp";
    6.    proc.StartInfo.CreateNoWindow = false;
    7.    proc.StartInfo.UseShellExecute = false;
    8.    proc.StartInfo.RedirectStandardOutput = false;
    9.  
    10.    proc.Start ();
    11.    proc.WaitForExit ();
    12.    proc.Close ();
    13. }
    14.  
    Thing is, this requires you to know the terminal application used.

    Another option is to use the $TERM environment variable, as long as it is set correctly. (go into a terminal, type 'echo $TERM', if the output is that of the terminal you want to use and is installed... it should work)

    Code (csharp):
    1.  
    2. var term = System.Environment.GetEnvironmentVariable("TERM");
    3. using (var proc = new Process ()) {
    4.    proc.StartInfo.FileName = term;
    5.    proc.StartInfo.Arguments = "-e ./test.sh";
    6.    proc.StartInfo.WorkingDirectory = "/home/dylan/Temp";
    7.    proc.StartInfo.CreateNoWindow = false;
    8.    proc.StartInfo.UseShellExecute = false;
    9.    proc.StartInfo.RedirectStandardOutput = false;
    10.  
    11.    proc.Start ();
    12.    proc.WaitForExit ();
    13.    proc.Close ();
    14. }
    15.  
    Unfortunately, when using the MonoDevelop debugger it doesn't give you access to the environment variables (because, of course it doesn't...). Not sure if Unity in debug mode with have access (I haven't used the linux build of the editor). It 'should' work if built though.... don't currently have the time to confirm though. Give it a try.

    Of course, another issue is that when doing this the terminal actually spins up its own process when executing that script. So this process won't wait for it. You need to for it to... so add the --disable-factory command as well.

    Code (csharp):
    1.  
    2. using (var proc = new Process ()) {
    3.    proc.StartInfo.FileName = "mate-terminal";
    4.    proc.StartInfo.Arguments = "--disable-factory -e ./test.sh";
    5.    proc.StartInfo.WorkingDirectory = "/home/dylan/Temp";
    6.    proc.StartInfo.CreateNoWindow = false;
    7.    proc.StartInfo.UseShellExecute = false;
    8.    proc.StartInfo.RedirectStandardOutput = false;
    9.  
    10.    proc.Start ();
    11.    proc.WaitForExit ();
    12.    proc.Close ();
    13. }
    14.  
    Is there a reason you need to show a terminal window when you do this?

    Is this just so you can display the output from the shell script?

    If so... you can capture the output from shell and display that.

    Code (csharp):
    1.  
    2. using (var proc = new Process ()) {
    3.    proc.StartInfo.FileName = "/bin/sh";
    4.    proc.StartInfo.Arguments = "test.sh";
    5.    proc.StartInfo.WorkingDirectory = "/home/dylan/Temp";
    6.    proc.StartInfo.CreateNoWindow = false;
    7.    proc.StartInfo.UseShellExecute = false;
    8.    proc.StartInfo.RedirectStandardOutput = false;
    9.  
    10.    proc.Start ();
    11.    proc.WaitForExit ();
    12.  
    13.    string result = proc.StandardOutput.ReadToEnd ();
    14.    Debug.Log(result);
    15.  
    16.    proc.Close ();
    17. }
    18.  
     
    Last edited: Feb 2, 2017
  5. fingersbleeding

    fingersbleeding

    Joined:
    Jun 10, 2013
    Posts:
    24
    I landed on this:
    Code (CSharp):
    1.  
    2. process.StartInfo.FileName = "osascript";
    3. process.StartInfo.Arguments = string.Format("-e 'tell application \"Terminal\" to do script \"cd {0} && ./{1} \"'", scriptPath, script);
    4. process.StartInfo.WorkingDirectory = workingDirectory;
    5. process.StartInfo.UseShellExecute = false;
    6.  
    7. process.Start();
    8. process.WaitForExit();
    9. process.Close();
    10.  
     
    litebox likes this.
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    lol... and here I was thinking you were in linux....

    I completely forget OSX exists sometimes.

    Interesting technique, and hey... if it works, it works.