admin管理员组

文章数量:1390303

our application consists in a service that is launched on a linux host, in particular a yocto linux custom embedded image.

Inside the app there are calls to some bash commands in order to change the system configuration, i.e. the date, the systemd network configuration, et similar.

To achieve this I used a RunCommand method with the following implementation:

 public static Result<string> RunCommand(string command, bool wait = true)
{
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return new Result<string>() { ResultObject = "done" };

     Result<string> result = new Result<string>();
     using (Process proc = new())
     {
         proc.StartInfo.FileName = "/bin/bash";
         proc.StartInfo.Arguments = "-c \" " + command + " \"";
         proc.StartInfo.UseShellExecute = true;
         proc.StartInfo.RedirectStandardOutput = true;
         proc.StartInfo.RedirectStandardError = true;
         proc.StartInfo.CreateNoWindow = true;
        
         proc.Start();
     
         proc.OutputDataReceived += Proc_OutputDataReceived;

         result.ResultObject = proc.StandardOutput.ReadToEnd();
         var error = proc.StandardError.ReadToEnd();
         if (!string.IsNullOrWhiteSpace(error))
         {
             result.HasError = true;
             result.ErrorMessage = error;
             result.ResultCode = Enums.ResultCode.UnspecifiedError;
         }
         if (wait)
             proc.WaitForExit();
         proc.OutputDataReceived -= Proc_OutputDataReceived;
     }
     return result;
}

Now, the issue. If I call the app directly, like ./Controller all works perfectly, but if I call the app in backround, like ./Controller &, then the app hangs forever. I assume it is due to output redirection, but I don't have enough knowledge nor I know where to look at to fix this...

our application consists in a service that is launched on a linux host, in particular a yocto linux custom embedded image.

Inside the app there are calls to some bash commands in order to change the system configuration, i.e. the date, the systemd network configuration, et similar.

To achieve this I used a RunCommand method with the following implementation:

 public static Result<string> RunCommand(string command, bool wait = true)
{
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return new Result<string>() { ResultObject = "done" };

     Result<string> result = new Result<string>();
     using (Process proc = new())
     {
         proc.StartInfo.FileName = "/bin/bash";
         proc.StartInfo.Arguments = "-c \" " + command + " \"";
         proc.StartInfo.UseShellExecute = true;
         proc.StartInfo.RedirectStandardOutput = true;
         proc.StartInfo.RedirectStandardError = true;
         proc.StartInfo.CreateNoWindow = true;
        
         proc.Start();
     
         proc.OutputDataReceived += Proc_OutputDataReceived;

         result.ResultObject = proc.StandardOutput.ReadToEnd();
         var error = proc.StandardError.ReadToEnd();
         if (!string.IsNullOrWhiteSpace(error))
         {
             result.HasError = true;
             result.ErrorMessage = error;
             result.ResultCode = Enums.ResultCode.UnspecifiedError;
         }
         if (wait)
             proc.WaitForExit();
         proc.OutputDataReceived -= Proc_OutputDataReceived;
     }
     return result;
}

Now, the issue. If I call the app directly, like ./Controller all works perfectly, but if I call the app in backround, like ./Controller &, then the app hangs forever. I assume it is due to output redirection, but I don't have enough knowledge nor I know where to look at to fix this...

Share Improve this question asked Mar 12 at 15:19 Marcomattia MocellinMarcomattia Mocellin 3906 silver badges17 bronze badges 6
  • What is the command ? , any feedback from the bash session ? , try sticking the command in a shell file and run that .... – ticktalk Commented Mar 18 at 14:08
  • I have many commands, i.e. "date" but also creating files with content and permissions... Also I have to get the IP address of a labelled interface (i have eth0 setup as DHCP client, and eth0:0 as static fallback ip). – Marcomattia Mocellin Commented Mar 19 at 14:40
  • #1 Usually c# apps are built as dll and then are executed with dotnet foo.dll . How are you building your app? – JRichardsz Commented Mar 22 at 12:56
  • Does the error occur with simple commands like : ls, date, ps -ef , etc ? – JRichardsz Commented Mar 22 at 13:00
  • I am publishing the app as an executable file, so it's called straight like Controller [args]. – Marcomattia Mocellin Commented Mar 25 at 9:39
 |  Show 1 more comment

1 Answer 1

Reset to default 0

Solution

Use nohup command

nohup ./Controller >/dev/null 2>&1 &

#1 If you want to see the output I suggested you to use a log file

Explanation

The problem could be related to these lines

if (wait)
    proc.WaitForExit();

And the usage of the ampersand &.

According to this answer, one of the differences between ampersand and nohup is that if you close the shell, the process started with ampersand will be terminated while the one started with nohup will continue executing.

As a result, this sentence never ends: proc.WaitForExit()

Test with ampersand

Using this code I tried with ampersand and as was expected, it hangs for ever

dotnet run date &

Test with nohup

nohup dotnet run date >/dev/null 2>&1 &

The process is started immediately, shell exits and in the background the command is executed and does its job.

References

  • https://stackoverflow/a/53882651/3957754

本文标签: Run Bash commands in C Net Core from background appStack Overflow