【问题标题】:Perl script failing from crontabPerl 脚本从 crontab 失败
【发布时间】:2011-11-25 22:12:37
【问题描述】:

我有一个 perl 脚本,它可以读取我们的防火墙访问日志以查看谁使用了特定的 vpn 帐户。从命令行运行时这工作正常,但从 crontab 运行时失败。代码在这里

#!/usr/bin/perl -w
use strict;
use warnings;
use MIME::Lite::TT::HTML;
my $basedir = "/var/log";
my @verdir = qw(fw_d);
my $fulldir;
my $configs; 
my $combidir;
my @results;
my @files1;
foreach $combidir (@verdir) {
    $fulldir = "$basedir/$combidir";
    opendir (DIR, $fulldir);
    my @files = grep { $_ ne '.' && $_ ne '..' && $_ ne 'CVS' } readdir DIR;
    closedir (DIR);
    @files1 = sort {expand($a)cmp expand($b)}(@files);
    foreach my $configs (@files1) {
        my $now = time;
        my @stat = stat("$fulldir/$configs");
        if ($stat[9] > ($now - 2592000)) {
            system("/usr/bin/less -f $fulldir/$configs | /bin/grep NETOPS_TUNNEL >> /usr/local/CCS/ravpn/output.log"); }
        }
    }
    results();
    sendmailnew(\@results);

    sub results{
        my $input = "/usr/local/CCS/ravpn/output.log";
        open my $fh, "<", "$input" or die "could not open '$input': $!";
        while (<$fh>){
            if ($_ =~ /(................)fw.*(Group = NETOPS_TUNNEL). (Username = .(authenticated.)/){
                push (@results, "$1 $2 $3 $4<br>")
            }
        }
        return @results
    }

    sub expand  { 
        my $file=shift; 
        $file=~s{(\d+)}{sprintf "%04d", $1}eg; # expand all numbers to 4 digits
        return $file;
    }

    sub sendmailnew {
        my %params; 
        my @results = @{$_[0]};
        $params{sorted} = "@results";
        my %options; 
        $options{INCLUDE_PATH} = '/usr/local/CCS/ravpn/templates/'; 
        my $msg = MIME::Lite::TT::HTML->new( 
            From        =>  "",
            #To          =>  "", 
            BCC                 =>  "",
            Subject     =>  "", 
            Encoding    => 'quoted-printable',
            Template    =>  {
                text    =>  'test.txt.tt',
                html    =>  'sort.html.tt',
            },
            TmplOptions =>  \%options, 
            TmplParams  =>  \%params, 
        ); 

        $msg->send;
        system("rm -rf /usr/local/CCS/ravpn/output.log");
    }

当从命令行运行时,它会进入目录 /var/log/fw_d,获取所有小于 30 天的条目,并将它们传递给 less 和 grep 对它们运行,结果是输出到 output.log。 (此文件是通过 crontab 运行时创建的,但没有输出任何内容)。从命令行运行时,会将条目添加到 output.log

一旦创建了 output.log,就会扫描一组特定的项目,并将结果推送到一个名为 results 的数组中,然后通过电子邮件发送出去。

如果手动运行此脚本效果很好,但如果从 crontab(我们用于创建日志的用户或 root 用户)运行,它无法将任何内容输出到 output.log 文件。

我感觉它会很简单,但我不确定。

这是 crontab -e 条目

  40 03 * * * perl /usr/local/CCS/ravpn/ravpn.pl    

正在读取的文件要么是纯文本文件,要么是压缩文本文件,.gz,所以我需要一种无需解压缩即可读取它们的方法,因此使用 less。

感谢任何帮助。

【问题讨论】:

    标签: perl crontab


    【解决方案1】:

    尝试替换

    system("/usr/bin/less -f $fulldir/$configs | /bin/grep NETOPS_TUNNEL >> /usr/local/CCS/ravpn/output.log");
    

    system("/bin/cat $fulldir/$configs | /bin/grep NETOPS_TUNNEL >> /usr/local/CCS/ravpn/output.log");
    

    Less 并不意味着在没有终端的情况下运行。在你的情况下没有必要这样做。如果您在 perl 中执行此操作而不使用 perl 自己的函数调用 system,那就更好了:

    if ($configs =~ /\.gz$/) {
        open (F1, "gunzip -c $fulldir/$configs |");
    } else {
        open (F1, "$fulldir/$configs");
    }
    open (F2, ">> /usr/local/CCS/ravpn/output.log");
    while (<F1>) {
        print F2 $_ if (/NETOPS_TUNNEL/);
    }
    close F2;
    close F1;
    

    PS:我看到您使用 /usr/local/CCS/ravpn/output.log 作为临时文件。根据此脚本的功能,不需要该文件。它使您的脚本更加简单。

    编辑:也适用于 .gz 文件。您也可以使用 IO::Uncompress::Gunzip,但这已经更复杂了。

    【讨论】:

    • 啊抱歉,我需要提到的最后一件事,文件是文本,或者压缩为 gz,我试图使用 less,因为它似乎能够读取压缩的文本文件.. .
    • 谢谢你,因为我一直试图把事情复杂化。这非常有效。
    猜你喜欢
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 2011-10-03
    • 2013-02-06
    • 2020-05-30
    • 2016-12-10
    相关资源
    最近更新 更多