views:

101

answers:

4

On a Solaris box in a "mysterious production system" I'm running a Perl script that references an environment variable. No big deal.

The contents of that variable from the shell both pre- and post-execution are what I expect.

However, when reported by the script, it appears as though it's running in some other sub-shell which is clobbering my vars with different values for the duration of the script.

Unfortunately I really can't paste the code. I'm trying to get an atomic case, but I'm at my wit's end here.

A: 

1) What version of Perl?

2) Some environment variables can be clobbered by child processes, I believe. Can you do a ps?

Paul Nathan
We're using 5.8.4. I unfortunately can't ps it. 1) it's over too fast. 2) it's a symlink of a read only script, so I can't add a pause in to game it so that I could.
Michael Wilson
Can you kill the symlink and create a copy in that places for debugging?
Paul Nathan
Yeah ya know, I may very well be able to do that. It has vast tendrils with execution of sub processes for it's "live" purpose, but thinking calmly I see no reason I couldn't at least get it to the problem area in an isolated environment.
Michael Wilson
@MichaelWilson Write Pause.pm which does `END { sleep 999 } 1;` and run the program as `perl -Ipath/where/Pause/lives -MPause yourprogram`. That'll make it sleep when its done. You can use the same technique to tie the %ENV hash and have it report any time its altered. Or just copy the code to your home directory, edit it to your heart's content and run it from there. If it uses FindBin to locate things you can alter $0 in a BEGIN block to match the original location.
Schwern
+2  A: 

Is it possible that your script or any libraries that you are 'use'-ing mess around with the %ENV hash?

dalton
Good thought, but unfortunately not. It's only using Sybase::DBLIB and Net::FTP.
Michael Wilson
Put `BEGIN{use Tie::Trace;Tie::Trace::watch %ENV}` at the top of your script (before you `use` any other modules). Then you'll get a warning message every time an environment variable changes in your Perl script.
mobrule
@mobrule: great tip! I never knew about that before.
Paul Nathan
@mobrule: That suggestion is too good for just a comment. Put it as a answer and earn yourself some upvotes. Of course, if I wanted a really secure system, I'd probably clobber most of `%ENV` at startup.
Axeman
+1  A: 

Can you run the code through the Perl debugger to see where it's going? Can you dump the pid ($$) to check if it is forking or invoking subshells?

Alternatively, you could sprinkle print statements throughout the code to narrow down at what point the environment variable is being altered, or start stubbing out components that are not likely to be relevant to hone in on the trouble spot.

Ether
I like the perl debugger idea. I keep forgetting it's there ;)At the moment we've found a very strange environmental workaround so, in the interest of expedience I have to go with that (it's at a much higher level than this symptom.)Once I'm clear of this problem I'm going to clone the thing locally and see if I can't figure it out the way you're describing.Thanks o/
Michael Wilson
A: 

Ok, here's what was going on:

perl itself was a red herring entirely.

The script was executing in a child shell which, when created, was re-loading rc files. Those rc files were blowing away the environment variables I had manually added during the parent shell with reference copies.

I was able to demonstrate this with a simple csh script that just echoed just echoed the environment.

De-wonkifying my rc files (which were overwrought with wonkitude) cleared up the mystical replacement.

UPDATE: The test that proved this was a "test.sh" that had a simple "set" command. It proved that the sub-shell wasn't inheriting the parent environment correctly. Oddly, when I switched my parent interactive shell to ksh, the environment began inheriting correctly.

Michael Wilson