我正试图想出一个脚本来管理超级计算机上的工作。细节并不重要,但关键是脚本一旦出现就开始tail -f文件。现在,这将永远运行,但是一旦检测到任务完成,我想彻底停止它并退出脚本。
不幸的是我被困住了。我尝试了多个解决方案,但没有一个解决方案退出脚本,即使在任务被检测到退出之后,脚本也会继续运行。下面的版本似乎是最符合逻辑的版本,但这个版本也一直在运行。
我该如何处理这个问题呢?我对bash没意见,但并不是很先进。
#!/bin/bash
# get the path to the job script, print help if not passed
jobscr="$1"
[[ -z "$jobscr" ]] && echo "Usage: submit-and-follow [script to submit]" && exit -2
# submit job via SLURM (the job secluder), and get the
# job ID (4-5-digit number) from it's output, exit if failed
jobmsg=$(sbatch "$jobscr")
ret=$?
echo "$jobmsg"
if [ ! $ret -eq 0 ]; then exit $ret; fi
jobid=$(echo "$jobmsg" | cut -d " " -f 4)
# get the stdout and stderr file the job is using, we will log them in another
# file while we `tail -f` them (this is neccessary due to a file corruption
# bug in the supercomputer, just assume it makes sense)
outf="$(scontrol show job $jobid | awk -F= '/StdOut=/{print $2}')"
errf="$(scontrol show job $jobid | awk -F= '/StdErr=/{print $2}')"
logf="${outf}.bkp"
# wait for job to start
echo "### Waiting for job $jobid to start..."
until [ -f "$outf" ]; do sleep 5; done
# ~~~~ HERE COMES THE PART IN QUESTION ~~~~ #
# Once it started, start printing the content of stdout and stderr
# and copy them into the log file
echo "### Job $jobid started, stdout and stderr:"
tail -f -n 100000 $outf $errf | tee $logf &
tail_pid=$! # catch the pid of the child process
# watch for job end (the job id disappears from the queue; consider this
# detection working), and kill the tail process
while : ; do
sleep 5
if [[ -z "$(squeue | grep $jobid)" ]]; then
echo "### Job $jobid finished!"
kill -2 $tail_pid
break
fi
done 我还尝试了另一个版本,其中tail在主进程中,而while循环运行在一个子进程中,一旦作业结束,这个循环就会杀死主进程,但是没有成功。无论哪种方式,脚本永远不会终止。
发布于 2023-05-31 10:14:19
由于@Paul_Pedant的评论,我设法找到了这个问题。当我在原始脚本中将tail传输到tee时,$!包含了tee的PID,而不是tail,因此只有tee会被杀死。后者得到一个$SIGPIPE,但显然它不足以阻止它。
解决方案如下:https://stackoverflow.com/a/8048493/5099168
在我的脚本中实现的相关行如下所示:
tail -f -n 100000 $outf $errf > >(tee $logf) &
tail_pid=$!https://unix.stackexchange.com/questions/747639
复制相似问题