How to run node.js script without a file, from Perl? - perl

I'm generating a node.js script inside a Perl program, and I want to run that through node.js, as a JavaScript interpreter. How canO run the node in $script without writing it to disk and then calling node, afterwards capturing the output.
I'm using the system command, which I think is good for this purpose.

Use IPC::Run or IPC::Open3.
use strictures;
use IPC::Run qw(run);
use autodie qw(:all run);
my $in = '… JavaScript goes here …';
my $out;
run ['node'], \$in, \$out;

Use open instead of system
#!/usr/bin/perl
open(FOO, "|node");
print FOO "console.log('hello world');";
Or if you don't need to do it from inside the perl script, just from your shell:
$ ./myscript.pl | node
Where myscript.pl exits after printing the javascript code

Related

Printing the result of the script(running in background) on the terminal

I am writing a perl script which runs another tcl script from it. The terminal doesn't print anything and waits for the tcl script to complete.
`chmod +x runme.tcl`; `./runme.tcl 2>&1`;
Can anyone please help me on how to print the results of the tcl script on the terminal instead of just waiting for it to get completed?
Thank you
system('chmod +x runme.tcl');
system('/runme.tcl 2>&1');
You can run tcl scripts directly from perl using the Tcl module without having to mess around with qx or system:
#!/usr/bin/env perl
use warnings;
use strict;
use Tcl;
Tcl->new->EvalFile("runme.tcl");
It'll share the same standard output as the perl script.
If you're using a new enough version of Tcl, you can easily create a safe interpreter to evaluate the script in case it tries to do anything nasty:
#!/usr/bin/env perl
use warnings;
use strict;
use Tcl v1.05;
my $interp = Tcl->new;
my $safeinterp = $interp->CreateSlave("safeinterp", 1);
$interp->Eval('interp share {} stdout safeinterp');
$interp->Eval('interp share {} stderr safeinterp');
$safeinterp->EvalFile("runme.tcl");
Backticks capture the output of an external command. You can write that output with a print command in front of the backticks.
`chmod +x runme.tcl`; print `./runme.tcl 2>&1`;

Communication between parent and child process - Perl

I'm running a perl program "a.pl" in the terminal that needs to call another program "b.pl" which then turns the environment to a tcl shell. The program "b.pl" sets environment variables which I have to use back in the main program "a.pl", after which I need to run new commands in the tcl environment created by "b.pl". Please see the example below
Program: a.pl
#!/usr/intel/bin/perl -w
use strict;
use warnings;
#turns it to a tcl shell and sets environment variable VERSION
system ("./b.pl");
system ("source <tclExecutable> -version $VERSION");
The second system command doesn't execute until I exit the tcl shell manually in the terminal. I've looked at fork and opening a pipe but I'm not sure how to go about it. I need to execute the second command in the tcl shell opened by the first system command. How can I make this work?
You may run b.pl "inside" a.pl using require. It may deliver what you want for simple scripts.
a.pl
use strict;
use warnings;
our $Version;
require "/.../b.pl"; # full path to b.pl script
print "Version: $Version\n";
b.pl
use strict;
use warnings;
our $Version;
$Version = "YES!";

Calling perl script from perl

I have a perl script which takes 2 arguments as follows and calls appropriate function depending on the argument. I call this script from bash, but i want to call it from perl, is it possible?
/opt/sbin/script.pl --group="value1" --rule="value2";
Also the script exits with a return value that I would like to read.
The Perl equivalent of sh command
/opt/sbin/script.pl --group="value1" --rule="value2"
is
system('/opt/sbin/script.pl', '--group=value1', '--rule=value2');
You could also launch the command in a shell by using the following, though I'd avoid doing so:
system(q{/opt/sbin/script.pl --group="value1" --rule="value2"});
Just like you'd have to do in sh, you'll have to follow up with some error checking (whichever approach you took). You can do so by using use autodie qw( system );. Check the docs for how to do it "manually" if you want more flexibility.
If you want to capture the output:
$foo = `/opt/sbin/script.pl --group="value1" --rule="value2"`;
If you want to capture the exit status, but send script.pl's output to stdout:
$status = system "/opt/sbin/script.pl --group=value1 --rule=value2";
If you want to read its output like from a file:
open SCRIPT, "/opt/sbin/script.pl --group=value1 --rule=value2 |" or die $!;
while (<SCRIPT>) ...
Yes. You can use system, exec, or <backticks>.
The main difference between system and exec is that exec "executes a command and never returns.
Example of system:
system("perl", "foo.pl", "arg");

Writing into a pipe in perl

I am passing the commands to some application through the Perl script using the pipe.
So I write the commands on pipe. But my problem is that the pipe is not waiting till the command execution is over from the application side and it takes the next command. So it is not blocking the inputs till the command execution is over. I need my Perl script work like UNIX shell. But it happens like the process is running in to background. I use readling to read the inputs.
#!/usr/bin/perl -w
use strict;
use Term::ReadLine;
open (GP, "|/usr/bin/gnuplot -noraise") or die "no gnuplot";
use FileHandle;
GP->autoflush(1);
# define readline
$term = new Term::ReadLine 'ProgramName';
while (defined( $_ = $term->readline('plot>'))) {
printf GP ("$_\n");
}
close(GP);
I recommend use of a concrete CPAN module, like Chart::Gnuplot, so you can have a high level of control

using export and perl -c in perl scripting

Since export cannot be used with a Perl script I've used the environment variable.
This code doesn't return any error but the command perl -c to check the syntax of the .pm file does not print the output.
myscript.pl
$ENV{'PATH'}='C:/Users/abc/Desktop/mno/wwwww/scripts/lib/perl/';
system("perl -c ContentModifySeasonPassOverlayRecord.pm");
Let me make another guess at what you want to do:
You want to batch syntax-check all your Perl modules, maybe in a cronjob. The script you are using to do that is located somewhere outside your working directory (where your framework sits). The scripts you want to check also sit somewhere else.
What you need to do is run the perl -c command from where the lib (framework) is, so that the working directory for the script while running has the lib files. You need to change the working directory before doing your perl -c call, and you need to include the full path to your scripts in the call.
#!/usr/bin/perl
use strict; use warnings;
# Change current working directory to where the framework is
chdir('/home/user/Desktop/QWARTS-0.6/autoinfra/lib/perl/');
# Run the perl -c command for each of your scripts you want to check
foreach my $script (qw(ContentModifySeasonPassOverlayRecord.pm otherfiles.pm)) {
system("perl -c /path/to/your/scripts/$script");
}
#!/usr/bin/perl
use warnings;
use strict;
system("perl -c /root/.cpan/build/DateTime-TimeZone-1.31-oqQt_7/lib/DateTime/TimeZone/America/Noronha.pm");
I don't see how it doesn't work?
# ./errr.pl
/root/.cpan/build/DateTime-TimeZone-1.31-oqQt_7/lib/DateTime/TimeZone/America/Noronha.pm syntax OK
I think you are doing a wrong way to execute a perl script with in perl script
here is the right way of executing a perl script with in perl script
use strict;
use warnings;
use IPC::System::Simple qw(system capture);
# Run a command, wait until it finishes, and make sure it works.
# Output from this program goes directly to STDOUT, and it can take input
# from your STDIN if required.
system($^X, "yourscript.pl", #ARGS);
# Run a command, wait until it finishes, and make sure it works.
# The output of this command is captured into $results.
my $results = capture($^X, "yourscript.pl", #ARGS);
And to check the errors in a module , You can just 'use' the module in your perl script and run the script in an usual way , if it has errors it will throw to stdout
If you want to test large number of perl modules you can build a shell script for that purpose .
#!/bin/sh
// List all modules
MODULES="Data::Dumper Foobar::Test"
for i in $MODULES ; do
if $(perl -M$i -e '1;' >/dev/null 2>&1 ); do
echo "Ok."
else
echo "No."
fi
done