2012-02-16 70 views
0

我一直在利用Perl啓動Java進程中掙扎。該問題的根源在於,java程序缺少JAVA_HOME環境變量引起ClassNotFoundException

我開始用IPC::Run3,因爲它的標準輸入/輸出的相對優雅的重定向。

假設IPC::Run3會使用%ENV,我試着加入$ENV{JAVA_HOME}

如果沒有工作,我想這樣做system()。沒有工作,所以最後,我把它用system("JAVA_HOME=/path/to/java && /path/to/java_program");

我的測試程序是下面工作。當然,我會取消註釋適當的塊來測試適當的調用。

#!/usr/bin/perl -w 
use strict; 

use IPC::Run3; 

use vars qw(%Config $nutch_stdout $nutch_stderr); 

%Config = (
    'nutch_binary'  => q[/home/crawl/nutch/runtime/local/bin/nutch], 
    'nutch_crawl_dir' => q[/home/crawl/nutch-crawl/crawl/crawldb/current/part-00000], 
    'nutch_seed_dir'  => q[/home/crawl/urls], 
    'solr_url'   => q[http://localhost:8080/solr], 
); 

my @nutch_command = ("$Config{nutch_binary}", 
       "crawl $Config{nutch_seed_dir}", 
       "-solr $Config{solr_url}", 
       "-d $Config{nutch_crawl_dir}", 
       "-threads 1", 
       "-depth 1"); 

$ENV{JAVA_HOME}  = '/usr/lib/jvm/java-1.6.0'; 

while ((my $key,my $value) = each %ENV) { 
    print "$key=$value\n"; 
} 

print "Running @nutch_command\n"; 

# My original code. Next few lines are shown in first batch of output below. 
#run3 \@nutch_command, undef, \$nutch_stdout, \$nutch_stderr; 
#print "Output from Nutch:\n"; 
#print $nutch_stdout; 
#print "Errors from Nutch:\n"; 
#print $nutch_stderr; 

# Second try. The next line's output is the second batch of output. 
#system(@nutch_command); 

# Third try. Despite setting and displaying %ENV, this is the only thing I tried that worked 
system("JAVA_HOME=/usr/lib/jvm/java-1.6.0 && @nutch_command"); 

這裏的運行RUN3的輸出:

-bash-3.2$ ./test.pl 
    ... [snip] ... 
    JAVA_HOME=/usr/lib/jvm/java-1.6.0 
    ... [snip] ... 
    Running /home/crawl/nutch/runtime/local/bin/nutch crawl /home/crawl/urls -solr http://localhost:8080/solr -d /home/crawl/nutch-crawl/crawl/crawldb/current/part-00000 -threads 1 -depth 1 
    Output from Nutch: 
    Errors from Nutch: 
    Exception in thread "main" java.lang.NoClassDefFoundError: crawl 
    Caused by: java.lang.ClassNotFoundException: crawl 
at java.net.URLClassLoader$1.run(URLClassLoader.java:217) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.net.URLClassLoader.findClass(URLClassLoader.java:205) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:321) 
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:266) 
    Could not find the main class: crawl. Program will exit. 

而且第一個系統的輸出()調用:

-bash-3.2$ ./test.pl 
    ... [snip] ... 
    JAVA_HOME=/usr/lib/jvm/java-1.6.0 
    ... [snip] ... 
    Running /home/crawl/nutch/runtime/local/bin/nutch crawl /home/crawl/urls -solr http://localhost:8080/solr -d /home/crawl/nutch-crawl/crawl/crawldb/current/part-00000 -threads 1 -depth 1 
    Exception in thread "main" java.lang.NoClassDefFoundError: crawl 
    Caused by: java.lang.ClassNotFoundException: crawl 
at java.net.URLClassLoader$1.run(URLClassLoader.java:217) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.net.URLClassLoader.findClass(URLClassLoader.java:205) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:321) 
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:266) 
    Could not find the main class: crawl. Program will exit. 

最後,第三個系統call--唯一一個工作 - 與環境變量設置在線:

-bash-3.2$ ./test.pl 
    ... [snip] ... 
    JAVA_HOME=/usr/lib/jvm/java-1.6.0 
    ... [snip] ... 
    Running /home/crawl/nutch/runtime/local/bin/nutch crawl /home/crawl/urls -solr http://localhost:8080/solr -d /home/crawl/nutch-crawl/crawl/crawldb/current/part-00000 -threads 1 -depth 1 
    crawl started in: crawl-20120216133832 
    ... continue success stdout output 

最後一個問題:除了有設置在線環境與系統()調用,什麼對環境無功傳遞給IPC :: RUN3或系統的正確方法()調用?

(注:%ENV的輸出被截斷,只相關的行......行像PATH,SHELL,_等不相關的省略問題)

在情況下,它是相關的:

-bash-3.2$ uname -a 
Linux hostname 2.6.18-238.el5xen #1 SMP Thu Jan 13 16:41:45 EST 2011 x86_64 x86_64 x86_64 GNU/Linux 
-bash-3.2$ perl --version 
This is perl, v5.8.8 built for x86_64-linux-thread-multi 
+0

只需設置%ENV即可。你得到什麼:'perl -e'die if $ ENV {FOO_BAR}; $ ENV {FOO_BAR} =「/usr/lib/jvm/java-1.6.0」;系統(q {echo - $ FOO_BAR - });''。 (「this is perl,v5.8.9 built for i686-linux-thread-multi」。將安裝5.8.8) – ikegami 2012-02-16 22:11:51

+0

順便說一句,'system(「JAVA_HOME =/path/to/java &&/path/to/java_program 「);'可以簡化爲'system(」JAVA_HOME =/path/to/java/path/to/java_program「);' – ikegami 2012-02-16 22:22:14

+0

我的簡化版本也適用於爲i686-linux-thread-multi構建的v5.8.8。 – ikegami 2012-02-16 22:33:50

回答

0

The root of the problem is that the java process is missing the JAVA_HOME environment variable causing a ClassNotFoundException.

REVISED

這不是問題的根源。實際上,Java本身不需要設置JAVA_HOME。

問題的直接原因是下列之一:

  • 封裝器沒有設置類路徑正確地爲您嘗試執行應用程序。

  • 使用了錯誤的類名的包裝。類名「nutch」是不尋常的和可疑的 - 沒有包名。

看起來真正的根本原因可能是您正在錯誤地組裝參數列表。其中每一個帶有空格的參數都應該是兩個參數;即

 my @nutch_command = ("$Config{nutch_binary}", 
      "crawl", "$Config{nutch_seed_dir}", 
      "-solr", "$Config{solr_url}", 
      "-d", "$Config{nutch_crawl_dir}", 
      "-threads", "1", 
      "-depth", "1"); 

我懷疑這混淆了Nutch的包裝腳本,並造成其使用了錯誤的類名(除其他事項外)。當你將整個命令作爲一個字符串傳遞並讓shell解析它時,問題(自然而然)就會消失。

+0

謝謝Stephen,但是我所說的內容是真實的,定義JAVA_HOME使nutch能夠正常運行。 我讀過那篇文檔,並且對它很熟悉。我在Perl中做的不只是編寫一個包裝腳本,儘管我的測試代碼看起來就是我所做的一切,因爲我想提煉出這個問題 - 爲什麼perl似乎沒有注意到%ENV散列 - 直至其本質。 我在nutch爬行之前做了很多準備工作,並且在我選擇使用perl進行爬網之後還有更多工作要做。 但是,我會考慮使用-cp。 – user1214836 2012-02-16 23:59:44

+0

它的確如此,因爲nutch只是一個shell腳本,並且包含如下的bash代碼:''if [「$ JAVA_HOME」=「」];然後 回顯「錯誤:未設置JAVA_HOME」。 1號出口 fi'' – user1214836 2012-02-17 00:19:48

+0

你釘了它......謝謝! – user1214836 2012-02-17 18:53:55