3

当我用“at”安排工作时,它被分配了一个 id,即:

工作 44 在 2014-01-28 17:30

当该作业运行时,我想从其中获取该 ID。这是在 Centos,FWIW 上。我已经确定没有环境变量包含 ID。当该作业中的 Perl 代码运行时,我希望它能够打印作业 ID(本例中为 44)。

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

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

4

1 回答 1

2

下面的内容是通过阅读 at-3.14 的来源得出的。对于任何版本,puts job id 的方式和运行到文件名的时间都应该相似,但我没有检查过。

首先将作业 id 和特定作业应该运行的时间编码到描述作业的文件名中。文件名有 format aJJJJJTTTTTTTT,其中JJJJJ5 个字符的十六进制字符串,作业 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. 我们只对包含我们需要的所有信息的文件名感兴趣。

符号链接指向已删除文件的原因是 at daemon 在执行作业之前取消链接原始文件。=只有在创建一个以代替开头的硬链接(硬链接)后才能取消链接a。有了这个, at 守护进程试图确保只有一份作业正在运行:守护进程不会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.
于 2014-09-28T17:10:59.143 回答