LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-30-2011, 06:23 AM   #1
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Rep: Reputation: 447Reputation: 447Reputation: 447Reputation: 447Reputation: 447
Perl newbie question about system command


Hi

I am trying to fix a perl script, and I really suck at perl. But I think this problem will be easy for people who know it.

The problem is, I have an old setup script someone wrote many years ago. It fails if the standard shell is dash and not bash. The only way I've gotten it to work is to point /bin/sh to bash. I looked thru the script and it uses "system" many places, and I think that's the problem.

I searched for it and found this link:

http://stackoverflow.com/questions/5...n-perls-system

My plan is to include this function:

Code:
sub system_bash {
  my @args = ( "bash", "-c", shift );
  system(@args);
}
Then I could simply change all calls to system into system_bash and it should work?

The parameter to the system calls is usually some variable. What if the parameter is a list already? Do I need to test for it somehow, and if it's a list, prepend "bash" and "-c" to the list? How do I do that?

In the script there are lots of places like this:

my $error = system($cmd);
if ($error) {
die/warn "some error message";
}

Shouldn't there be a return in the system_bash function?
 
Old 06-30-2011, 09:29 AM   #2
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
My first instinct would be to stop using 'system()' if it has any dependency on a particular shell, and since anything you can do with Bash you can probably do easier & better with Perl. If it needs to call other stand-alone applications, these can be invoked from Perl in any number of ways.
I haven't tried this, but you may be able to coerce Perl to use Bash by default in system() calls, simply by setting the $SHELL environment variable to "bash".

--- rod.
 
Old 06-30-2011, 10:01 AM   #3
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Original Poster
Rep: Reputation: 447Reputation: 447Reputation: 447Reputation: 447Reputation: 447
The problem is that the script is long and complicated - reading lots of config files and things. The person who wrote it was fairly good at Perl, so I figured he didn't use system if it was uneccessary. But when he wrote it, there was no dash, and as I said, if bash is standard shell, it works fine.

Setting $SHELL in the script doesn't seem to work. I tried this code:

Code:
$SHELL = "bash";
my $cmd = 'for (( i=1 ; i<=10 ; i++ )) ; do echo $i ; done';
system($cmd);
This too works fine if /bin/sh points to bash, but not when it's dash. Or does Perl need something like export? It looks like "/bin/sh" is hard-coded in Perl somewhere.
 
Old 06-30-2011, 10:29 AM   #4
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Quote:
Originally Posted by Guttorm View Post
This too works fine if /bin/sh points to bash, but not when it's dash. Or does Perl need something like export? It looks like "/bin/sh" is hard-coded in Perl somewhere.
Yes, it looks like it. I just tried invoking perl from a csh commandline, with $SHELL set to 'csh', and it still invoked dash (Debian). Sorry to have sent you on a tangent.

Incidently, setting environment variables in Perl is done by writing to the %ENV hash.
Code:
$ENV{"ABCDEF"}='qwerty';
--- rod.
 
Old 06-30-2011, 11:07 AM   #5
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Guttorm View Post
...
Then I could simply change all calls to system into system_bash and it should work?
...
Why do you think so ? I.e. suppose you have a 'foo.sh' script which somewhere inside has

Code:
...
/path/to/bar.sh SOME_ARGS
...
, and 'bar.sh' begins with typical

Code:
#!/bin/sh
, but still expects 'bash' and not 'dash'. So, regardless of what you do in Perl, 'bar.sh' won't work because your '/bin/sh' is 'dash' and not 'bash'.
 
Old 06-30-2011, 11:11 AM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Guttorm View Post
The problem is that the script is long and complicated - reading lots of config files and things. The person who wrote it was fairly good at Perl, so I figured he didn't use system if it was uneccessary. But when he wrote it, there was no dash, and as I said, if bash is standard shell, it works fine.

Setting $SHELL in the script doesn't seem to work. I tried this code:

Code:
$SHELL = "bash";
my $cmd = 'for (( i=1 ; i<=10 ; i++ )) ; do echo $i ; done';
system($cmd);
This too works fine if /bin/sh points to bash, but not when it's dash. Or does Perl need something like export? It looks like "/bin/sh" is hard-coded in Perl somewhere.
First of all, you are doing it wrong - see a post above about '%ENV'; secondly, according to my experiments, Perl ignores $SHELL - it looks like '/bin/sh' is hard-coded into it. I am not even sure this can be changed when Perl is built from sources, but one can find '/bin/sh' in whatever Perl source files and replace it with desired path to shell.
 
Old 06-30-2011, 12:17 PM   #7
Guttorm
Senior Member
 
Registered: Dec 2003
Location: Trondheim, Norway
Distribution: Debian and Ubuntu
Posts: 1,453

Original Poster
Rep: Reputation: 447Reputation: 447Reputation: 447Reputation: 447Reputation: 447
Good point Sergei. I grepped a bit in the code without finding anything. And the script is meant to setup/upgrade some software, and I searched thru it without finding any shell scripts. There is no mention of "bash" or "bin/sh" anywhere. But there are some use of open, and I think some of them can be like popen, so I will have to look thru those.

But back to that system_bash function. Is there anyway to make it accept a list as parameter instead of just a string? I tried this, but it doesn't work:

Code:
sub system_bash {
  my @args = ( "bash", "-c", shift );
  return system(@args);
}

my @cmd = ("echo", "1", "2", "3");
my $retcode = system_bash(@cmd);
 
Old 06-30-2011, 05:52 PM   #8
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by Guttorm View Post
... Is there anyway to make it accept a list as parameter instead of just a string? ...
There is - read 'perldoc perlsub' paying special attention to '@_' (without the quotes).
 
Old 06-30-2011, 08:43 PM   #9
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
It is easy enough to just use join() to make a whitespace delimited string.
Code:
sub system_bash {
  my @args = ( "bash", "-c", shift );
  return system( join( " ", @args ) );
}
I'm glad Sergei was able to confirm that modifying $ENV{"SHELL"} doesn't affect how Perl loads a shell; I thought I had gone a bit soft in the head. Still seems an odd and counter-intuitive behavior.

One could manufacture their own system() function clone, but I wouldn't do it the way the OP suggested, since that appears to make the problem recursive. My solution, if I had to use system() at all (and I never prefer to), would be to use a fork() + exec() + wait(). From what I've observed, most/many people use system(), which loads a shell in order to simply load some other program which could have been loaded directly. If you really do need bash instead of dash, you can launch it this way.

Code:
sub mySystem{

    if(  my $childPid = fork() ){
        wait;
    }
    else{
        exec( @_ );
    }
}
--- rod.

Last edited by theNbomr; 06-30-2011 at 08:45 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Use of "Command line perl" in perl script using system command. aditya007 Linux - Newbie 4 11-29-2009 10:08 PM
perl script system() only execute one command knockout_artist Programming 4 11-11-2008 10:57 AM
Perl problems with system command AgentRn007 Linux - General 1 05-24-2006 12:08 AM
perl's system() command paul_mat Linux - Software 3 11-21-2005 01:37 AM
Help with System() command on linux PERL I R J Programming 2 01-05-2005 12:20 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:46 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration