altTesting has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, I have something that I'm working on, and with it, I believe I need to fork a process, and retrieve the exit status and PID. A command is exec'ed in the background that essentially is an rsync process

I'm working on a Browser based Rsync backup process: Ajax <-> Perl.cgi -> SETUID C Prog ->Perl(Rsync)

This C program is passed a username and the script to run, and it changes it's effective UID before running the Perl script, so that the rsync command can be run as an ssh login session sudo'ed to the user with environment, and subsequent key pairs, to enable a non-interactive process.

All works so far as I can tell, except for the very last bit - I'm trying to decide on the best approach to launch process, retrieve PID, and Exit Status before writing JSON back to the browser about what happened, and continue to seek read chunks from logfile and also write back to web browser in separate process

When I open pipe as a way to fork and get PID, I get success (on open pipe) even if wrapper process fails. If I exec, I get no PID etc. I know I can use 'pidof' and/or parse 'ps' command etc., but perhaps I'm not seeing a less-convoluted way to approach this?

Any awesome suggestions are welcome

### run backup command ### my @system_params = ( "-o", "log/nix_backup_wrap", "$var{usern +ame}", "./backup_run.plX" ); my $pid = open my $cmd, "-|", './nix_backup_wrap', @system_pa +rams or warn "$!\n"; my $backup_process_status = $? >> 8; my @backup_status_message; print "BACKUP PROCESS STATUS: $backup_process_status\n"; if ( $backup_process_status == 0 ) { $msglog->write( "Success starting backup process!" ); push @backup_status_message, "Success starting backup +process!"; open 'PID', '>', $PID_FILE or die "Status $var{status} +: Tried to open $PID_FILE $!\n"; print PID "$pid\n"; close PID; } else { $err_msglog->write( "Error starting backup process!" ) +; push @backup_status_message, "Error starting backup pr +ocess!"; } $jsonObject = { msgdata => "BACKUP STATUS MESSAGE: @backup_status_message with P +ID: $pid", pid => $pid, lposition => $var{lposition}, count => $var{count}, segment => $var{segment}, status => $var{status}, backup_process_status => $backup_process_status }; my $jsonEncoded = encode_json $jsonObject; print WB_OUT $cgi->header(-type => "application/json", -charset => + "utf-8"); print WB_OUT $jsonEncoded;
From Rsync Script
eval { alarm 5; $msglog->write( "/usr/bin/rsync -avz $var{username}\@$IP:/tmp/$var{ +username}/test /tmp/ | tee -a $TMPLOG" ); exec( "/usr/bin/rsync -avz $var{username}\@$IP:/tmp/$var{username}/ +test /tmp/ | tee -a $TMPLOG") or $err_msglog->write( "STATUS: $var{status}: Couldn't initiate bac +kup $!\n" ); alarm 0; };
From C Program
/* Set UID to user */ setuid( new_uid ); _user = custom_command( command_whoami ); printf("User after setuid(%d): %s\n", new_uid,_user); /* Now run the actual ".cgi" file */ strcpy( _HOME, "HOME=/home/e-smith/files/users/" ); strcat( _HOME, username ); strcpy( _LOGNAME, "LOGNAME=" ); strcat( _LOGNAME, username ); int ret; char *cmd[] = { script_name, username, (char *)0 }; char *env[] = { _HOME, _LOGNAME, "SHELL=/bin/bash", "SSH_TTY=/dev/pts/ +1", (char *)0 }; ret = execve (script_name, cmd, env); return(0); }

Replies are listed 'Best First'.
Re: Open pipe and fork or system command to retrieve PID and exit status - Best approach?
by aitap (Curate) on Aug 24, 2012 at 18:16 UTC
    launch process, retrieve PID, and Exit Status
    At the same time? PID belongs to a running process; exit status is an int returned by terminating main(). Unless I've mistaken, you can't have both meaningful at the same time: when you have the exit status, the process is already terminated.
    Anyway, have a look at IPC::Run. Other method is to pipe (thus you can read STDOUT), fork (thus you get the PID), exec then waitpid in the main procss (and then use $? to get the exit status).
    Sorry if my advice was wrong.

      Sorry, wrong definition from me - I meant Return Status and PID.

      ie. -1 or 0 or 127 etc. and if 0, the PID as well.

      I am really trying to find most suitable approach to fork, and /most reliably/ work with PID obtained, over a period of time, and different script executions. So far I have decided to fork, exec, and in essence use

       do_something() if kill 0, $PID