moving a perl script/dbm to a new server, and shifting out of dbm?

1.1k views Asked by At

I've been tasked with mirroring a site onto a new server. The old site has a few Perl scripts that, as far as I can see internally (i know nothing about Perl, though I have a pretty good understanding of coding generally, and specifically PHP/js/etc) aren't reliant on the old server. That said, when I try to run this script, which looks through a database file to find the appropriate article file, it doesnt retrieve anything.

Basically, this is a rudimentary old CMS, as I explain it, where it searched the PAG file for the filename and displayed it. I am a little bit lost here. Is there a reason why the mirroring doesn't work on the new site? I've checked the permissions, I've checked that Perl is installed in the same /usr/etc directories. I think it uses dbm because, according to another article, if I see commands like these:

 dbmopen( %ARTS, $art_dbm, 0644 );
 $entry = $ARTS{$article_id};
 dbmclose( %ARTS );

it must be dbm, right?

On a related note, is there any way to merge that PAG file's info with the original files without an incredibly sophisticated Perl script; i.e., recreate the 100 text files with that info in the file itself, rather than stored separately?

EDIT: thanks for the 1st answer below. can you explain what that HASH may be, and the mask? I've doublechecked that the .pag file (the database name) is indeed in the place where its defined earlier in the .pl file, and that it was transferred in binary. yet somehow I cant get it to open it correctly!

EDIT 3: Ok, sorry, final editing here: I used the die code below (Shwern) and found that it is not finding that DB file, despite it being there (two files articles.pag and articles.dir, but the variable only references "articles" without extensions) in the right directory and with the right permissions... So, the question here is now what the hell is going on? are these different versions of perl? or am i just doing something basic and stupid? for the record (yes, its terrible) i dont have shell access just yet, though i'm working on it... I was asked to do this because of my "new web" skills, and I'm certainly not the appropriate person for things like perl and dbm, though i can read the files and understand them. As a final suggestion, does anyone know how (a script or the like) I could ask the original server people (who are NOT the coders) to do an ASCII dump of this, or would that be out of line? I need to get this into CSV and back into the file so I can reuse it in another db... ugh what a nightmare!

3

There are 3 answers

0
Ether On

If I read your question correctly, you're having difficulty opening the database on a new machine. Does the database exist there?

The documentation for the dbmopen method is available on the command line via perldoc -f dbmopen (and at this link for the latest stable perl release, 5.10.1).

As you can see from the docs, the second argument to dbmopen contains the filename being opened. In the code you pasted, that's contained in the scalar variable $art_dbm. So what you need to do is look for some earlier declaration of this variable (perhaps it is loaded in from a configuration file, or it could be hard-coded). Then once you've found that DB, all that should be necessary is transferring that file over to your new machine.

If you need more help deciphering the code, feel free to edit your question with a code snippet and we can go from there.

(Now, if you've found the database but you just can't open it, you've got some other problem.. It's been a long time since I dealt with PAG files however.)

0
brian d foy On

Do you still have access to the original machines?

Although you are using a DBM files, that actual functionality can come from one of several implementations, some of which are not compatible. I'd dump the file with the same perl that created it, then recreate it with the new perl.

0
Schwern On

There's a few things which could be going wrong. The most obvious one is that the dbmopen() call isn't opening the file. If the DBM file doesn't exist, rather than failing dbmopen() just makes a new one which could be why it appears empty.

To eliminate that possibility, make sure the DBM file does exist and is readable. You also want to check if the dbmopen() succeeded, it will (usually) error out if its the wrong format.

die "$art_dbm does not exist" unless -e $art_dbm;
die "Cannot read $art_dbm"    unless -r $art_dbm;
dbmopen( %ARTS, $art_dbm, 0644 ) or die "dbmopen of $art_dbm failed: $!";

Unfortunately dbmopen() is too clever for its own good. If you give it "foo" it might create "foo.db" instead. Depends on the implementation. See below.

The other possibility is that your two Perls are trying to open the file with two different DBM implementations. Perl can be compiled with different sets of DBM implementations on your different machines. dbmopen() will use the first one in a hard coded (and historically barnacled) list. Its actually a wrapper around AnyDBM_File. You can check which implementation is being used with...

use AnyDBM_File;
print "@AnyDBM_File::ISA\n";

Make sure they're the same. If not, load the DBM library in question before using dbmopen. perldoc -f dbmopen explains.

Here's a demonstration. First we see what dbmopen() will default to.

$ perl -wle 'use AnyDBM_File; print "@AnyDBM_File::ISA"'
NDBM_File

Then create and populate a dbm file.

$ perl -wle 'dbmopen(%foo, "tmpdbm", 0644) or die $!; $foo{23} = 42;  print %foo'
2342

Now demonstrate we can read it.

$ perl -wle 'dbmopen(%foo, "tmpdbm", 0644) or die $!; print %foo'
2342

And try to read it using a different DBM implementation.

$ perl -wle 'use GDBM_File; dbmopen(%foo, "tmpdbm", 0644) or die $!; print %foo'

Nothing in the file, but no error either. Turns out it made a file called tmpdbm whereas ndbm was using tmpdbm.db. Let's try Berkeley DB.

$ perl -wle 'use DB_File; dbmopen(%foo, "tmpdbm", 0644) or die $!; print %foo'
Inappropriate file type or format at -e line 1.

At least that gives an error.

Your best bet is to figure out what DBM implementation the original machine is using and use that module before the dbmopen() call. That will make the situation static.

PS The Unix file utility will also give you a good idea what type of DBM it is.

$ file tmpdbm
tmpdbm: GNU dbm 1.x or ndbm database, little endian
$ file tmpdbm.db
tmpdbm.db: Berkeley DB 1.85 (Hash, version 2, native byte-order)

And hope to $diety its not a byte-order issue, less common now that almost everything is x86.

PPS As you can see, using DBM files is a bit of a mess. Strange considering its supposed to be just a hash-on-disk.