Appending '&' to execute in the background?

I have a set of scripts that define variables and then use another script to actually execute commands, not unlike the rc.d system. The problem I've come across is a certain program, that typically runs as a daemon, not actually support daemonizing via any command line arguments or configuration options (as far as I can tell, anyway). Thus, I need to append a '&' to run it in the background on startup--though I don't want to do this for all the other programs. My problem is as follows:

Code:
# Example subroutine in the shared script
foo $bar $args

# The problem is, if I append '&' in args, it is passed as an argument and
# not interpreted as attempting to run the process in the background, e.g.
args="-foo bar &"
# which does not work.  Furthermore, even passing in a '&' as a separate
# variable doesn't work, and neither does enclosing the command in backticks
# and then appending a '&' in a variable at the end.  e.g.
foo $bar $args $bg
# with
bg='&'
# doesn't work (interprets '&' as an arg) and neither does
`foo $bar $args` $bg
# which doesn't move into the background.

I did find one way to work around it, but it's not ideal. You copy the command twice, and then enclose it in an if. I don't like it because it's prone to error when editing or updating the script, but it would look something like this:

Code:
# In the variable definition, I would have
bg=1 # to run in the background, or
bg=0 # for programs that can daemonize themselves

# And then in the subroutine script...
if [ $bg -ne 0 ]; then
    foo $bar $args &
else
    foo $bar $args
fi

So, is there a way to achieve this without duplicating the execution line?
 
Okay, figured out a solution. I store the entire command line in a variable, and then I execute in an if, one with a trailing ampersand and one without. Like so:

Code:
cmdline=foo $bar $args

if [ $bg -ne 0 ]; then
    $cmdline &
else
    $cmdline
fi

This way if I need to update the command line, I only need to update the single instance, and I can still force programs into the background by setting bg=1 (or bg=0 when I don't want to).
 
Code:
cmdline=foo $bar $args
backgnd=""

[ "$bg" -gt 0 ] && backgnd="&"
$cmdline $backgnd

Untested. I'm not sure that using the & is the right way to do this, but sh(1) is so weak it may be. Output from the backgrounded process could mess up the foreground display. Redirect stdout and stderr if needed.
 
Orum said:
So, is there a way to achieve this without duplicating the execution line?
As phoenix said it's actually pretty simple:
Code:
# Specify one of these:
bg="&" # to run in the background, or
bg="" # for programs that can daemonize themselves

# And then in the subroutine script...
[b]eval[/b] foo $bar $args $bg
I tested the following at the prompt:
Code:
[b]fonz@spectrum>[/b] sh
[b]sh$[/b] COMMAND=ls
[b]sh$[/b] ARGS="-R /"
[b]sh$[/b] BG="&"
[b]sh$[/b] eval $COMMAND $ARGS $BG
This executes the command % ls -R / in the background.
 
Back
Top