2015-08-19 84 views
0

我不熟悉linux/linux环境,所以如果我犯了任何错误,请原谅我,做一下评论澄清。Cronjob在perl脚本中不执行命令行

我创建了一个简单的perl脚本。该脚本创建一个sql文件,如图所示,它将执行要插入数据库的文件中的行。

#!/usr/bin/perl 

use strict; 
use warnings; 
use POSIX 'strftime'; 

my $SQL_COMMAND; 
my $HOST = "i"; 
my $USERNAME = "need"; 
my $PASSWORD = "help"; 
my $NOW_TIMESTAMP = strftime '%Y-%m-%d_%H-%M-%S', localtime; 

open my $out_fh, '>>', "$NOW_TIMESTAMP.sql" or die 'Unable to create sql file'; 

printf {$out_fh} "INSERT INTO BOL_LOCK.test(name) VALUES ('wow');"; 

sub insert() 
{ 
    my $SQL_COMMAND = "mysql -u $USERNAME -p'$PASSWORD' "; 

    while(my $sql_file = glob '*.sql') 
    { 
     my $status = system ("$SQL_COMMAND < $sql_file"); 
     if ($status == 0) 
     { 
      print "pass"; 
     } 
     else 
     { 
      print "fail"; 
     } 
    } 
} 

insert(); 

这工作,如果我作为用户登录时(我没有访问管理员)执行它。但是,当我设置一个cronjob运行此文件,让我们在上午10时08说,通过使用行(crontab -e):

08 10 * * * perl /opt/lampp/htdocs/otpms/Data_Tsunami/scripts/test.pl > /dev/null 2>&1 

我知道作为创建SQL文件正在执行的脚本。但是,上午10点08分之后没有新行插入到数据库中。我已经搜索了解决方案,有些人建议使用DBI模块,但它在服务器上不可用。

编辑:没有设法解决它到底。使用root/admin帐户来执行脚本,以便“解决”问题。第一

+2

你是否有理由避免['DBI'模块](http://metacpan.org/module/DBI)? – Borodin

+0

你可以把'printf'改成'print'吗? [docs](http://perldoc.perl.org/functions/printf.html)有一些有趣的说法,就是在文件句柄中使用'printf'并且没有列表。 –

+0

@MattJacob:只使用格式字符串而不使用'printf'没有问题。文档中关于省略的“列表”包含格式,如'printf FH',它等同于'printf FH $ _',但是具有像'printf $ fh'这样的词法文件句柄。Perl将解释为打印到当前 - 选择的输出句柄使用字符串化文件句柄'“$ fh”'作为格式字符串 – Borodin

回答

2

第一件事,摆脱了> /dev/null 2>&1在您crontab项的末尾(至少暂时),所以实际上你可以看到可能发生的任何错误。

换句话说,暂时将其更改为类似:

08 10 * * * perl /opt/lampp/htdocs/otpms/Data_Tsunami/scripts/test.pl >/tmp/myfile 2>&1 

然后你可以检查/tmp/myfile文件,看看有什么是输出。

可能情况是mysql实际上不是在你的cron工作的道路上,因为cron本身给出了一个相当最小的环境。

要解决这个问题(假设它就是这样),请参阅this answer,它提供了一些关于如何最好地扩展环境以提供所需内容的指导。这可能只涉及将MySQL可执行文件目录添加到您的变量PATH

您可能要考虑的另一件事是在尝试将它传递给mysql之前关闭out_fh文件 - 如果缓冲区没有被刷新,就其他进程而言,它仍可能是空文件。

+0

它说'sh:mysql:命令没有找到 失败'几次然后有'SQL文件大小为0'。后者是我添加的一个检查,用于检查文件大小是否为0.不知道为什么'找不到'命令。它在我手动执行文件时运行并插入,但不是在通过cronjob执行时插入。对不起,晚了(谁也在读书)。 – hzq

+0

@hzq,那么它确实是我的想法。 MySQL不在你的cronjob的路径上,因为'cron'给你一个相当小的环境。有关如何解决,请参阅http://stackoverflow.com/questions/1972690/cannot-get-php-cron-script-to-run/1972763#1972763,http://stackoverflow.com/questions/3295611/how-可以,我的故障排除,为什么,我的PHP脚本,不会工作在克朗,当它从/ TH/3295657#3295657或http://stackoverflow.com/questions/1068071/include-路径和-的cron/1068084#1068084。 – paxdiablo

0

表达式glob(“。* *”)匹配当前工作的 目录中的所有文件。 - http://perldoc.perl.org/functions/glob.html

你不应该依赖于cron作业中的wd。如果你想用相对路径使用glob(或任何文件操作),首先用chdir设置wd。 来源:http://www.perlmonks.org/bare/?node_id=395387

所以,如果你的工作目录,例如/home/user,你应该插入

chdir('/home/user/'); 

WHILE之前,即:

sub insert() 
{ 
    my $SQL_COMMAND = "mysql -u $USERNAME -p'$PASSWORD' "; 

    chdir('/home/user/'); 

    while(my $sql_file = glob '*.sql') 
    { 
... 

与地方的SQL文件替换/home/user被创建。

+0

更好:不要使用glob,并为所有文件和目录构建完整路径。 –

+0

这样做会更好,但我的尝试是直接回答这个人的问题,“为什么这不起作用?”而不是全部说教。 –

+0

是的,我只是想明白为什么。我按照你的建议尝试过,但我遇到了同样的问题。 – hzq

0

最好在Perl中尽可能多地进行处理。它避免了生成一个单独的shell进程的开销,并将所有内容留在程序的控制之下,以便您可以更简单地处理任何错误。

Perl的数据库访问使用DBI module完成。该程序演示如何实现您使用mysql实用程序编写的内容。正如你可以看到它也更加简洁

#!/usr/bin/perl 

use strict; 
use warnings; 

use DBI; 

my $host  = "i"; 
my $username = "need"; 
my $password = "help"; 

my $dbh = DBI->connect("DBI:mysql:database=test;host=$host", $username, $password); 

my $insert = $dbh->prepare('INSERT INTO BOL_LOCK.test(name) VALUES (?)'); 

my $rv = $insert->execute('wow'); 

print $rv ? "pass\n" : "fail\n"; 
+1

原来的帖子说DBI没有安装在服务器上。 –