Reputation: 2918
I just wrote a perl script that is restarting a list of services on a linux server. It's intended to run as a cron job. 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;
}
Upvotes: 0
Views: 371
Reputation: 6524
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. It also means you end up passing something like the following to sh
:
kill ARRAY(0x91b0768)
You want something like (if the arrayref is empty, there's nothing to loop over anyway):
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:
sub get_pids_by_process {
my $proc = shift;
$proc =~ s/^(.)/[$1]/;
Upvotes: 3
Reputation: 182762
Actually, I'd be more suspicious of what's in @ids in kill_rogue_procs. 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.
Upvotes: 3
Reputation: 11852
As sh
is raising the errors, I'm pretty sure one of the parameters to system
is being expanded to something unexpected. I'd print all parameters just prior to passing them to system for a quick debug.
Upvotes: 1