Question

I have written an script After.sh to postpone one job to be started after another running job is finished:

echo "Waiting job $1 to be finished..."
while ps -p $1 >/dev/null; do sleep 1; done ;
echo "Job $1 finished."
echo "Now running job ${*:2}..."
${*:2}
echo "Job ${*:2} finished."

I run it like After.sh 5327 shutdown 0 to shutdown the PC after the job with PID=5327 is finished. Even I can run it like After.sh "5327 5778 5935" shutdown 0, this way it waits until all jobs 5327 5778 and 5935 are finished first.

My problem is when I want to feed a more complex job as argument to the script, for instance:

After.sh 5327 for f in *; do echo $f; done

Now it runs with an error: for: command not found. I tried to replace the command ${*:2} in the script to sh ${*:2} or eval ${*:2}, but they failed (sh fails again to find for command, eval keeps the first value of $f for the whole loop, so prints the name of the first file every time.)

Do you have any idea how to fix it?

Was it helpful?

Solution

the problem is, that you are for f in *; do echo $f; done is not a command, but rather it is bash-code, which needs a bash-interpreter to be executed.

you can start an interpreter by using eval:

#!/bin/sh

PID="$1"
shift
JOB="$@"

echo "Waiting job ${PID} to be finished..."
while ps -p ${PID} >/dev/null; do sleep 1; done ;
echo "Job ${PID} finished."
echo "Now running job '${JOB}'"
eval ${JOB}
echo "Job '${JOB}' finished."

then use single quotes for commands including variables that should be evaluated by After:

./After.sh 123 'for f in *; do echo $f; done'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top