当我使用'at'安排作业时,会为其分配一个ID,即:
工作44在2014-01-28 17:30
当这项工作开始时,我想从内部获取该ID。这是在Centos,FWIW。我已经确定没有环境变量包含ID。当该作业中的Perl代码运行时,我希望它能够打印作业ID(在本例中为44)。
是的,我知道atq在正在执行的作业旁边显示一个=,但一次可能有多个作业。
我可以做一些事情,例如在调度时将一个唯一的参数传递给作业,捕获ID,将该参数保存到文件某处,从作业中读取。如果我不需要,那么我宁愿不去做很多工作,看起来这应该很简单,但我要画一个空白。
答案 0 :(得分:2)
通过阅读at-3.14的来源可以得出以下内容。放置工作ID的方式以及它运行到文件名的时间应该与任何版本类似,但我还没有检查过。
开始编码作业ID和特定作业应该在描述作业的文件名中运行的时间。文件名的格式为aJJJJJTTTTTTTT
,其中JJJJJ
为5个字符的十六进制字符串,作业ID,TTTTTTTT
为8个字符的十六进制字符串,即应运行作业的时间。时间存储为纪元的秒数。
通过将作业描述文件作为标准输入提供给sh -c
来运行作业。幸运的是,Linux内核提供了一个符号链接/proc/self/fd/0
,它将指向当前正在执行的进程的标准输入(如果您需要确保自己确实如此),请使用ls -l /proc/self/fd/0
。
在作业运行时删除了描述作业的文件。但是,该文件仍可用于内核,因为它在用作作业的标准输入之前已与dup(2)
重复。所以,实际上我们正在解析一个不再可见的文件名的符号链接。在最后的perl脚本中,我们需要考虑到这一点,因为readlink
将返回类似/foo/bar/baz (deleted)
而不是/foo/bar/baz
的内容。我们只对文件名感兴趣,该文件名包含我们需要的所有信息。
符号链接指向已删除文件的原因是,守护程序在执行作业之前取消链接原始文件。只有在创建了一个以=
而不是a
开头的硬拷贝后,才能取消链接。有了这个,at守护进程会尝试确保只有一个正在运行的作业副本:守护进程不会execle(2)
,即。如果link(2)
失败,它会纾困。因为原始文件受open(2)
和dup(2)
约束,所以内核仍然可供内核使用,因为它仍然有指向它的硬链接。
经过一段相当长时间且可能令人困惑的介绍,以下是如何将它们放在一起:
#!/usr/bin/perl
use strict;
use warnings;
my $job_file = readlink("/proc/self/fd/0");
if (index($job_file, " ") > 0) {
$job_file = substr($job_file, 0, index($job_file, " ") - 1);
}
my $tmp = substr($job_file, rindex($job_file, "/") + 1);
$tmp =~ s/^a([0-9a-f]{5})[0-9a-f]+/$1/;
my $job_id = hex($tmp);
if ($job_id > 0) {
printf("My AT job id is %d.\n", $job_id);
}
# end of file.