CMD operations through Perl - perl

Trying to run some commands through perl. One of the command requires to press enter in the middle to complete!
I was first trying with java but failed to do so i thought it's possible in perl but not getting through!
$dir = "C:\\bip_autochain\\scripts";
chdir($dir) or die("Can't change to dir \n");
system("lcm_cli.bat -lcmproperty C:\\pl\\LCMBiar_Import.property");
sleep(5);
system("\n");
The system command highlighted requires to press enter after some time say 5 sec.
My code doesn't serve this purpose.

If you want to send data from your Perl script to a command launched in a subprocess you need to pipe a filehandle in to the program when launching it. Then you wait the required time and send the data using print (or printf).
There is one huge caveat. If the external program opens the console terminal directly for input and does not read from stdin (i.e. to prompt for a password) you may not be able to send the data to the program.
For the standard case where the program reads from stdin:
$dir = "C:\\bip_autochain\\scripts";
chdir($dir) or die("Can't change to dir \n");
open(CMD, "|lcm_cli.bat -lcmproperty C:\\pl\\LCMBiar_Import.property");
# ^
# vertical bar, aka "pipe" symbol
sleep(5);
print CMD "\n";
...
close(CMD); -- when you are done sending data
The pipe symbol at the beginning of the command is a special form of open that sets up the CMD filehandle piped to the command's stdin. This is descibed in the documentation

Related

Perl script interacting with another program's STDIN

I have a Perl script that calls another program with backticks, and checks the output for certain strings. This is running fine.
The problem I have is when the other program fails on what it is doing and waits for user input. It requires the user to press enter twice before quitting the program.
How do I tell my Perl script to press enter twice on this program?
The started command receives the same STDIN and STDERR from your script, just STDOUT is piped to your script.
You could just close your STDIN before running the command and there will be no input source. Reading from STDIN will cause an error and the called command will exit:
close STDIN;
my #slines = `$command`;
This will also void any chance of console input to your script.
Another approach would use IPC::Open2 which allows your script to control STDIN and STDOUT of the command at the same time:
use IPC::Open2;
open2($chld_in, $chld_in, 'some cmd and args');
print $chld_in "\n\n";
close $chld_in;
#slines = <$chld_out>;
close $chld_out;
This script provides the two \n input needed by the command and reads the command output.
You could just pipe them in:
echo "\n\n" | yourcommand

Perl - Logging to terminal from a long running system call

I am calling an external program from my perl code using backticks
print `<some long running program>`
The long running program prints detailed log messages onto standard output.
The problem I'm having is that due to buffering, the output from the long running program is printed all at once after it has finished its execution.
I tried making the STDOUT filehandle "hot" but that did not help.
Is there anyway I can have my program print continuously onto the screen?
Open as an exec pipe rather than using backticks.
open ( my $prog_stdout, "-|", "/your/program" ) or die $!;
This will fork and exec but give you access to $prog_stdout to do things with.
E.g.
while ( <$prog_stdout> ) {
print;
}
(It'll close if your external program exits, so the while will terminate).
You may also want to include autoflushing of the filehandle. http://perldoc.perl.org/IO/Handle.html
But that may not be necessary, as output won't be buffered indefinitely.
It might not be buffering but the fact that back ticks return when external program finishes.
You can however use reading pipe to read external output line by line,
use autodie;
open my $pipe, "-|", "<some long running program>";
# $pipe->autoflush();
while (<$pipe>) { .. }

Simulate pressing enter key in Perl

I have following perl script which saves the output from the command into a textfile
#!/usr/bin/perl
use warnings;
use strict;
use Term::ANSIColor;
my $cmd_backupset=`ssh user\#ip 'dsmadmc -id=username -password=passwd "q backupset"' >> output.txt`;
open CMD, "|$cmd_backupset" or die "Can not run command $!\n";
print CMD "\n";
close CMD;
The output of output.txt is this:
Text Text Text
...
more... (<ENTER> to continue, 'C' to cancel)
The script is still running in the terminal and when I press enter, the output.txt file gets the extra information. However, I must press enter more than 30 times to get the complete output. Is there a way to automate the script so when the last line in output.txt is more..., it simulates pressing enter?
I have tried with Expect (couldn't get it installed) and with echo -ne '\n'
Most interactive commands, like the one you are using, accept some flag or some command to disable pagination. Sometimes, connecting their stdin stream to something that is not a TTY (e.g. /dev/null) also works.
Just glancing over IBM dsmadmc docs, I see it accepts the option -outfile=save.out. Using it instead of standard shell redirection would probably work in your case.

How can my perl script invoke and exe and post process it

I need my script to do a simple operation:
Use unix script command to log the activities on the screen to a file
execute a shell script ( there are multiple lines output by this script to STDOUT)
Stop the script command
Analyse the output of the script command
I am planning to use system command to do this work, but I am not sure if I should fork the shell script and wait for its completion. Since the output of the shell script is multiple like not sure if capture will work. Let me know the best option
This is one of the most interesting questions I've come across in a while.
Let's say you have a shell script myscript.sh. To get script to run it and capture the output, at least on my SUSE linux, so check your script(1) man page, I'd write:
script -c /path/to/myscript.sh myscript.log
So the Perl would look vaguely like:
# first, a bunch of code to initialize the program
# then run the shell script.
my $rv = system("script -c /path/to/myscript.sh myscript.log");
# then a bunch of code to process myscript.log
But I'm wondering my you can't just:
system("/path/to/myscript.sh > myscript.log");
instead of involving script(1)?
Why do you need to use script at all? Is the shell script interactive? Does it need a valid TTY? If it is a non-interactive batch job that doesn't need a valid TTY, then you'd be best off opening it as a pipe and processing the output via a file handle.
For example:
open my $cmd_handle, "-|", $command, #args
or die "Could not run $command #args: $!";
foreach my $line ( <$cmd_handle> )
{
# ... process the command output here ...
}
close $cmd_handle;
This has the advantage that your Perl script will process the command's output as it happens. In case you really do need to defer processing until the end, you could slurp all the output into an array and then process it afterwards:
open my $cmd_handle, "-|", $command, #args
or die "Could not run $command #args: $!";
my #cmd_output = ( <$cmd_handle> );
close $cmd_handle;
foreach my $line ( #cmd_output )
{
# ... process the command output here ...
}
Either ought to be better than running the command via script if it meets those restrictions I gave above: non-interactive, and does not need a valid TTY. Most batch scripts meet those restrictions.

Calling command from Perl, need to see output

I need to call some shell commands from perl. Those commands take quite some time to finish so I'd like to see their output while waiting for completion.
The system function does not give me any output until it is completed.
The exec function gives output; however, it exits the perl script from that point, which is not what I wanted.
I am on Windows. Is there a way to accomplish this?
Backticks, or the qx command, run a command in a separate process and returns the output:
print `$command`;
print qx($command);
If you wish to see intermediate output, use open to create a handle to the command's output stream and read from it.
open my $cmd_fh, "$command |"; # <--- | at end means to make command
# output available to the handle
while (<$cmd_fh>) {
print "A line of output from the command is: $_";
}
close $cmd_fh;