Executing Perl script from Tcl - perl

I'm trying to execute a Perl script from Tcl.
I use eval in Tcl, and it executes the Perl script but doesn't execute the other command in my Tcl file.
Tcl:
eval perl perl_script
puts "Command executed"
Result: the Perl script is executed, but not the puts command. Why is this?

In tcl, eval executes its arguments as tcl code, similar to its perl equivalent. But, you do not want this, instead you need to launch the perl interpreter as an external process and ask this interpreter to execute the script passed in its commandline. This is the job of exec in tcl.
exec perl perl_script
Read more about exec # https://www.tcl.tk/man/tcl/TclCmd/exec.htm
UPDATE
exec will throw an error when the command returns a non-zero exit status. You need wrap exec with a catch to continue with non zero exit status. See WORKING WITH NON-ZERO RESULTS
UPDATE 2
The reason why eval perl script_path manages to successfully launch the perl interpreter is tcl's unknown magic. It is likely that you do not have tcl proc named perl. So, tcl calls the "unknown" proc, which tries to handle this exception intelligently by calling exec on its arguments since it finds an executable in $env(PATH). You can try info body unknown to see how this magic actually works.

Try this:
exec sh -c { perl -ape 's/this/that/' tmp.1 > tmp.11 }
It works for me.

Related

how to capture the exit status of capture calling another perl script within a perl script and if it fails it should die

I've just started using Perl 5.26 on secure-CRT and i wrote a Perl script that capture calls multiple Perl scripts.
my #secondCommand = capture("perl clientquery.pl -r $cid -l test.log -is $sqlFile");
I was wondering how can I capture the exit status of each capture calling and if it fails how can i make the original script die.
IPC::System::Simple provides $EXITVAL, which captures the exit code of commands run via capture and the other functions.
The exit value of any command executed by IPC::System::Simple can
always be retrieved from the $IPC::System::Simple::EXITVAL variable:
This is particularly useful when inspecting results from capture,
which returns the captured text from the command.
use IPC::System::Simple qw(capture $EXITVAL EXIT_ANY);
my #enemies_defeated = capture(EXIT_ANY, "defeat_evil", "/dev/mordor");
print "Program exited with value $EXITVAL\n";
$EXITVAL will be set to -1 if the command did not exit normally (eg,
being terminated by a signal) or did not start. In this situation an
exception will also be thrown.

Shell calling perl and returning back string to Shell Script

I have a shell script , i want to call a perl script to do some compute, once perl is called i want perl to process it and while returning i want it to return not exit code but a string back to shell script ? how can i do that?
Here is my simple piece of code calling perl in shell script
VAR=$(perl Test.pl)
Quick and dirty would be to have the perl script print the Information to STDOUT and just call it in your Shell script by backticks or just as you did.
Along the lines of
VAR=`perl Test.pl`
This will put everything the perl script printed to STDOUT into VAR.

Output of bash script in perl script

I want to embed a bash script inside a perl script. I want to run my bash script by taking some variables from the perl script. Once it gets the variable the bash script takes over and tries to output the files that is created within.
How can I pass the perl script variable to my bash script ?
I do not know perl but from what I read in Google, I can embed my bash script as
system("get_files.cmd -yr ${year}");
where my bash script is get_files.cmd.
I think it might be better if you passed them as arguments to your bash script.
The perl call:
system("get_files.cmd ${var1} ${var2}");
The bash script
var1="$1"
var2="$2"
...
Where $1, $2 are the arguments passed in the command line (in order). Note that you can use the $# bash variable to get the number of arguments passed.
Hope this helps =)
The Expect module can essentially automate shell tasks such as running scripts and passing perl variables. Such that:
Use Expect;
# create an Expect object by spawning another process
my $exp = Expect->spawn($command, #params)
or die "Cannot spawn $command: $!\n";
http://search.cpan.org/~rgiersig/Expect-1.15/Expect.pod

Executing perl code inside shell script using eval

I came across the following example. I tried to google but could not find much so I'm posting this question here.
What is the benefit of executing the perl script like this?
How can we make the shell script work like a "normal" shell script once we are through executing the perl code?
Here's the code:
#!/bin/ksh
#! -*- perl -*-
eval 'exec $PERLLOCATION/bin/perl -x $0 ${1+"$#"} ;'
if 0;
print "hello world\n";
# how can I make it behave like a "normal" shell script from this point onwards? What needs to be done?
# echo "hello world" ### this results in error
This idiom is described in the perlrun documentation.
The -x switch scans the whole file and ignores anything that appears before the first line that begins with #! and also contains the word perl.
It means that your system will run the script with the Perl interpreter whether you invoke the script with perl or with a shell command (sh/bash/ksh/etc.)
That is,
$ perl this_script
and
$ sh this_script
will both run the script with perl.
To address your second question, this idiom has just about nothing to do with combining shell script and Perl script in the same file. There are a few different ways to approach that problem, but maybe the most readable way is to write in shell script, but use the shell's heredoc notation to invoke perl code.
#!/bin/bash
# this is a bash script, but there is some Perl in here too
echo this line is printed from the shell
echo now let\'s run some Perl
perl <<EOF
# this is now perl script until we get to the EOF
print "This line is printed from Perl\n";
EOF
echo now this is from the shell script again
1. If you start a Perl script in the usual way:
#!/usr/bin/perl
print "hello world\n";
the #! line will only work if the Perl interpreter is actually installed under /usr/bin. The perl/ksh bilingual script you show is a tricky kluge to make the script work even if perl is installed somewhere else. For more information, see e.g. this.
2. You can't. When the shell process encounters the exec command, it terminates and hands control over to perl. (Technically, it executes perl in place of the shell, without creating a new process.) The only way to run more shell commands after that would be to launch a new shell.
It's way simpler than what's already been posted.
#!$PERLLOCATION/bin/perl
doesn't work because the shebang (#!) line is interpreted by the kernel (not the shell), and the kernel doesn't do variable interpolation.
The code invokes ksh to expand the environment variable and to launch the specified installation of Perl.

Not able to call a perl script from a shell script

I am trying to call a perl script from a shell script and code looks like shown below...
shell script test_sh
#Call the script
test2.pl ${PARTITION_ID} ${VNG_USER} ${VNG_PASSWORD} ${VNG_INSTANCE}
if [ $? -ne 0 ]
then
OP1ExitStatus -6
fi
while execution getting below error message:
./test_sh[142]: test2.pl: not found
Failed in test_sh
permission given to both files are 755.
But when i and calling test2.pl directly from the command line by passing all arguments it runs successfully.
I tried with below command as well :
#Call the script
perl test2.pl ${PARTITION_ID} ${VNG_USER} ${VNG_PASSWORD} ${VNG_INSTANCE}
if [ $? -ne 0 ]
then
OP1ExitStatus -6
fi
but it is also not working.
please let me know how to proceed in order to run it successfully.
From the command line you're invoking perl test2.pl directly. From the script you're assuming that (1) test2.pl is executable and (2) . is in $PATH somewhere. I would use the direct perl invocation in the script, at least for now.
check your shebang, eg #!/bin/bash. you may also want to try using the full path of your Perl executable.
That usually means that the path to perl in the shebang line at the top of the Perl script is wrong (assuming that the file has execute permission for you).
Try using:
#!/usr/bin/env perl
Your shell script is unable to find your test2.pl. You need to give the full path of test2.pl in your shell script or ensure it is in your $PATH.