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

Oh purveyors of Perl wisdom, please can you help.

I'm trying to call sql*loader (sqlldr) from a Perl script. The script appears to run okay (no errors are generated) but the loader doesn't do anything. There's no data in the target database table and no log file is generated from loader. I'm sure the script is going through the code (debug messages are generated) but it just doesn't do anything.

The script is running under Linux and is loading to a Oracle 10g database. Here is line from the script:

my $rt = `sqlldr userid=$u/$p\@$sid control=$fileParms[0] log=$fileParms[0] 2>&1`;

where $u is the user id, $p is the password, $sid is the database instance and $fileparms[0] contains the name for the sqlldr control and log files (no .ctl or .log is included). If i run the equivalent from the command line it works fine.

As usual, any help given will be greatly appreciated.

Martino

Replies are listed 'Best First'.
Re: Help with sql*loader
by moritz (Cardinal) on May 15, 2008 at 08:20 UTC
    The first step should be to print the exact command line from your script, so that you can be sure that all variables have the values you expect:
    print "sqlldr userid=$u/$p\@$sid control=$fileParms[0] log=$fileParms[ +0] 2>&1\n";

    If you can execute that by copy & paste to your shell, you should investigate further. What's in $rt after the run? Are the perl script and your shell in the exact same environment? Are the environment variables the same? Does sqlldr try to access the terminal? (fancy prompts or formatting characters).

      Thanks for the reply, Moritz. I dumped out the sqlldr command and ran it succesfully from the command line. $rt is false (0) after the run (i check for true and write to a log if it is and nothing is written to the log).

      I asked for help from one of our dba's and he thought it might be environment variables so he provided me with a command to run to set these up - no difference.

      Forgive my ignorance but i don't know what you mean when you ask if it tries to access the terminal.

      Thanks, Martino

        $rt is false (0) after the run

        Is it false because there was not output (empty string) or is it undefined because the command failed to execute at all?  In the latter case, you could print out the system error message to see if it might provide some hint as to what's going wrong (that would typically be "No such file or directory", for example, if the command isn't found along the configured search path):

        my $rt = `...your command...`; print "error: $!\n" unless defined $rt;

        Are you running your Perl script from exactly the same command line / environment that you can successfully execute it in without the backticks wrapper?

        In cases like these, it's usually best to start with whatever works, and then modify things in small steps until it no longer works. For example, you could try to run the command within backticks from the shell, or run it with system from Perl... both with and without the 2>&1 redirection, etc. — and all from the same command line, to begin with.

        If all else fails, you could trace the system calls being made to get a clearer picture of what's going on, e.g.

        $ strace -f ./686679.pl or, to redirect the output to a file: $ strace -f -o strace.out ./686679.pl or, to trace only specific system calls, like execve, $ strace -f -e execve ./686679.pl or the set of 'file' system calls, etc. $ strace -f -e file ./686679.pl

        (If you're having difficulties interpreting strace's output, post the last 20-30 lines here...)

        This looks suspiciously like a problem with environment variables to me as well. It's been a while since I've used Oracle, so forgive me if I'm a little fuzzy on details. But I'd suggest you check not only ORACLE_HOME, but (where appropriate)
        • LD_LIBRARY_PATH,
        • TNS_ADMIN, which points to TNSNAMES.ORA (this one consistently gave me grief for some reason), and
        • TWO_TASK
        Take a look at this page for summary information on other Oracle environment variables.

        I'd also suggest double checking %ENV from within your code to be 100% sure you are setting the environment variables correctly and double checking that TNSNAMES.ORA, library files, and the other files the environment variables are targeting are where you expect them to be based on the environment variables.

        Hope this helps :-)

        Forgive my ignorance but i don't know what you mean when you ask if it tries to access the terminal.

        If a program prompts for a password, it usually turns off the echo, so that the typed password isn't visible on screen. To do that, that program has to have some control over the terminal (for example xterm) that it runs it.

        That's why it is so hard to remote-control programs like passwd and gpg.

        But somehow I don't think that this is your problem, it's just something I encountered before in similar situations.