Std::process::command::new not returning

I am trying to run a shell script from my Rust code, and I am having partial success.

I am having problems if the shell script starts other processes in the back ground. The match process::Command::new(command.as_str()).output() does not return.

I can run the exact same shell script from the command line and there is no such problem

I am on a Raspberry Pi 4, Raspbian GNU/Linux 10

The shell script I am running is an absolute path, and the script itr runs, too, use absolute paths.

I am stumped

        match process::Command::new(command.as_str()).output() {
            Ok(out) => {
                if out.status.success() {
                    let s = String::from_utf8_lossy(&out.stdout);
                    eprintln!("Success: {} and stdout was:\n{}", cmd, s)
                } else {
                    let s = String::from_utf8_lossy(&out.stderr);
                    eprintln!("Not success: {} and stderr was:{}", cmd, s)
                }
            }
            Err(err) => eprintln!("Failure: cmd {}  Err: {:?}", command, err),
        }

Could you share the shell script, and the command you're executing? The script must not be exiting, but it's hard to know why without seeing it.

Background processes don't normally prevent scripts from exiting. Normally, any children that are still running when a parent process exits are orphaned and get re-parented to init.

Does your script expect input from stdin?

I have worked it out:

I am hanging on to stdout and stdin after fork. So process::Command has to wait for all the children to exit. Since one of my children is persistent it will not.

This is the script called by process::command

#!/bin/sh
echo ON-CTL.39
/tmp/test.pl
echo ON-CTL.39 Over

This is /tmp/test.pl. I have made progress: The process::Command::new call is waiting for all the children to complete because fork holds stdin and stdout

#!/usr/bin/perl -w
use strict;
print "In $0\n";
my $pid = fork();
if($pid){
    print "In parent $$.  Child pid: $pid\n";
}else{
    print scalar(localtime())." In child.  \n";
    sleep(5);
    print scalar(localtime())."exit child\n";
    exit 0;
}

This (mostly from the PerlIPC man page) seems to fix it.

#!/usr/bin/perl -w                                                                                                                                                                
use strict;
print "In $0\n";

use POSIX "setsid";


    chdir("/")                  || die "can't chdir to /: $!";
    open(STDIN,  "< /dev/null") || die "can't read /dev/null: $!";
    open(STDOUT, "> /dev/null") || die "can't write to /dev/null: $!";
    defined(my $pid = fork())   || die "can't fork: $!";
    exit if $pid;               # non-zero now means I am the parent                                                                                                              
    (setsid() != -1)            || die "Can't start a new session: $!";
    open(STDERR, ">&STDOUT")    || die "can't dup stdout: $!";
    print scalar(localtime())." In child.  \n";
    sleep(5);
    print scalar(localtime())."exit child\n";
    exit 0;

That Perl script forks a child which sleeps five seconds. After five seconds process::Command returns.

It must to be able to hand me back a String as stdout.

The Rust code

        eprintln!("run_cmd({}) Command: {}", &cmd, &command);
        match process::Command::new(command.as_str()).output() {
            Ok(out) => {
                if out.status.success() {
                    let s = String::from_utf8_lossy(&out.stdout);
                    eprintln!("Success: {} and stdout was:\n{}", cmd, s)
                } else {
                    let s = String::from_utf8_lossy(&out.stderr);
                    eprintln!("Not success: {} and stderr was:{}", cmd, s)
                }
            }
            Err(err) => eprintln!("Failure: cmd {}  Err: {:?}", command, err),
        }

When it runs this is outputs (to demonstrate it holding on until all children exit)

run_cmd(ON-CTL.39) Command: /......./ON-CTL.39
Success: ON-CTL.39 and stdout was:
ON-CTL.39
In /tmp/test.pl
In parent 19620.  Child pid: 19621
ON-CTL.39 Over
Sat Jul  9 18:10:29 2022 In child.
Sat Jul  9 18:10:34 2022exit child