从里面找出'at'工作的ID

当我安排一个工作与“在”它被分配一个ID,即:

工作44 2014-01-28 17:30

当这个工作运行时,我想从里面得到这个ID。 这是在Centos,FWIW上。 我已经确定没有环境variables包含该ID。 当该作业中的Perl代码运行时,我希望能够打印作业ID(本例中为44)。

是的,我知道atq在正在执行的作业旁边显示an =,但是一次可能有多个作业。

我可以做一些事情,比如在调度时向工作传递一个唯一的参数,捕获这个ID,把这个参数保存到某个文件中,从工作中读取。 如果我不必这样做,我宁愿不去做很多工作,看起来这应该很简单,但我正在画一个空白。

通过阅读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 。 有了这个守护进程试图确保将只有一个作业运行的副本:守护进程将不会执行execle(2) ,即。 如果link(2)失败,它将退出。 因为原始文件已经被open(2)dup(2)所以inode仍然在那里供内核使用,因为它仍然有指向它的硬链接。

经过相当长的时间和可能令人困惑的介绍,以下是如何把它们放在一起:

 #!/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.