Can't load oracle.so - oracle

I am getting this exception:
Can't load '/usr/perl/lib/site_perl/5.8/x86_64-linux/auto/DBD/Oracle/Oracle.so' for module DBD::Oracle: libclntsh.so.8.0: cannot open shared object file:
No such file or directory at
/.../perl/lib/5.8/x86_64-linux/DynaLoader.pm line 169
If I do ls -ltr /.../perl/lib/site_perl/5.8/x86_64-linux/auto/DBD/Oracle/Oracle.so I see that the file is there. The process I am running also sets LD_LIBRARY_PATH before attempting to connect. A build and deploy on another machine doesn't produce the same error and runs fine. Running uname -sm gives Linux x86_64 on both machines. Is there something else that could cause this error?

Another solution:
Just pass your Oracle path variables before you run any scripts:
Like for perl you can do add below in beginning of your script:
BEGIN {
my $ORACLE_HOME = "/usr/lib/oracle/11.2/client64";
my $LD_LIBRARY_PATH = "$ORACLE_HOME/lib";
if ($ENV{ORACLE_HOME} ne $ORACLE_HOME
|| $ENV{LD_LIBRARY_PATH} ne $LD_LIBRARY_PATH
) {
$ENV{ORACLE_HOME} = "/usr/lib/oracle/11.2/client64";
$ENV{LD_LIBRARY_PATH} = "$ORACLE_HOME/lib";
exec { $^X } $^X, $0, #ARGV;
}
}

It looks like DBD::Oracle's Oracle.so is trying to open libclntsh.so.8.0 and can't find it. So you need to find out if that version of the shared library is installed.
Perform the following command:
$ locate libclntsh.so
You should get a list of files beginning with libclntsh.so. If you are lucky , libclntsh.so.8.0 will be among the results, and then you'll need to make sure that the directory that it lives in is on you load path. For instance my server has:
$ locate libclntsh.so
/home/oracle/11.2/lib/libclntsh.so
/home/oracle/11.2/lib/libclntsh.so.10.1
/home/oracle/11.2/lib/libclntsh.so.11.1
If locate fails completely, you can build the database using updatedb or you can try using find:
find / -name 'libclntsh.so*' -print
Use a pager or redirect stderr to a file because you might end up dealing with a lot of error messages from find, which is okay, but using less will allow you to just refresh the screen to see find's output.

Related

Perl code doesn't run in a bash script with scheduling of crontab

I want to schedule my Perl code to be run every day at a specific time. so I put the below code in bash file:
Automate.sh
#!/bin/sh
perl /tmp/Taps/perl.pl
The schedule has been specified in below path:
10 17 * * * sh /tmp/Taps/Automate.sh > /tmp/Taps/result.log
When the time arrived to 17:10 the .sh file hasn't been running. however, when I run ./Automate.sh (manually) it is running and I see the result. I don't know what is the problem.
Perl Code
#!/usr/bin/perl -w
use strict;
use warnings;
use Data::Dumper;
use XML::Dumper;
use TAP3::Tap3edit;
$Data::Dumper::Indent=1;
$Data::Dumper::Useqq=1;
my $dump = new XML::Dumper;
use File::Basename;
my $perl='';
my $xml='';
my $tap3 = TAP3::Tap3edit->new();
foreach my $file(glob '/tmp/Taps/X*')
{
$files= basename($file);
$tap3->decode($files) || die $tap3->error;
}
my $filename=$files.".xml\n";
$perl = $tap3->structure;
$dump->pl2xml($perl, $filename);
print "Done \n";
error:
No such file or directory for file X94 at /tmp/Taps/perl.pl line 22.
X94.xml
foreach my $file(glob 'Taps/X*') -- when you're running from cron, your current directory is /. You'll want to provide the full path to that Taps directory. Also specify the output directory for Out.xml
Cron uses a minimal environment and a short $PATH, which may not necessarily include the expected path to perl. Try specifying this path fully. Or source your shell settings before running the script.
There are a lot of things that can go wrong here. The most obvious and certain one is that if you use a glob to find the file in directory "Taps", then remove the directory from the file name by using basename, then Perl cannot find the file. Not quite sure what you are trying to achieve there. The file names from the glob will be for example Taps/Xfoo, a relative path to the working directory. If you try to access Xfoo from the working directory, that file will not be found (or the wrong file will be found).
This should also (probably) lead to a fatal error, which should be reported in your error log. (Assuming that the decode function returns a false value upon error, which is not certain.) If no errors are reported in your error log, that is a sign the program does not run at all. Or it could be that decode does not return false on missing file, and the file is considered to be empty.
I assume that when you test the program, you cd to /tmp and run it, or your "Taps" directory is in your home directory. So you are making assumptions about where your program looks for the files. You should be certain where it looks for files, probably by using only absolute paths.
Another simple error might be that crontab does not have permission to execute the file, or no read access to "Taps".
Edit:
Other complications in your code:
You include Data::Dumper, but never actually use that module.
$xml variable is not used.
$files variable not declared (this code would never run with use strict)
Your $files variable is outside your foreach loop, which means it will only run once. Since you use glob I assumed you were reading more than one file, in which case this solution will probably not do what you want. It is also possible that you are using a glob because the file name can change, e.g. X93, X94, etc. In that case you will read the last file name returned by the glob. But this looks like a weak link in your logic.
You add a newline \n to a file name, which is strange.

Determine write access in windows from activeperl

I have a script written using ActivePerl that creates files where the user specifies. If the directory doesn't already exist, it uses mkpath to attempt to create it and trap any error conditions (such as not having permission to create the directory there). This seems fine. What I'm running into trouble with is determine the permissions of a directory that already exists. I don't want a user to be able to specify a protected folder that they can read from (c:\windows\system32 comes to mind) and the script silently fail attempting to create its files there.
From other perl examples on the web I've tried using the following, but I'm always given 0777 as the result for any existing directory:
use File::stat;
#
#...
#
my $info = stat($candiDirectory);
my $retMode = $info->mode;
my $mymode = sprintf("0%o, $retMode & 07777);
print "retMode for $candiDirectory is $mymode \n";
While this seems reasonable for unix/Linux, I'd be surprised if it didn't require something different under Win32 or 64.
from perldoc perlfunc:
-w $filename
unless (-w $filename) {
say "i can't write this file";
}

Unexpected bash autocompletion behavior within a symbolic link loop

I have the following directory structure:
base/
dir/
subdir/
link -> ../dir
Now if I cd to dir/link and type:
cd ../subd[tab]
I get:
cd ../subdir[space]
I would understand if autocomplete fails (because it would canonize the path and look into base/ and not dir/).
I would also understand if it autocompletes to cd ../subdir/ with the ending / (because it would interpret .. as go up one level and search into dir/).
But I do not understand the actual behaviour that is somewhere between the two. Ideally I would like bash to behave like 2. (autocomplete to cd ../subdir/). I am using fedora 14, bash version 4.1.7(1). Any idea how to accomplish this ?
UPDATE: The program with which you can customize auto-completion is called complete.
You can find some good basic examples here: More on Using the Bash Complete Command
Using function and script names as per the above link, here is a script which appends the / to a symbolic link to a directory... It is just a rough sample, but it shows it can be done (I haven't tried it with the cd builtin...
Associate the function _mycomplete_ with executable myfoo
complete -F _mycomplete_ myfoo
The function to go in ~/.bashrc
function _mycomplete_()
{
local cmd="${1##*/}"
local word=${COMP_WORDS[COMP_CWORD]}
local line=${COMP_LINE}
local xpat='!*.foo'
COMPREPLY=($(compgen -f -X "$xpat" -- "${word}"))
if ((${#COMPREPLY[#]}==1)) ;then
[[ -h $COMPREPLY ]] && COMPREPLY="$COMPREPLY/"
fi
}
Original answer:
At the command-line, the main indicator of a auto-expansion to a symbolic link is shown on the last line of the following table, ie. a name expands but without the final /.
on pressing TAB on pressing TAB (again)
what happens? meaning what happens?
=================== ======================= ====================================
Nothing is appended 1=> Multiple sub-dirs exist => A list of possibilities is presented
2=> No sub-directory exists => Nothing is appended (again)
Expands to end in / => A uniquely matching dir => ...as per first column (repeat)
Expands text only => Current name is a link => Expands to end in /
In your example, if you have already primed the command-line to the full name, ie. cd link then the indicator is not obvious. Also you won't know it is a symbolic link via the list of possibilities.
To be able to cd to the link's target, you can use cd -P link, or set -P; cd link
After digging the source code a bit, it looks like this is a bit complicated. The actual problem is a mix between bash allowing symlinks inside the working directory (see pwd -L and pwd -P) and readline not able to determine the type of a match if it is not in a physical directory
In readline/complete.c:1694
s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
? LSTAT (filename, &finfo)
: stat (filename, &finfo);
stat() fails since ../ is understood as relative to the physical path and not the logical path. readline fails to determine this is a directory and therefore does not append the final '/'.
A very similar problem is described here
So I guess I can live with the existing behaviour for now...
I was having the exact same problem in Ubuntu. Autocompletion was working like in your example #2, but started working as you describe at some point. I purged and reinstalled the package bash-completion, and now everything seems back to normal. Do not uninstall bash! Only bash-autocompletion.
Edit
look at this:
https://bbs.archlinux.org/viewtopic.php?id=113158

How to use perl dbmopen on Windows and Linux

I have a perl script that runs fine on Linux but fails on Windows at this point:
$freq{total} = 0;
dbmopen(%freq,$dictfile,0666) || die "Error: Cannot open dbmfile $dictfile";
$dictfile points to the proper location on the respective platforms. Changing the 0666 file permissions does not help. The file to open is a text file encoded in gb18030.
Is there a trick? Do I need to declare the encoding to open it on Window? Or possibly a different perl distro on Windows. I'm using Strawberry Perl.
Thanks.
Edit: Sorry, if I'm stating the obvious, but I just re-read the question. When you say
The file to open is a text file encoded in gb18030.
Do you mean a plain text file?
If so I think thats your problem. dbmopen is for indexed database file, ideally created by dbmopen in a previous run of you perl program. For plain text files you cannot bind them to hashes.
My previous resonse...
It works for me on Windows with Strawberry perl 5.12.1 running on Windows7x64. Which windows perl are you using? Make sure your installation has at least one of the DBM modules with it.
Some other points which might help:
You should include $! in your die statement, it will give you the error message for the failed open. So hopefully answer your question.
dbmopen will clear the contents of the %freq hash, so you will lose $freq{total} (because its 0 you may not notice). Usual pattern is: dbmopen, change some hash values, dbmclose
Edits:
$! is the variable which contains the error test of any failed "system" call. So you open line should be something like:
dbmopen(%freq,$dictfile,0666) || die "Error: Cannot open dbmfile $dictfile: $!";
To check for the standard DBM modules you can run the following from the command prompt
for %m in ( DB_File GDBM_File SDBM_File NDBM_File ODBM_File ) do #perl -M%m -e "print qq(%m: $%m::VERSION\n)"
For me that gives:
DB_File: 1.82
GDBM_File: 1.10
SDBM_File: 1.06
Can't locate NDBM_File.pm in #INC (#INC contains: C:/Nerd/StrawberryPerl/perl/site/lib C:/Nerd/StrawberryPerl/perl/vendor/lib C:/Nerd/StrawberryPerl/perl/lib .)
.
BEGIN failed--compilation aborted.
Can't locate ODBM_File.pm in #INC (#INC contains: C:/Nerd/StrawberryPerl/perl/site/lib C:/Nerd/StrawberryPerl/perl/vendor/lib C:/Nerd/StrawberryPerl/perl/lib .)
.
BEGIN failed--compilation aborted.
Which effectively meands I have DB_File, GDBM_File, and SDBM_File. But not NDBM_File or ODBM_File. Sorry I don't know how to find out which module dbmopen uses by default.
Personally I always use a specific module and then use the tie operator instead of dbmopen.

llv8call on Mac OS X - 2nd try

I didn't give a lot of info in my last question.
I've built llv8call from http://code.google.com/p/llv8call/, v0.4. I've gotten the known dependencies installed, being libxml-2.0 and libreadline. My dev system is Mac OS X 10.5. llv8call is built with Scons.
When I attempt to run llv8call via ./llv8call, I get this error:
library loading error: org.coderepos.env is not found in : (loadBinary)
I am not sure how to troubleshoot this error. The author hasn't responded to me yet. I need some tips on how to troubleshoot this more than an explicit answer, though if someone has one it's very welcome.
The files are installed to /usr/local/llv8call. There is a directory structure under llv8call/lib/llv8call/org/coderepos but it doesn't contain an "env" directory. My first guess is that whatever library its looking for at org.coderepos.env is supposed to be in this path, but "env" doesn't exist. If this sounds reasonable, it might be a place that I should start looking at but I need confirmation.
Your intuition seems right. Doing a grep:
grep -r "org.coderepos" *|less
I see it checks for many "libraries" under org.coderepos. Furthermore, in src/main.cc in the preload_builtin_classes function, we see:
Handle<Value> args[1];
args[0] = String::New("org.coderepos.fs");
loadBinary->Call(v8ext, 1, args);
args[0] = String::New("org.coderepos.env");
loadBinary->Call(v8ext, 1, args);
if (try_catch.HasCaught()) {
String::Utf8Value error(try_catch.Exception());
fprintf(stderr, "library loading error: %s\n", *error);
exit(2);
}
That, my friend, is your smoking gun.
It is looking for a library called env (i.e., libenv.so) in the directory /org/coderepos.
Either make /org/coderepos and copy the libraries into it, or ask your dynamic linker to look for /org/coderepos content elsewhere.
I fixed this by doing the following from the top-level directory of my llv8call source directory (after running scons to build everything):
mkdir -p out/lib/llv8call/org/coderepos
find ext -name \*.dylib -exec cp {} out/lib/llv8call/org/coderepos \;
"dtruss -f test.sh" was helpful in finding where v8 was looking for the libs.

Resources