I am writing a script in bash, which is calling two bash scripts internally. Where first script includes different tests which runs in background and second script print results of first script.
我正在用bash编写一个脚本,它在内部调用两个bash脚本。第一个脚本包括在后台运行的不同测试,第二个脚本打印第一个脚本的结果。
When I run these two scripts one after other, sometimes, second script get executed before first script ends Which prints wrong results.
当我一个接一个地运行这两个脚本时,有时会在第一个脚本结束之前执行第二个脚本,这会打印出错误的结果。
I am running both scripts with source command. Any better suggestions?
我正在使用source命令运行这两个脚本。还有更好的建议?
source ../../st_new.sh -basedir $STRESS_PATH -instances $INSTANCES
source ../../results.sh
3 个解决方案
#1
9
Shell scripts, no matter how they are executed, execute one command after the other. So your code will execute results.sh
after the last command of st_new.sh
has finished.
Shell脚本,无论它们如何执行,都会在另一个之后执行一个命令。因此,在st_new.sh的最后一个命令完成后,您的代码将执行results.sh。
Now there is a special command which messes this up: &
现在有一个特殊的命令搞砸了这个:&
cmd &
means: "Start a new background process and execute cmd
in it. After starting the background process, immediately continue with the next command in the script."
表示:“启动一个新的后台进程并在其中执行cmd。启动后台进程后,立即继续执行脚本中的下一个命令。”
That means &
doesn't wait for cmd
to do it's work. My guess is that st_new.sh
contains such a command. If that is the case, then you need to modify the script:
这意味着&不等待cmd做它的工作。我的猜测是st_new.sh包含这样的命令。如果是这种情况,那么您需要修改脚本:
cmd &
BACK_PID=$!
This puts the process ID (PID) of the new background process in the variable BACK_PID
. You can then wait for it to end:
这将新后台进程的进程ID(PID)放在变量BACK_PID中。然后,您可以等待它结束:
while kill -0 $BACK_PID ; do
echo "Process is still active..."
sleep 1
# You can add a timeout here if you want
done
or, if you don't want any special handling/output simply
或者,如果您不想要任何特殊的处理/输出
wait $BACK_PID
Note that some programs automatically start a background process when you run them, even if you omit the &
. Check the documentation, they often have an option to write their PID to a file or you can run them in the foreground with an option and then use the shell's &
command instead to get the PID.
请注意,某些程序在运行时会自动启动后台进程,即使您省略了&。检查文档,他们通常可以选择将PID写入文件,或者您可以使用选项在前台运行它们,然后使用shell的&命令来获取PID。
#2
1
Make sure that st_new.sh does something at the end what you can recognize (like touch /tmp/st_new.tmp when you remove the file first and always start one instance of st_new.sh).
Then make a polling loop. First sleep the normal time you think you should wait, and wait short time in every loop. This will result in something like
确保st_new.sh最终能够识别出什么(比如首先删除文件时触摸/tmp/st_new.tmp并始终启动一个st_new.sh实例)。然后进行轮询循环。首先睡觉你认为应该等待的正常时间,并在每个循环中等待很短的时间。这会产生类似的结果
max_retry=20
retry=0
sleep 10 # Minimum time for st_new.sh to finish
while [ ${retry} -lt ${max_retry} ]; do
if [ -f /tmp/st_new.tmp ]; then
break # call results.sh outside loop
else
(( retry = retry + 1 ))
sleep 1
fi
done
if [ -f /tmp/st_new.tmp ]; then
source ../../results.sh
rm -f /tmp/st_new.tmp
else
echo Something wrong with st_new.sh
fi
#3
-2
You can just add a sleep
line between the two source
lines to make the script wait a specific amount of seconds.
您可以在两个源代码行之间添加一个睡眠行,以使脚本等待特定的秒数。
But without understanding what st_new.sh
does, we can't explain to you why there is some racing condition.
但是如果不了解st_new.sh的作用,我们就无法向你解释为什么会出现一些竞争条件。
source ../../st_new.sh -basedir $STRESS_PATH -instances $INSTANCES
sleep 5 # Wait 5 seconds for st_new.sh to finish.
source ../../results.sh
#1
9
Shell scripts, no matter how they are executed, execute one command after the other. So your code will execute results.sh
after the last command of st_new.sh
has finished.
Shell脚本,无论它们如何执行,都会在另一个之后执行一个命令。因此,在st_new.sh的最后一个命令完成后,您的代码将执行results.sh。
Now there is a special command which messes this up: &
现在有一个特殊的命令搞砸了这个:&
cmd &
means: "Start a new background process and execute cmd
in it. After starting the background process, immediately continue with the next command in the script."
表示:“启动一个新的后台进程并在其中执行cmd。启动后台进程后,立即继续执行脚本中的下一个命令。”
That means &
doesn't wait for cmd
to do it's work. My guess is that st_new.sh
contains such a command. If that is the case, then you need to modify the script:
这意味着&不等待cmd做它的工作。我的猜测是st_new.sh包含这样的命令。如果是这种情况,那么您需要修改脚本:
cmd &
BACK_PID=$!
This puts the process ID (PID) of the new background process in the variable BACK_PID
. You can then wait for it to end:
这将新后台进程的进程ID(PID)放在变量BACK_PID中。然后,您可以等待它结束:
while kill -0 $BACK_PID ; do
echo "Process is still active..."
sleep 1
# You can add a timeout here if you want
done
or, if you don't want any special handling/output simply
或者,如果您不想要任何特殊的处理/输出
wait $BACK_PID
Note that some programs automatically start a background process when you run them, even if you omit the &
. Check the documentation, they often have an option to write their PID to a file or you can run them in the foreground with an option and then use the shell's &
command instead to get the PID.
请注意,某些程序在运行时会自动启动后台进程,即使您省略了&。检查文档,他们通常可以选择将PID写入文件,或者您可以使用选项在前台运行它们,然后使用shell的&命令来获取PID。
#2
1
Make sure that st_new.sh does something at the end what you can recognize (like touch /tmp/st_new.tmp when you remove the file first and always start one instance of st_new.sh).
Then make a polling loop. First sleep the normal time you think you should wait, and wait short time in every loop. This will result in something like
确保st_new.sh最终能够识别出什么(比如首先删除文件时触摸/tmp/st_new.tmp并始终启动一个st_new.sh实例)。然后进行轮询循环。首先睡觉你认为应该等待的正常时间,并在每个循环中等待很短的时间。这会产生类似的结果
max_retry=20
retry=0
sleep 10 # Minimum time for st_new.sh to finish
while [ ${retry} -lt ${max_retry} ]; do
if [ -f /tmp/st_new.tmp ]; then
break # call results.sh outside loop
else
(( retry = retry + 1 ))
sleep 1
fi
done
if [ -f /tmp/st_new.tmp ]; then
source ../../results.sh
rm -f /tmp/st_new.tmp
else
echo Something wrong with st_new.sh
fi
#3
-2
You can just add a sleep
line between the two source
lines to make the script wait a specific amount of seconds.
您可以在两个源代码行之间添加一个睡眠行,以使脚本等待特定的秒数。
But without understanding what st_new.sh
does, we can't explain to you why there is some racing condition.
但是如果不了解st_new.sh的作用,我们就无法向你解释为什么会出现一些竞争条件。
source ../../st_new.sh -basedir $STRESS_PATH -instances $INSTANCES
sleep 5 # Wait 5 seconds for st_new.sh to finish.
source ../../results.sh