在 Fedora 17 上,我放入了一个/etc/cron.daily
包含以下内容的文件:
cd /
su dstahlke /home/dstahlke/bin/anacron-daily.sh
exit 0
出于某种原因,我每天都会收到一封邮件,上面写着
/etc/cron.daily/dstahlke-daily:
...killed.
我尝试了有和没有exit 0
上述行(我注意到有些系统脚本有这行,而其他的没有,我不确定目的是什么)。/etc/cron.daily/dstahlke-daily
以 root 身份从命令行运行不会产生任何...killed
消息。除了消息之外,一切似乎都运行正常。将set -x
上述脚本以及脚本放入其中/home/dstahlke/bin/anacron-daily.sh
表明,...killed
消息在后一个脚本终止后立即出现(或者可能在 su 命令完成后立即出现)。
该消息是什么原因造成的...killed
?
或者,有没有更可接受的方法让 anacron 每天运行用户脚本?我认为加入这个/etc/cron.daily
将有助于系统协调所有日常任务,而不是可能同时运行我的任务和系统任务。
答案1
我做了进一步的调查,发现程序...killed
确实打印了su
,虽然打印内容不是来自上游 coreutils 项目,但它是由源 rpm 中的 coreutils-8.5-pam.patch 引入的。在 bugzilla 上有一些关于添加此内容的起源的历史 (622700,597928和240117)。
代码的相关部分是
static sig_atomic_t volatile caught_signal = false;
...
/* Signal handler for parent process. */
static void
su_catch_sig (int sig)
{
caught_signal = true;
}
...
static void
create_watching_parent (void)
{
...
sigfillset (&ourset);
if (sigprocmask (SIG_BLOCK, &ourset, NULL))
{
error (0, errno, _("cannot block signals"));
caught_signal = true;
}
if (!caught_signal)
{
...
action.sa_handler = su_catch_sig;
...
|| sigaction (SIGTERM, &action, NULL)
...
if (caught_signal)
{
fprintf (stderr, _("\nSession terminated, killing shell..."));
kill (child, SIGTERM);
}
cleanup_pam (PAM_SUCCESS);
if (caught_signal)
{
sleep (2);
kill (child, SIGKILL);
fprintf (stderr, _(" ...killed.\n"));
}
exit (status);
}
因此,以某种方式(直接/间接与 cleanup_pam 相关或不相关)父进程在倒数第二个和最后一个 if 测试之间接收 SIGTERM,因此仅打印...killed
显然应该是上述 fprintf 的延续的消息。
总而言之,在caught_signal
函数中同时使用异步信号处理程序和本地流控制变量感觉像是一种非常肮脏的黑客行为,我不喜欢这段代码。我通过拆分它并引入 kill_child 布尔变量在函数主体中使用来进行测试,然后
if (caught_signal)
{
kill_child:
kill_child = true;
status = 1;
}
if (kill_child) {
{
fprintf (stderr, _("\nSession terminated, killing shell..."));
kill (child, SIGTERM);
}
cleanup_pam (PAM_SUCCESS);
if (kill_child)
{
sleep (2);
kill (child, SIGKILL);
fprintf (stderr, _(" ...killed.\n"));
}
exit (status);
}
在函数的末尾。通过这样的修改,我不再收到....killed
来自 anacron 的任何垃圾邮件。
所以解释起来很长,可能比你需要的信息还多。但是。我还发现了更多,这对你来说是个好消息,因为你不必对 coreutils 包进行本地修改。对于从 cron 运行 su 的情况,你应该运行该程序运行用户 反而。这对我来说是个“坏”消息,因为它使我上面的发现变得不那么重要,但好吧 :)。