2012-01-04 61 views
0

我剛剛寫了一個perl腳本,它正在重新啓動linux服務器上的服務列表。它的目的是作爲一個cron工作來運行。當我執行腳本時,我不斷收到這個錯誤;Perl系統調用拋出奇怪的錯誤

[email protected]:~/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; 
} 
+0

如果你嘗試'的perl -e「系統(「在/ etc /初始化會發生什麼。 d/apache2停止「);''? – 2012-01-04 15:34:54

+0

正常工作。我將粘貼代碼。 – Skittles 2012-01-04 15:39:28

+0

你知道那個時候$ state是什麼嗎? – 2012-01-04 15:47:35

回答

3

其實,我會更加懷疑kill_rogue_procs中@ids的內容。這是ps後面跟着一個grep的結果,所以如果ps不返回任何結果或者如果pid不是5位數,那麼可能會有僞造的值。

+0

太棒了!謝謝,保羅! :) – Skittles 2012-01-04 16:00:46

1

由於sh是提高了錯誤,我敢肯定的參數之一system正在擴大,以意想不到的事情。在將它們傳遞給系統進行快速調試之前,我會打印所有參數。

+0

我嘗試改變系統調用來將kill命令調用爲/ bin/kill,但仍然無法停止它。我注意到,如果它試圖殺死一個不存在的pid,你會得到這條sh消息:「bash:kill:(31014) - 沒有這樣的進程」。那可能是從哪裏開始可能呢? – Skittles 2012-01-04 16:12:28

+0

@Skittles,「改變系統調用」並不是給出的建議。給出的建議非常好,你應該遵循它。 – ikegami 2012-01-05 02:14:17

3

這是錯誤的:

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將始終包含一個數組引用,所以(標量@ids)將永遠是正確的。這也意味着你最終通過類似以下內容sh

kill ARRAY(0x91b0768) 

你想要的東西,像(如果該數組引用是空的,沒有什麼可以遍歷反正):

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

或代替循環:

kill SIGTERM => @$ids; 

此外,也無需調用系統kill的過程。

要這個,我要補充的最後一行,這樣你就不會用grep grep的過程本身:

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

這是所有優秀的建議。我還沒有嘗試過,但是肯定會添加它們。我喜歡perl的一件事是,如果你在語言中獲得的經驗越豐富,獲得相同結果所需做的就越少。我不是perl的導師,但我相信你可以從我的腳本中衡量我的專業水平。非常感謝分享這個,runrig。 – Skittles 2012-01-04 17:03:44

+0

@runrig,你離這個答案只有一步之遙,所以我添加了它。 – ikegami 2012-01-05 02:10:54