【发布时间】:2013-12-25 22:47:02
【问题描述】:
我们有 bash 脚本(作业包装器),它写入文件、启动作业,然后在作业完成时将有关作业的信息附加到文件中。包装器在数千个批处理节点之一上运行,但只出现了几台批处理机器(我相信是 RHEL6)访问一个 NFS 服务器,以及在不同批处理节点上使用不同批处理作业的至少一个已知实例NFS 服务器。在所有情况下,只有一个客户端主机正在写入相关文件。有些作业需要几个小时才能运行,有些则需要几分钟。
在发生这种情况的同一时间段内,100,000 多个工作中似乎有 10-50 个问题。
这是我认为有效的作业包装器的(蒸馏)版本:
#!/bin/bash
## cwd is /nfs/path/to/jobwd
## This file is /nfs/path/to/jobwd/job_wrapper
gotEXIT()
{
## end of script, however gotEXIT is called because we trap EXIT
END="EndTime: `date`\nStatus: Ended”
echo -e "${END}" >> job_info
cat job_info | sendmail jobtracker@example.com
}
trap gotEXIT EXIT
function jobSetVar { echo "job.$1: $2" >> job_info; }
export -f jobSetVar
MSG=“${email_metadata}\n${job_metadata}”
echo -e "${MSG}\nStatus: Started" | sendmail jobtracker@example.com
echo -e "${MSG}" > job_info
## At the job’s end, the output from `time` command is the first non-corrupt data in job_info
/usr/bin/time -f "Elapsed: %e\nUser: %U\nSystem: %S" -a -o job_info job_command
## 10-360 minutes later…
RC=$?
echo -e "ExitCode: ${RC}" >> job_info
所以我认为有两种可能:
echo -e "${MSG}" > job_info
此命令会抛出损坏的数据。/usr/bin/time -f "Elapsed: %e\nUser: %U\nSystem: %S" -a -o job_info job_command
这会破坏现有数据,然后正确输出数据。
但是,某些作业(但不是全部)调用 jobSetVar,它最终不会损坏。
因此,我深入研究了 time.c(从 GNU 时间 1.7 开始)以查看文件何时打开。总而言之,time.c 实际上是这样的:
FILE *outfp;
void main (int argc, char** argv) {
const char **command_line;
RESUSE res;
/* internally, getargs opens “job_info”, so outfp = fopen ("job_info", "a”) */
command_line = getargs (argc, argv);
/* run_command doesn't care about outfp */
run_command (command_line, &res);
/* internally, summarize calls fprintf and putc on outfp FILE pointer */
summarize (outfp, output_format, command_line, &res); /
fflush (outfp);
}
所以,time 让FILE *outfp(job_info 句柄)打开了整个作业时间。然后它在作业结束时写入摘要,然后实际上并没有关闭文件(不确定 fflush 是否需要这样做?)我不知道 bash 是否也同时打开了文件句柄.
编辑:
损坏的文件通常由损坏的部分组成,然后是未损坏的部分,如下所示:
损坏的部分,发生在未损坏的部分之前,通常主要是一堆 0x0000,可能混入了一些循环垃圾:
这是一个 hexdump 示例:
40000000 00000000 00000000 00000000
00000000 00000000 C8B450AC 772B0000
01000000 00000000 C8B450AC 772B0000
[ 361 x 0x00]
然后,在第 409 个字节处,它继续未损坏的部分:
Elapsed: 879.07
User: 0.71
System: 31.49
ExitCode: 0
EndTime: Fri Dec 6 15:29:27 PST 2013
Status: Ended
另一个文件如下所示:
01000000 04000000 805443FC 9D2B0000 E04144FC 9D2B0000 E04144FC 9D2B0000
[96 x 0x00]
[Repeat above 3 times ]
01000000 04000000 805443FC 9D2B0000 E04144FC 9D2B0000 E04144FC 9D2B0000
后面是未损坏的部分:
Elapsed: 12621.27
User: 12472.32
System: 40.37
ExitCode: 0
EndTime: Thu Nov 14 08:01:14 PST 2013
Status: Ended
还有其他文件有更多的随机损坏部分,但不止一些是与上述类似的循环。
编辑 2: 从echo -e 语句发送的第一封电子邮件正常。由于没有电子邮件元数据损坏,最后一封电子邮件永远不会发送。所以MSG 在那一点上没有损坏。假设 job_info 可能 在那时也没有损坏,但我们还无法验证这一点。这是一个没有进行重大代码修改的生产系统,我已经通过审计验证了没有同时运行的作业会触及这个文件。这个问题似乎是最近才出现的(过去 2 个月),但它可能以前发生过并被忽略了。此错误确实会阻止报告,这意味着作业被视为失败,因此通常会重新提交它们,但特定用户有大约 9 小时的作业,其中此错误特别令人沮丧。我希望我能想出更多信息或随意复制它的方法,但我希望有人可能已经看到了类似的问题,尤其是最近。我不管理 NFS 服务器,但我会尝试与管理员交谈,了解在这些问题(我相信是 RHEL6)运行时 NFS 服务器的更新。
【问题讨论】:
-
有趣的效果!您能否举例说明损坏的文件通常是什么样的?
-
我添加了几个例子
标签: bash time batch-processing nfs