【问题标题】:Cronjob does not execute command line in perl scriptCronjob 在 perl 脚本中不执行命令行
【发布时间】:2015-11-12 03:59:34
【问题描述】:

我对linux/linux环境不熟悉,如有错误请见谅,评论澄清。

我创建了一个简单的 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 点 8 分使用以下行(在 crontab -e):

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

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

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

【问题讨论】:

  • 你有理由避开DBI module吗?
  • 你能把你的printf改成print吗? docs 对使用带有文件句柄和不带列表的 printf 有一些有趣的说法。
  • @MattJacob:使用printf 没有任何问题,只有一个格式字符串,没有参数。文档中谈到省略的“列表”包括格式,如printf FH,它等同于printf FH $_,但具有像printf $fh 这样的词法文件句柄,Perl 解释为打印到当前选择的输出句柄,使用字符串化文件句柄 "$fh" 作为格式字符串

标签: sql linux perl crontab


【解决方案1】:

首先,删除crontab 条目末尾的&gt; /dev/null 2&gt;&amp;1(至少是暂时的),这样您就可以真正查看任何可能发生的错误。

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

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

然后您可以检查/tmp/myfile 文件以查看正在输出的内容。

可能的情况是mysql 实际上不在您的cron 作业的路径上,因为cron 本身提供了一个相当小的环境。

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

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

【讨论】:

【解决方案2】:

表达式 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' )
    {
...

/home/user 替换为创建 sql 文件的位置。

【讨论】:

  • 更好的是:不要使用glob 并为所有文件和目录构建完整路径。
  • 那会更好,但我的尝试是最直接地回答这个人的问题"why doesn't this work?",而不是全部说教。
  • 是的,我只是想了解原因。我已经按照你的建议尝试了,但我遇到了同样的问题。
【解决方案3】:

最好在 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";

【讨论】:

  • 原帖说服务器上没有安装DBI。
猜你喜欢
  • 2012-03-29
  • 2012-10-20
  • 1970-01-01
  • 2021-11-17
  • 2021-12-14
  • 2013-06-17
  • 2012-07-21
  • 2015-10-30
  • 2021-01-22
相关资源
最近更新 更多