How to return status from an rsh command using csh via perl

I have a perl script that runs a command via rsh and I need to get the exit status of that command on the remote server. The shell on both the local and remote servers is csh (I can't change this). To get the exit status on the remote server I am running:

my $output = `rsh myserver $command;echo $status`

The value of $output is the result of the command but the value of $status is never printed out.

I removed the rsh for testing and got the same results. Here is my test script:

#!/usr/local/bin/perl5.8

use strict;
use warnings;

my $output = `printf '';echo \$status`;
print "$command\n";
print "Returned: $output\n";

And here is the output:

printf '';echo $status
Returned:

If I copy and paste the command from the output into the command line the 0 prints out like I would expect:

:>printf '';echo $status
0

Any idea why this works via the command line but not via perl?

Answers


The back tick operator in perl uses sh (or more precisely, the default system shell, different from the default login shell) to execute the code, not csh, and $status is not a predefined shell variable in sh.


Problem 1

readpipe (aka `` aka backticks) executes its command using /bin/sh, which uses $? instead of $status.

Solution 1

Adjust the command to use csh

my $status = `/bin/csh -c 'rsh myserver $command; echo $status`;
die "Can't create child: $!\n if $? < 0;
die "Child killed by signal ".($? & 0x7F)."\n" if $? & 0x7F;
die "Child exited with exit code".($? >> 8)."\n" if $? >> 8;
die "rsh exited with exit code $status\n" if $status;
Solution 2

Adjust to a bourne shell:

my $status = `rsh myserver $command; echo $?`;
die "Can't create child: $!\n if $? < 0;
die "Child killed by signal ".($? & 0x7F)."\n" if $? & 0x7F;
die "Child exited with exit code".($? >> 8)."\n" if $? >> 8;
die "rsh exited with exit code $status\n" if $status;
Solution 3

The shell actually returns the exit code of the last command it executes, so you don't need to create a new channel to grab it.

my $output = `rsh myserver $command`;
die "Can't create child: $!\n if $? < 0;
die "Child killed by signal ".($? & 0x7F)."\n" if $? & 0x7F;
die "Child exited with exit code".($? >> 8)."\n" if $? >> 8;
print($output);

It also means you are now free to capture the remote program's output without interference.


Problem 2

The contents of $command are going to be interpolated by both the local shell and the remote shell. For example, if $command contains echo *, it will list the local files instead of the remote ones. Some escaping is needed.

Solution
use String::ShellQuote qw( shell_quote );

my $local_command = shell_quote('rsh', 'myserver', $command);
my $output = `$local_command`;
die "Can't create child: $!\n if $? < 0;
die "Child killed by signal ".($? & 0x7F)."\n" if $? & 0x7F;
die "Child exited with exit code".($? >> 8)."\n" if $? >> 8;
print($output);

Need Your Help

Texture Mapping is reversed! Java3D

java 3d java-3d texture-mapping

I could use some extra eyes to help me see why my texture map is reversed on my object. It prints backwards -- as if seeing it in a mirror. I had suspected that maybe reversing the indices would ...

Merge two classes background image for one element

html css css3 background

I am trying to add two classes to one element with two different background images positioned on its different space. But when I apply another class it is overriding first class background image. See

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.