我目前正在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身份运行脚本不是一种选择。
答案 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。
问题解决了......