I am trying to understand the significance of the special variables $!,$@ and $? in perl. I have a code block as follows:
eval {
Code Segment 1: #authenticating to the remote server
$ftpobj -> login($username,$password) or die "Can't login to $remote_host";
Code Segment 2: #setting up the current working directory
$ftpobj -> cwd ($cwd) or die "Can't change directory";
Code Segment 3: #putting the file in remote server
$ftpobj -> put($filename) or die "Can't ftp the file:",$!;
}
[Where $ftpobj is an Net::FTP object and $filename is an invalid filename]
In Code Segment 1 and 2,if there were any errors,i can able to catch it using if($@) since the above code is enclosed by eval.
But the trapping is not successful in the case of Code Segment 3.Although the control comes inside the conditional loop if($@) after eval,error message
is written to the Standard output with this.The error message is:
"Cannot open Local file test2.log: No such file or directory
at ftp_file.pl line 44"
Why is this happening?Exception handling in perl is implemented using eval{} and if($@), but in this case the error is going out-of control and got printed to STDOUT or STDERR
Can anyone suggest what is going on and what is the reason for this behaviour?
Can anyone explain me what makes $!,$@,$? different in various situations?
$@ is the error message from the last eval(). Period. It's null if there was no eval.
$! is what went wrong after the last call to the OS -- it's essentially from errno. It gets reset as soon as you do something that succeeds, like the statement "1;".
$? Is only after an external command, pipeline, system(), or wait(), it contains the error the last command returned, shifted left 8 bits.
About the error message, it could be Net::FTP is printing out to stderr. You can instantiate the object with a Debug parameter...
Thank you for your response.I understand about the variable difference.But am just wondering what is Debug code "10".My understanding is that a non-zero debug code will print each and every internal process to STDOUT.So how this will help to solve my problem.ie,Throwing error to STDOUT or STDERR
My guess is that the misplaced comma in your third segment is causing the error to be lost. You probably mean die "Can't ftp the file: $!" rather than (die "Can't ftp the file"), $! which is what your code currently seems to do, if I managed to get the precedence right.
Where in your code is there a reference to Local file test2.log? Is that the file you are attempting to upload? (What's the value of $filename?)
"die" takes a list, so that comma is fine. The problem might be in the Net::FTP implementation. Why don't you use the debugger and trace your way through the code?
It's possible to override the die/warn handlers with $SIG{__DIE__} = code; In this way, a module can redirect stderr to stdout, or something like that. It might be the Net::FTP module is doing this.
Thanks for your response. I know the filename is invalid.Basically am trying to workout on the exception handling mechanism, where exceptions from all the above statements like,creating ftp object,loggging,change directory etc are trapped in $@ and print only if i give a print statement in the catch block or if($@) block.
But in this case alone ie,putting the file to remote server,error is thrown to the STDOUT/STDERR along with trapping it in $@.I am wondering about this behaviour and looking for the reason and solution.
Unfortunately, the possibility you had given(comma) is not the trum card!
I got a little clue about the reason.Thanks otheus to make me look into the source code of Net::FTP module.Your doubt is correct,this module is the core reason for this behaviour
In this module,in situations like can't able to open the file due to permissions,invalid filename etc. 'carp' method in 'Carp' module is called,which will act exactly like inbuilt method 'warn'.The exceptions or control thrown using 'warn' is not possible to trap using a $@ and it won't be get set in this case also.So the message is thrown out to the STDOUT/STDERR.
One question i have to you guys is how to trap or prevent this from being printed into the console.I know i can do it by redirecting the output or error message and all.But i want it to be trapped...Anyone please!
If you don't have the latest version of this module, get it from CPAN. If you do have it, bitch to the authors -- that sounds like sloppy module writing to me. Good luck on your project!