【问题标题】:I have a linux script that runs flawlessly from the command line but refuses to work as a cron我有一个 linux 脚本,可以从命令行完美运行,但拒绝作为 cron 工作
【发布时间】:2015-02-26 17:14:28
【问题描述】:

此脚本在登录时运行,但我无法让它在 cron 作业下运行,有什么想法吗?

如果检测到发送电子邮件所必须的任何图形/视觉差异,此脚本用于监控 web 页面的更改。

我已阅读有关此类问题的其他帖子,并尝试实施一些建议,但我仍然收到错误,即使有更改,我也没有收到电子邮件。 (仅供参考:出于保密目的,电子邮件已更改)

#!/usr/local/cpanel/3rdparty/bin/perl
`SHELL=/bin/bash`;
`PATH=/usr/local/jdk/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/root/bin`;
`cd /root/pagechange`;
`rm -f null`;
`wkhtmltoimage --no-images --height 3000 --javascript-delay 7500 http://www.google.com /root/pagechange/sys.jpg`;
`$dif=/usr/bin/compare -metric AE /root/pagechange/sys.jpg /root/pagechange/sys1.jpg null: 2>&1`;
print "1";
if ( $dif == 0 ) {
  print "They're equal\n";
} else {
   $to = 'me@domain.com';
   $from = 'you@domain.com';
   $subject = 'Page changes detected ';
   $message = "Get to work";
   print "2";
   open(MAIL, "|/usr/sbin/sendmail -t");
# Email Header
   print MAIL "To: $to\n";
   print MAIL "From: $from\n";
   print MAIL "Subject: $subject\n\n";
# Email Body
   print MAIL $message;
print "3";
   close(MAIL);
   print "Email Sent Successfully\n";
}

print "4";
`cp /root/pagechange/sys.jpg /root/pagechange/sys1.jpg`;
print "5";
#`rm /root/pagechange/index.html`;
exit

【问题讨论】:

  • 无论如何都不能解决您的问题,但看起来使用 Perl 并没有真正为您提供任何优势。也许解决问题的一种方法是简单地使用 shell 脚本。
  • 那么当 cron 尝试执行脚本时会发生什么?你得到什么错误?我们无法猜测,您必须告诉我们!检查日志文件!
  • afaik 每个反引号命令都会创建一个新的系统调用/一个新的 shell。所以后来被调用的不会“知道”你之前声明的变量。如果是 bash,您可以 #!/usr/bin/bash --login 执行您的个人资料,就像登录设置您的变量“全局”一样。不知道在 perl 中是否可能。在你的情况下,为什么不使用 shell 脚本,因为你使用 perl merley 只是为了执行 shell 命令?
  • 当你说这个程序“完美无缺”时,我可能会说“无论如何,它确实会产生一些看起来像是在工作的东西,但更有可能是运气和缺乏的结合好的测试用例。”您尝试在反引号命令中分配给$dif 的行只是表明您不了解自己在做什么,如果您认为这行得通,那只是因为您没有使用use strict; use warnings;
  • 正如@evilive 所说,您不能使用反引号、qx()system 等系统调用来设置 shell 变量,因为它们每次都会打开一个新的 shell,当命令结束时,这个新的 shell并且它的所有设置都被丢弃。如果这确实有效,那是因为您的 shell 已经以某种方式设置了这些变量。或者您使用的路径和外壳与您想象的不同。但是,您可以通过在 %ENV 中设置路径来影响路径,例如$ENV{PATH} = " ... "

标签: linux bash perl cron


【解决方案1】:

这就是 Perl 中的样子。我只修改了最明显的问题:

#!/usr/bin/perl
use strict;
use warnings;

# Set the environment with the %ENV hash
# environment variables set in a subshell will not persist
$ENV{SHELL} = '/bin/bash'; # although you don't need this
$ENV{PATH}  = ...;

# change directory
chdir '/root/pagechange' or die "Could not change directory: $!";

# remove a file with unlink
unlink 'null';

# list argument form of system
# this prevents arguments from being treated as special by the shell
# use full path to executable so you know which one you use
system '/path/to/wkhtmltoimage', qw(
    --no-images --height 3000 --javascript-delay 7500 
    http://www.google.com /root/pagechange/sys.jpg
    );

# save the result of the backticks to get the program output
my $dif = `/usr/bin/compare -metric AE /root/pagechange/sys.jpg /root/pagechange/sys1.jpg null: 2>&1`;

print "1";
if ( $dif == 0 ) {
    print "They're equal\n";
    } 
else {
    my $to      = 'me@domain.com';
    my $from    = 'you@domain.com';
    my $subject = 'Page changes detected';
    my $message = "Get to work";

    print "2";
    open(MAIL, "|/usr/sbin/sendmail -t");
    # Email Header
    print MAIL "To: $to\n";
    print MAIL "From: $from\n";
    print MAIL "Subject: $subject\n\n";
    # Email Body
    print MAIL $message;

    print "3";
    if( close(MAIL) ){
        print "Email Sent Successfully\n";
        }
    else { # close puts the error in $? instead of $! (until 5.22!)
        my $error = $? >> 8; 
        print "Problem sending mail: $error";
        }
    }

print "4";
# list argument form of system, again
system '/bin/cp', qw(/root/pagechange/sys.jpg /root/pagechange/sys1.jpg);

print "5";
# unlink '/root/pagechange/index.html';

【讨论】:

    【解决方案2】:

    除此之外,它必须是:

    $dif=`/usr/bin/compare -metric AE /root/pagechange/sys.jpg /root/pagechange/sys1.jpg null: 2>&1`;
    

    您没有在代码中的脚本中将任何内容分配给 $dif 作为变量。而且无论你在 shell 中以你的方式做什么,它都会留在 shell 中。

    编辑:仅此一项肯定不能解决您的问题,请检查其他 cmets

    【讨论】:

    • 不正确。它将尝试在命令中插入$dif,这只会产生空字符串。 use warnings 会发现这一点并警告连接或字符串中未初始化的变量。之后的检查if ($dif == 0) 给人一种工作的错觉,也是因为没有使用use warnings。那里的警告应该是use of uninitialized value in numeric eq。结果是误报,因为undef == 0 为真。
    • @TLP 抱歉,为什么不正确?在反引号中执行并在标量上下文中分配会导致将已执行命令的整个输出作为字符串分配给变量。 perlhowto.com/executing_external_commands(不过你的其他言论是对的;))
    • 命令在shell中设置$dif是不正确的。执行的命令将是=/usr/bin/compare -metric ...,因为$dif 将被内插为空字符串""。就好像你做了my $str = "$dif= ..."; qx($str);。你的其余答案都是正确的。
    • 没错,但我不是那个意思。我希望我现在在上面说得更清楚了。
    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 2011-05-11
    • 2015-04-12
    • 2017-07-26
    • 1970-01-01
    相关资源
    最近更新 更多