Системный вызов Perl выдает странную ошибку - PullRequest
0 голосов
/ 04 января 2012

Я только что написал Perl-скрипт, который перезапускает список сервисов на сервере Linux. Он предназначен для работы в качестве cron. когда я выполняю скрипт, я получаю эту ошибку;

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

Для этого используется вызов:

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

Я могу вставить весь код скрипта, если это необходимо, но я решил, что это источник проблемы, и мне просто нужно знать, как ее остановить.

Есть идеи?

Вот весь сценарий;

#!/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;
}

Ответы [ 3 ]

3 голосов
/ 04 января 2012

На самом деле, я бы более подозрительно относился к тому, что находится в @ids в kill_rogue_procs.Это результат ps, за которым следует grep, поэтому могут иметь поддельные значения, если ps не возвращает никаких результатов или если pid не имеет 5 цифр.

3 голосов
/ 04 января 2012

Это неправильно:

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) {

Из того, что вы передаете этому сабвуферу, @ids всегда будет содержать ссылку на один массив, поэтому (scalar @ids) всегда будет истинным. Это также означает, что вы в конечном итоге передаете что-то вроде следующего в sh:

kill ARRAY(0x91b0768)

Вы хотите что-то вроде (если arrayref пуст, в любом случае нет ничего зацикливаться):

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

Или вместо цикла:

kill SIGTERM => @$ids;

Кроме того, нет необходимости вызывать систему для уничтожения процесса.

К этому я бы добавил последнюю строку, чтобы вы не включали сам процесс grep:

sub get_pids_by_process {
  my $proc = shift;
  $proc =~ s/^(.)/[$1]/;  
1 голос
/ 04 января 2012

Поскольку sh вызывает ошибки, я почти уверен, что один из параметров до system расширяется до чего-то неожиданного. Я бы напечатал все параметры непосредственно перед передачей их в систему для быстрой отладки.

...