From a bash script how can i execute a perl script get the output and exit if value is = 0?
Also in the perl script how do i return the value, do i just return it or do i print it?
#!/bin/bash
perl-script args && exit
If you want to continue running, the return value is in $?
Note that there is a distinction between the value returned by the perl script and the output of the script. To get the output of the script, use the $() operator:
#!/bin/bash
output=$(perl-script args)
echo The perl script returned $?
echo The output of the script was $output
To get a return code, use the exit function. Example:
Perl script:
if ($success) {
$return_value = 0;
} else {
$return_value = 1;
}
exit($return_value);
Bash script:
perl scriptname args > outfile && exit
That's assuming that you want to exit if the return value of the Perl script is 0 and you want so save the output of the Perl script in outfile. If the return value is not zero, it's stored in $?, you can save that value to a variable if you please.
Your perl script: foo.pl
#!/usr/bin/perl
# do something and then
exit 1;
And inside your bash script foo.sh:
#!/bin/bash
# do something and then call perl script
perl foo.pl
# check return value using $?
echo "perl script returned $?"
Related
I have a master Perl script that needs to call another Perl script with options. I read many threads regarding arguments but I need both, arguments and options. Below is my sample code:
sub run_script_a{
my $script_path = "/home/sample/script.pl"
my #ARGS = "input.txt";
##I need to capture the result of the script run and fail if something went wrong
system($^X, $tool_path, #ARGS);
}
I tried the following:
my #ARGS = "input.txt -o output.txt";
It didn't work, gave me this error:
Cannot open input.txt -o output.txt for read: No such file or directory
How do I make it work? The second script runs as:
sample.pl input.txt -o output.txt
I am not good at coding bash scripts so I am using Perl.
my $tool_path = "/home/sample/script.pl"
my #args = "input.txt -o output.txt";
system($tool_path, #args);
is equivalent to the shell command
/home/sample/script.pl "input.txt -o output.txt"
You want
my $tool_path = "/home/sample/script.pl"
my #args = ( "input.txt", "-o", "output.txt" );
system($tool_path, #args);
Actually, if you want to capture the output, there's no need to involve a file. You want
use IPC::System::Simple qw( capturex );
my $tool_path = "/home/sample/script.pl"
my #args = "input.txt";
my $output = capturex($tool_path, #args);
Use backticks to run script with arguments and capture output (perldoc -f qx).
perl -E'say `echo 4 | $^X -p ./script.pl`'
Content of script.pl:
$_**=3
How to run a if block in unix from perl.
Eg:
location="/home/shon";
if [[ -f $location/sample.txt ]]
then
echo "file found...."
else
echo "Error in getting file"
exit 255
fi
from perl.
As suggested, this code is simple to translate into perl. Assuming you have something more complex, you can spawn a shell to run it: put the shell code in a quoted heredoc so that perl does not substitute the shell variables.
system 'bash', '-c', <<'END_SHELL_CODE';
location="/home/shon"
if [[ -f $location/sample.txt ]]; then
echo "file found...."
else
echo "Error in getting file"
exit 255
fi
END_SHELL_CODE
Try this
#! /usr/bin/perl
my $location ="/home/shon/sample.txt";
if (-f $location)
{
print "file found....";
}
else
{
print "Error in getting file";
}
Suppose, we have a bash script:
#!/bin/bash
perl /home/user/myscript.pl
echo "hello"
myscript.pl:
#!/usr/bin/perl
print "First\n";
#here I want the script to sleep for 5 seconds
#and return the execution back to the caller
#so, "hello" will be printed
#but after 5 seconds the script will wake up from sleep and run the next line
print "Second\n";
How can I this?
#!/bin/bash
perl /home/user/myscript.pl &
sleep 5
echo "hello"
#!/usr/bin/perl
...
-or-
#!/bin/bash
perl /home/user/myscript.pl
echo "hello"
#!/usr/bin/perl
sleep(5);
$SIG{CHLD} = 'IGNORE';
exit(0) if fork();
...
Here is the updated question
Script:
open (my $pipe, "| ptsetenv.sh $ProductType $Release");
print $pipe "genidasack.py -v --alignment=mips64 -a -s $WORKSPACE/dbgen/ose_signals_ADA.sdt -o $WORKSPACE/$Product/\n";
close ($pipe);
Command 2:
ptsetenv.sh $ProductType $Release # Sets Environment Variables and creates a Child Shell
Command 3:
genidasack.py -v --alignment=mips64 -a -s $WORKSPACE/dbgen/ose_signals_ADA.sdt -o $WORKSPACE/$Product/\n #this has to be executed on child Shell created by Command 2
Currently when i run the script within a perl script after first line child shell is invoked and script remains at child shell when type exit from child shell subsequent script lines are executed which is not what is needed!
HERE ARE CONTENTS OF ptsetenv.sh
envsetup.py $*
./export_env.sh
export_env.sh is the script which basically creates the child shell
Let me know if you need contects of export_env.sh
HERE ARE CONTENTS OF export_env.sh
has_dir()
{
if [ -d $1 ]; then
return 0
else
return 1
fi
}
has_dir $DXENVROOT
if [ "$?" != "0" ]; then
echo "Directory $DXENVROOT does not exist. Exiting the script."
exit -1
fi
echo "Environment set to ${DXENVNAME} ${DXENVVERSTR}"
echo $SHELL
$SHELL
echo "Exiting ${DXENVNAME} ${DXENVVERSTR} shell"
This will run a sequence of commands in the child shell:
system("Command 1; python script; Command 2");
You can also do:
system("Command 1");
system("python script");
system("Command 2");
This avoids creating a shell process if there are no special shell characters in the commands.
UPDATE:
Now that you've clarified that the python script starts a subshell, here's how to send a command to it:
open (my $pipe, "| Command 1; python script");
print $pipe "Command 2\n";
close ($pipe);
#!/bin/bash
i="0"
echo ""
echo "##################"
echo "LAUNCHING REQUESTS"
echo " COUNT: $2 "
echo " DELAY: $3 "
echo " SESSID: $1"
echo "##################"
echo ""
while [ $2 -gt "$i" ]
do
i=$[$i+1]
php avtest.php $1 $4 &
echo "EXECUTING REQUEST $i"
sleep $3
done
here is a better/modified script in bash
#!/bin/bash
i="0"
#startTime=`date +%s`
startTime=$(date -u +%s)
startTime=$[$startTime+$1+5]
#startTime=$($startTime+$1+5)
dTime=`date -d #$startTime`
echo ""
echo "##################"
echo "LAUNCHING REQUESTS"
echo " COUNT: $1 "
echo " DELAY: 1 "
#echo " EXECUTION: $startTime "
echo " The scripts will fire at : $dTime "
echo "##################"
echo ""
while [ $1 -gt "$i" ]
do
i=$[$i+1]
php avtestTimed.php $1 $3 $startTime &
echo "QUEUEING REQUEST $i"
sleep 1
done
Here's a direct translation
#!/usr/bin/env perl
use strict;
use warnings;
print <<HERE;
##################
LAUNCHING REQUESTS
COUNT: $ARGV[1]
DELAY: $ARGV[2]
SESSID: $ARGV[0]
##################
HERE
my $i = 0;
while($ARGV[1] > $i){
$i += 1;
system("php avtest.php $ARGV[0] $ARGV[3] &");
print "EXECUTING REQUEST $i\n";
sleep $ARGV[2];
}
But it would make more sense to read the command line parameters into variables named after what they're for and not rely on remembering argument ordering.
A brief errata in the conversion:
I use a here string to represent multiline text. I could also have put in multiple print statements to more closely mimic the bash version
In bash arguments are accessed as numbered variables, starting with $1 and going up. In Perl the argument list is represented by the array #ARGV, which is numbered starting at zero (like arrays in most languages). In both bash and Perl the name of the script can be found in the variable $0.
In Perl arrays are written as #arrayname when refering to the entire array, but they use $arrayname[index] when accessing array members. So the Perl $list[0] is like the bash ${list[0]} and the Perl #list is like the bash ${list[#]}.
In Perl variables are declared with the my keyword; the equivalent in bash would be declare.
I've used the system function for spawning background processes. Its argument can be simply the command line as you might use it in bash.
Unlike echo, print requires to be told if there should be a newline at the end of the line. For recent versions of Perl the say function exists which will append a newline for you.
The Perl sleep function is pretty self-explanatory.
EDIT: Due to a typo $i in the print statement had been represented as $ni leading to runtime errors. This has been corrected.