如何从Perl脚本设置crontab?

时间:2016-06-27 20:52:02

标签: perl crontab sudo

我目前正在Perl中编写CGI脚本,该脚本应该在crontab(工作)中读取,允许在Web浏览器(TODO)中轻松操作,并且最终应该在编辑它时设置crontab(失败) 。 要预先回答有关安全性的任何问题:脚本只能在VPN隧道内访问,因此在“网络”上是不可见的

无论如何,这是有问题的代码:

if($p_action eq 'set')
  {
my $l_i = 1;
my $l_param;

  if(!open(CRON, "| /usr/bin/sudo /usr/bin/crontab"))
    {
    print CRON "CRON_TZ=$l_param\n" if(defined ($l_param = $cgi->param("cron_tz")));
    print CRON "MAILTO=$l_param\n" if(defined ($l_param = $cgi->param("mailto")));
    print CRON "SHELL=$l_param\n" if(($l_param = $cgi->param("shell")) ne 'unset');

    print CRON "\n" if(defined $cgi->param("cron_tz") || defined $cgi->param("mailto") || $cgi->param('shell') ne 'unset');

    while(defined $cgi->param("line$l_i-min"))
      {
my $l_min = $cgi->param("line$l_i-min");
my $l_hour = $cgi->param("line$l_i-hour");
my $l_day = $cgi->param("line$l_i-day");
my $l_month = $cgi->param("line$l_i-month");
my $l_wday = $cgi->param("line$l_i-wday");
my $l_cmd = $cgi->param("line$l_i-cmd");

      print CRON "- " if($cgi->param("line$l_i-nolog") eq 'Nolog');
      print CRON $l_min.' ';
      print CRON $l_hour.' ';
      print CRON $l_day.' ';
      print CRON $l_month.' ';
      print CRON $l_wday.' ';
      print CRON $l_cmd."\n";
      $l_i++;
      }

    close(CRON);
    }
  }

我已经允许sudoers文件中的/ usr / bin / crontab -l和/ usr / bin / crontab供wwwrun执行。

虽然在打开管道时实际执行了crontab,但是没有任何内容传递给crontab,因此导致空的crontab。看来我在这里缺少一些关键的东西,但我不太可能看到它可能是什么。关于如何解开这个东西的任何线索?

P.S。:我想将root权限限制为尽可能少的代码行,因此以root身份运行脚本不是一种选择。

4 个答案:

答案 0 :(得分:1)

sudo在提供密码的情况下使用标准输入,因此无法将输入通过管道传递给sudo'ed命令。

要安装crontab,crontab支持语法

crontab FILE

作为一种解决方法,您可以将crontab内容写入文件并调用

system("/usr/bin/sudo /usr/bin/crontab $FILE");

答案 1 :(得分:0)

我认为你在crontab上缺少一个“ - ”参数。没有它,contab不知道你想要它从stdin读取。 (另外,不要在sudo中使用“-u”可能有点冒险。)

有关详细信息,请参阅“man crontab”...

答案 2 :(得分:0)

MrCleanX可能打算用他的参考open - perldoc暗示的是

  

Open成功返回非零值,否则返回未定义值。

所以,写作

analemma’s

如果 if(!open(CRON, "| /usr/bin/sudo /usr/bin/crontab")) 成功而不是失败,则跳过以下块。

答案 3 :(得分:0)

让这个东西休息然后做一些阅读(man crontab实际上给了我最重要的提示)我只是将管道放在open语句中,而是将crontab写入临时文件。 完成后,我需要做的就是调用sudo / usr / bin / crontab / tmp /,而不必添加重定向来安装新的crontab。

问题解决了......