简体   繁体   English

Perl系统调用引发奇怪的错误

[英]Perl system call throws strange error

I just wrote a perl script that is restarting a list of services on a linux server. 我刚刚编写了一个Perl脚本,该脚本重新启动了Linux服务器上的服务列表。 It's intended to run as a cron job. 它旨在作为cron工作运行。 when I execute the script though, I keep getting this error; 但是,当我执行脚本时,会不断出现此错误;

root@www:~/scripts# ./ws_restart.pl
  * Stopping web server apache2                                   [ OK ]
sh: Syntax error: "(" unexpected
  * Stopping MySQL database server mysqld                         [ OK ]
sh: Syntax error: "(" unexpected

The call that is being used to do this is; 用于执行此操作的呼叫是:

system("/etc/init.d/apache2 stop");
system("/etc/init.d/mysql stop");

I can paste the entire script code if needed, but I figured that this is the source of the problem and just need to know how to stop it. 如果需要,我可以粘贴整个脚本代码,但是我认为这是问题的根源,只需要知道如何停止它即可。

Any ideas? 有任何想法吗?

Here's the entire script; 这是整个脚本;

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

my $old_pids = {};
my $post_stop_ids = {};
my @services = qw/apache2 mysql solr/;
my $app_dir  = '/home/grip/apps/eventfinder';


# collect existing pids then kill services
foreach my $service (@services) {
  # gather up existing pids
  $old_pids->{$service} = [ get_pids_by_process($service) ];

  # issue stop command to each service
  set_service_state($service, 'stop');

  # attempt to regather same ids
  $post_stop_ids->{$service} = [ get_pids_by_process($service) ];

  # kill any rogue ids left over
  kill_rogue_procs($post_stop_ids->{$service});

  # give each kill time to finish
  sleep(5);
}


# attempt to restart killed services
foreach my $service (@services) {
  # issue start command to each service
  set_service_state($service, 'start');

  # Let's give each service enough time to crawl outta bed.
  # I know how much I hate waking up
  sleep(5);
}

# wait for it!...wait for it! :P
# Pad an extra 5 seconds to give solr enough time to come up before we reindex
sleep(5);

# start the reindexing process of solr
system("cd $app_dir ; RAILS_ENV=production rake reindex_active");

# call it a day...phew!
exit 0;

sub kill_rogue_procs {
  my @ids = shift;
  # check if we still have any rogue processes that failed to die
  # if so, kill them now.
  if(scalar @ids) {
    foreach my $pid (@ids) {
      system("kill $pid");
    }
  }
}


sub set_service_state {
  my ($proc, $state) = @_;

  if($proc eq 'apache2') {
    system("/etc/init.d/apache2 $state");
  } elsif($proc eq 'mysql') {
    system("/etc/init.d/mysql $state");
  } elsif($proc eq 'solr') {
    system("cd $app_dir ; RAILS_ENV=production rake sunspot:solr:$state");
  }
}


sub get_pids_by_process {
  my $proc = shift;

  my @proc_ids = ();

  open(PSAE, "/bin/ps -ae | grep $proc |") || die("Couldn't run command");

  while(<PSAE>) {
    push @proc_ids, $_ =~ /(\d{1,5})/;
  }

  close PSAE;

  return @proc_ids;
}

Actually, I'd be more suspicious of what's in @ids in kill_rogue_procs. 实际上,我会对kill_rogue_procs中@ids中的内容更加怀疑。 It's the result of a ps followed by a grep, so might have bogus values if ps doesn't return any results or if the pid isn't 5 digits long. 这是ps后跟grep的结果,因此,如果ps不返回任何结果或pid的长度不是5位数字,则可能会有假值。

This is wrong: 这是错误的:

sub kill_rogue_procs {
  my @ids = shift;
  # check if we still have any rogue processes that failed to die
  # if so, kill them now.
  if(scalar @ids) {

From what you're passing to this sub, @ids will always contain a single array reference, so (scalar @ids) will always be true. 从您传递给此子项的内容来看,@ ids将始终包含单个数组引用,因此(标量@ids)将始终为true。 It also means you end up passing something like the following to sh : 这也意味着您最终将类似以下内容的内容传递给sh

kill ARRAY(0x91b0768)

You want something like (if the arrayref is empty, there's nothing to loop over anyway): 您想要类似的东西(如果arrayref为空,则没有任何循环可循环):

my $ids = shift;
...
for my $pid (@$ids) {
  kill SIGTERM => $pid;

Or instead of the loop: 或代替循环:

kill SIGTERM => @$ids;

Also, there is no need to call system to kill a process. 同样,也无需调用系统来杀死进程。

To this, I'd add the last line, so you don't grep the grep process itself: 为此,我要添加最后一行,因此您不必grep grep进程本身:

sub get_pids_by_process {
  my $proc = shift;
  $proc =~ s/^(.)/[$1]/;  

As sh is raising the errors, I'm pretty sure one of the parameters to system is being expanded to something unexpected. 随着sh引发错误,我很确定system的参数之一正在扩展到意外的地方。 I'd print all parameters just prior to passing them to system for a quick debug. 我会在将所有参数传递给系统之前进行快速调试,以打印所有参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM