我对 bash 非常了解,所以如果这个问题很容易解决,我深表歉意,如果需要更多细节,请告诉我。下面的脚本是一个较大脚本的一部分,用于启动 python 工作流程并等待 results.json 文件在工作流程结束时更新。
我尝试过使用
{
sleep 1m
kill $$
}&
但是当 results.json 文件在 1 分钟内刷新时,这会生成错误:
杀死:(90015)-没有这样的进程
这是脚本:
#! /bin/bash
export DISPLAY=:0.0
export outputfile=results.json
if [[ ! -e $outputfile ]]; then
touch $outputfile
fi
OldTimestamp=$(date -r $outputfile)
{
sleep 1m
kill $$
}&
NewTimestamp=$OldTimestamp;
while [ "$NewTimestamp" = "$OldTimestamp" ]; do
sleep 0.1
NewTimestamp="$(date -r $outputfile)"
done
答案1
如果你只想摆脱它杀死:(90015)-没有这样的进程错误,您可以在杀死进程之前检查进程是否仍在运行:
{
sleep 1m
ps -p $$ > /dev/null && kill $$
}&
但实际上我根本不会使用kill。您可以只跟踪 while 循环的交互次数,并在适当的迭代次数后中断循环:
NewTimestamp=$OldTimestamp;
iterations=0
while [ "$NewTimestamp" = "$OldTimestamp" ] && [ $iterations -lt 600 ]; do
sleep 0.1
NewTimestamp="$(date -r $outputfile)"
let iterations++
done
如果您想在文件未更新的情况下以非零退出代码退出,您可以在之后添加:
if [ "$NewTimestamp" = "$OldTimestamp" ] ; then
echo "results.json was not updated" >&2
exit 1
fi
或者类似的。
答案2
如果您必须以这种方式执行此操作,这就是为什么您在成功生成 results.json 时收到该错误的原因:当您将 sleep 和 Kill 放在大括号中时,这称为组命令。当您将 & 符号放在大括号后面时,会将其放入子 shell 的后台($$
仍然有效,因为它在解析和执行组命令时已更改为当前 pid)。如果您的 Python 程序成功完成,则没有任何信息告诉运行 sleep 和kill 的子进程消失。当睡眠到期时,它会运行kill,并且由于您的原始脚本不再运行,因此它会抱怨“没有这样的进程”。
以下是让它发挥作用的方法。当你得到成功的结果后就跑kill %1
,这会消除睡眠和杀戮。
OldTimestamp=$(date -r $outputfile)
{
sleep 1m
kill $$
}&
NewTimestamp=$OldTimestamp;
while [ "$NewTimestamp" = "$OldTimestamp" ]; do
sleep 0.1
NewTimestamp="$(date -r $outputfile)"
done
echo "I have found my $outputfile and am done"
kill %1 # Kill off the subprocess which would have killed off this script
我在上面说过“如果你必须......”,因为这不是人们写这篇文章的典型方式。通常,您会使用timeout
命令来运行 Python 脚本,该脚本应该创建 results.json。这样,您可以检查该运行的状态,如果不成功,只需退出脚本即可。
它还具有在达到超时时间后终止报告生成器的好处。上面的方法不会:如果报告生成器运行缓慢,您会看到它仍在后台运行,即使顶级脚本已完成。 (我正在对您的系统如何工作做出一些假设,但一般来说,此方法只会停止顶级脚本,而不会停止脚本本身启动的任何内容)
如果你的 python 脚本名为“makereport.py”,我们可以这样做:
#!/bin/bash
export outputfile=results.json
OldTimestamp=$(date +"%s" -r $outputfile) # Use %s so we have a simple integer
timeout 1m makereport.py
if [[ $? -ne 0 ]]; then
echo "makereport.py failed"
exit 1
fi
# At this point you can either assume report.json was created, or you
# can check it like you did before
CurTimestamp=$(date +"%s" $outputfile)
if [[ $CurTimestamp = $OldTimestamp ]]; then
echo "makereport.py finished successfully, but a new report was not generated"
fi
echo "Verified we have a new report.json ready to go"