Llamar al sistema () o los comandos IPC :: Run3 de Perl no parecen pasar la variable de entorno ($ env {java_home})

StackOverflow https://stackoverflow.com/questions/9319745

  •  26-10-2019
  •  | 
  •  

Pregunta

He estado luchando por lanzar un proceso de Java desde Perl. La raíz del problema es que el proceso Java le falta el JAVA_HOME Variable de entorno que causa un ClassNotFoundException.

Empecé usando IPC::Run3 Debido a su redirección relativamente elegante de Stdin/Stdout.

Asumiendo IPC::Run3 usaría %ENV, Intenté agregar $ENV{JAVA_HOME}.

Cuando eso no funcionó, intenté hacer system(). Eso no funcionó, así que finalmente, lo hice para trabajar usando system("JAVA_HOME=/path/to/java && /path/to/java_program");

Mi programa de prueba está a continuación. Naturalmente, desencadenaría el bloque adecuado para probar la invocación apropiada.

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

Aquí está la salida de ejecutar la ejecución3:

    -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.

Y la salida del primer sistema () llamar:

    -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.

Finalmente, la tercera llamada del sistema, ¡la única que funcionó!, Con la variable de entorno establecida en línea:

    -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

Finalmente, a la pregunta: además de tener que establecer el entorno en línea con la llamada System (), ¿cuál es la forma apropiada de pasar un entorno VAR a una llamada IPC :: Run3 o una llamada System ()?

(Nota: la salida de %env se trunca solo a líneas relevantes ... líneas como ruta, shell, _, etc. No es relevante para la pregunta omitida)

En caso de que sea relevante:

-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
¿Fue útil?

Solución

La raíz del problema es que al proceso Java le falta la variable de entorno Java_Home que causa una ClassNotFoundException.

REVISADO

Esa no es la raíz del problema. En realidad, Java misma no requiere que se establezca Java_Home.

La causa inmediata del problema es una de las siguientes cosas:

  • El envoltorio no está configurando el clase correctamente para la aplicación que está intentando ejecutar.

  • El envoltorio usando el nombre de clase incorrecto. El nombre de clase "Nutch" es inusual y sospechoso: no hay nombre de paquete.

Parece probable que la causa raíz real sea que esté ensamblando la lista de argumentos de manera incorrecta. Cada uno de esos argumentos con un espacio dentro de ellos realmente debería ser dos argumentos; es decir

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

Sospecho que esto ha confundido el script de envoltura de nueces y ha hecho que usara el nombre de clase incorrecto (entre otras cosas). Cuando pasa todo el comando como una cadena y deja que el caparazón lo analice, el problema (naturalmente) desaparece.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top