Perl not executing command when in debugger or as a Win32::Daemon - eclipse

Synopsis
I execute a shell command from Perl and when run from the command line it works, but when run in the debugger it does not work. Running it as a Win32::Daemon shows the same behaviour.
The Source Code
I execute a command either with backticks
print `$cmd`
or like this:
open FH, "$cmd |" or die "Couldn't execute $cmd: $!\n";
while(defined(my $line = <FH>)) {
chomp($line);
print "$line\n";
}
close FH;
The command reads like this:
$cmd = '"C:\path\to\sscep.exe" getca -f "C:\path\to\config\capi_sscep.cnf"'
Even creating a small test script that just executes this command does only work if run from command line.
The System
Windows x64
Active Perl v5.16.0, MSWin32-x64-multi-thread
Eclipse Juno 20120614-1722
What works
I works to open an administrator prompt (necessary for script execution) and to:
perl script.pl
Output gets printed to screen, $? is 0.
What does not work
Starting Eclipse and running a debug session with the same perl script.pl call.
Also not working is adding a service and executing the command (created with Win32::Daemon). The daemon itself is working perfectly fine and starting the perl script as expected. Only the command does not get executed. $? is 13568 or 53 if shifted with $? >> 8, no output gets printed. The exit code does not belong to the program.
Further Details
The tool I am calling is called sscep and is extended by me. It uses the OpenSSL API and loads the capi engine (Windows CryptoAPI). But the command itself does at least print output before any serious action starts. I can happily provide the source code for this, but I doubt it will help.
I was able to narrow this further down: The problem only exists in the combination of the Perl program (CertNanny) and the binary (sscep). Calling dir inside CertNanny works, calling sscep in a test Perl script works, too. So what could possibly be done in Perl to break a single binary from being called...?
Any ideas where this problem might originate from or how I can possibly narrow it down?

Here is what I believe the problem to be: when you run your program on the command line, the system() command goes through the shell (cmd.exe); when you run your program elsewhere, it does not. Unfortunately, the two methods handle command line arguments differently. Here is an article that seems like it should help you solve the problem.
In my experience, this sort of thing is a mess in Windows. I have had trouble with this issue in Perl, also.

Related

Perl executing an exe using system()?

I could not able to run the exe using perl code.
my $XSD = "C:\\IParser\\Iparser\.exe --xsds \"$dir\\$out\_xsd\.xml\"";
system($XSD);
The above $xsd run in commend prompt it will execute fine. when I run through perl source code it shows error as
the handle is invalid
I don't no what is the problem behind this. Please help.
This could be because of closed handles to STDIN, STDOUT and STDERR (or any of them). Most probably if you run this as a daemon or from service.
Try opening the standard handles before running the process (assuming you're on windows according to path):
open(STDIN, "<NUL");
open(STDOUT, ">NUL");
open(STDERR, ">NUL");

How to capture STDOUT from executable (cap) executed within a perl script executed from a crontab

Whew that is a long-winded title. But it explains my issue:
I have a crontab that runs a perl script.
That perl script runs a cap task, which outputs to STDOUT some status messages.
The perl script is supposed to capture the STDOUT (currently using backticks) from cap and parse it.
Now, this works 100% fine when I run the script from a bash user. However, when I run the script from a crontab, the perl script doesn't capture any output from the cap task.
Has anyone dealt with anything like this before? Thanks.
Maybe your cap executables are died without emitting any message to stdout. Did you checking the success state of execution?
Could you tried this?
$check_result = `$cmd 2>&1`;
if ($?){
die "$cmd failed with $check_result, $!";
}

Perl as a batch-script tool - fully piping child processes?

Apologies if some of the terminology may be slighlty off here. Feel free to correct me if I use a wrong term for something.
Is it possible to use Perl as an "advanced shell" for running "batch" scripts? (on Windows)
The problem I face when replacing a .bat/.cmd script that's getting too complicated with a perl script is that I can't easily run sub processes as a shell does.
That is, I would like to do the same thing from my perl script as a shell does when invoking a child process, that is, fully "connecting" STDIN, STDOUT and STDERR.
Example:
foo.bat -
#echo off
echo Hello, this is a simple script.
set PARAM_X=really-simple
:: The next line will allow me to simply "use" the tool on the shell I have open,
:: that is STDOUT + STDERR of the tool are displayed on my STDOUT + STDERR and if
:: I enter something on the keyboard it is sent to the tools STDIN
interactive_commandline_tool.exe %PARAM_X%
echo The tool returned %ERROLEVEL%
However, I have no clue how to fully implement this in perl (is it possible at all?):
foo.pl -
print "Hello, this is a not so simple script.\n";
my $param_x = get_more_complicated_parameter();
# Magic: This sub executes the process and hooks up my STDIN/OUT/ERR and
# returns the process error code when done
my $errlvl = run_executable("interactive_commandline_tool.exe", $param_x);
print "The tool returned $errlvl\n";
How can I achieve this in perl? I played around with IPC::Open3 but it seems this doesn't do the trick ...
Probably you'll find IPC::Run3 useful. It allow you to capture both STDOUT and STDERR (but not pipe them in real time). Command error level will be returned in $?.
Why not this way:
print "Hello, this is a not so simple script.\n";
my $param_x = get_more_complicated_parameter();
system('cmd.exe', $param_x);
my $errorlevel = $? >> 8;
print "The tool returned $errorlevel\n";
sub get_more_complicated_parameter { 42 }
I don't have your interactive program, but the shell executed allowed me to enter commands, it has inherited environment defined in perl, etc.
I am using perl as replacement for more complicated shell scripts on Windows for long time and so far everything I needed was possible.

How to grab the Unix command that I had run using Perl script?

As I am still new to Unix and Perl, I'm finding a simple and direct method to grab the Unix command that I had run using Perl script.
What I know is "history" can track back the commands that I had run, but it is not working in Perl using back ticks history to run it.
I tried to put "history > filename" in vi text editor in a temporary file, use command "source" it, and it works, but command "source" also not working in Perl script using back ticks.
Can anyone guide me about my problems? direct me to correct method to solve my problems? T.T
Thanks.
You can't. Shells (well, bash and tcsh, anyway, your shell might, but probably doesn't, vary) only save command history in interactive mode. Commands run in a subshell by a perl script won't be added to the history file.
This will get the history of commands that were run by the user in interactive mode:
$data_file = "~/.bash_history";
open(DAT, $data_file) || die("Could not open file!");
#fileData = <DAT>;
close(DAT);
foreach $command (#fileData) {
# Do things here.
}
As mentioned by Wobble, though, this history file will not include commands run from a Perl script - you'll have to have the script append the command to a file when it runs it, thus creating it's own history file (or, append it to ~/.bash_history, which will have it share the history file with interactive shells).
If you have access to the perl script (that is, you can change it), you can simply write each command run in the perl script to a chosen text file:
sub run_program
{
my $program = shift;
open PROGS, ">>my-commands.txt", or die $!;
print PROGS $program."\n";
`$program`;
close(PROGS);
}
then just run `run_program($command) every time you wish to run a command in the script.

jsvc (tomcat) does not daemonize properly when run with backticks and then defuncts

In debian lenny, when running /etc/init.d/tomcat5.5 start, it runs jsvc and expects it to daemonize itself.
From a simple bash shell, this works fine.
However, from a script, this gets completely stuck:
For example, the following works like a charm:
#!/usr/bin/perl
my $cmd = '/etc/init.d/tomcat5.5 start';
system($cmd);
However, the following gets stuck as jsvc does not daemonize:
#!/usr/bin/perl
my $cmd = '/etc/init.d/tomcat5.5 start';
`$cmd`;
It also gets stuck when running it using backticks in bash:
#!/bin/bash
CMD='/etc/init.d/tomcat5.5 start'
`$CMD`
Is this a bug in jsvc? Any idea why this works in a shell or using system() , but not using backticks? I am actually getting defunct/zombie processes because of this issue.
Just a hunch -- for a job to become a daemon it needs to close any file descriptors that were opened in its parent process. Perhaps this is easier to do with system than with backticks/readpipe, though I can't come up with any good reasons why that would be so. What if you used the backticks like:
`$CMD < /dev/null > /dev/null 2>&1`
Backticks will evaluate to the output of the command, if there's lots of data, you may fill the buffer. No need to use the backticks if you don't want to evaluate or catpure the output in the script itself.
In example, this bash script should work:
#!/bin/bash
CMD="/etc/init.d/tomcat5.5 start"
# note no backticks
$CMD
Also please define "daemonize"? You want this nohup'd and asynchronous?