perlmoon has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
In shell(ksh) it runs fine works create tickets

#!/usr/bin/ksh export CLASSPATH="/usr/work/ticket/ETicketClient.jar:." PATH=$PATH:"/usr/work/ticket/" test="This is new title" result=`java ETicket.ETicketClient -i Ticket -n p_name -t "$test"` echo $result;

But in Perl its fails

#!/usr/bin/perl -w $ENV{CLASSPATH}="/usr/work/ticket/ETicketClient.jar:."; $ENV{PATH}.=":/usr/work/ticket/" $test="This is perl ticket"; my $result =qx/java ETicket.ETicketClient -i TICKET -n p_name -t "$test"/; print $result;

Gives me Error

Exception in thread "main" java.lang.NoClassDefFoundError: ETicket/ETicketClient Quotes are required for API to recognize options.

I have put \ before quotes but no luck. Tried using safe pipes but same problem. Also when i use this line in script my $result =qx/java ETicket.ETicketClient -i TICKET -n p_name -t title_name/; Then it runs fine. But is i put this line my $result =qx/java ETicket.ETicketClient -i TICKET -n p_name -t "title name"/; Same error is coming.
OS AIX 5.1 Perl 5.6.0 .

Can anyone help me.
Thanks
Sanjay

20051018 Janitored by Corion: Added formatting

Replies are listed 'Best First'.
Re: Problem using Backtick having quotes
by Nkuvu (Priest) on Oct 18, 2005 at 20:08 UTC
    Anyone else notice that the case is different between Ticket in the shell sample, and TICKET in the Perl script? Does that matter? I have no idea -- off hand I don't know what the -i does for the Java compiler. Just an observation.

    Update: I didn't have time to look earlier, but just took a minute and found the docs for command line options on Windows, Solaris, and Linux. None of which indicated an option of -i. So if someone could tell me what that switch is supposed to do, I'd appreciate it (if only to satisfy my curiosity).

Re: Problem using Backtick having quotes
by fizbin (Chaplain) on Oct 19, 2005 at 13:14 UTC

    The only thing I can think is that when you have quote marks the string as a whole contains "shell metacharacters", and when you don't, it doesn't.

    For example, see this bit from the documentation for perl's system command:

    If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is "/bin/sh -c" on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to "execvp", which is more efficient.
    So, for some reason, invoking "/bin/sh -c" is clearing the environment before running the command. I find this a bit odd, but you can check it with this simple perl script:
    #!perl $ENV{CLASSPATH}="/usr/work/ticket/ETicketClient.jar:."; print "Without shell metachars we get:\n", grep(/CLASSPATH/, qx[/usr/bin/env]), "\n"; print "With shell metachars we get:\n", grep(/CLASSPATH/, qx[/bin/false || /usr/bin/env]), "\n";

    See if there's a difference in the two outputs.

    So then, the question is, why is this clearing the environment? It's not supposed to, but I wonder if on your system /bin/sh is aliased to csh. (or if perhaps the qx[] operator uses your default shell, which might be csh) Csh has a habit of always running its initialization scripts even if it's just being called for one command, and that could reset your environment variable settings.

    Fortunately, for java there is a simple solution - you can change your original code to:

    #!/usr/bin/perl -w my $cp = "/usr/work/ticket/ETicketClient.jar:."; $ENV{PATH}.=":/usr/work/ticket/" $test="This is perl ticket"; my $result =qx/java -cp \Q$cp\E ETicket.ETicketClient -i TICKET -n p_ +name -t "\Q$test\E"/; print $result;
    That is, use the -cp argument to set the classpath for java even when the environment is being reset.
    --
    @/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/; map{y/X_/\n /;print}map{pop@$_}@/for@/
Re: Problem using Backtick having quotes
by davidrw (Prior) on Oct 18, 2005 at 18:33 UTC
    Because the %ENV hash is not propagated to the shell that the perl backticks spawns off.. Can you just have perl call the ksh script instead?

    Update: doh. i confused myself with a bad test: perl -le '$ENV{foo}="asd"; print `echo b $foo a`' (needs to be \$foo)

    Maybe it's due to the behavior of the qx// operator? What about doing this instead?
    my $cmd = sprintf 'java ETicket.ETicketClient -i Ticket -n p_name -t +"%s"', $test; my $result = `$cmd`; print $result;
      Because the %ENV hash is not propagated to the shell..
      This works fine for me:
      #!/usr/bin/perl $ENV{foobar} = "baz"; my $res = `echo \$foobar`; print $res; #prints 'baz'
Re: Problem using Backtick having quotes
by graff (Chancellor) on Oct 19, 2005 at 03:34 UTC
    This is just a work-around (and somewhat of a kluge, at that), but hey, if it works, it gets the job done, and that's what we want, right? (That's what Perl is for!)

    Given that the shell script works, use perl to write a working, executable shell script, then execute the shell script in backticks.

Re: Problem using Backtick having quotes
by perlmoon (Initiate) on Oct 18, 2005 at 19:20 UTC
    Hi, Tried $cmd = sprintf 'java ETicket.ETicketClient -i TICKET -n p_name "%s"', $test; my $result =`$cmd`; print $result; But Same Error. Exception in thread "main" java.lang.NoClassDefFoundError: ETicket/ETicketClient