Which shell does a Perl system() call use?

2020-02-05 18:06发布

I am using a system call to do some tasks

system('myframework mycode');

but it complains of missing environment variables. Those environment variables are set at my bash shell (from where I run the Perl code).

What am I doing wrong?

Does the system call create a brand new shell (without environment variable settings)? How can I avoid that?

7条回答
何必那么认真
2楼-- · 2020-02-05 18:32

I think it's not the question of shell choice, since environment variables are always inherited by subprocesses unless cleaned up explicitly. Are you sure you have exported your variables? This will work:

$ A=5 perl -e 'system(q{echo $A});'
5
$

This will work too:

$ export A=5
$ perl -e 'system(q{echo $A});'
5
$

This wouldn't:

$ A=5
$ perl -e 'system(q{echo $A});'

$
查看更多
乱世女痞
3楼-- · 2020-02-05 18:41

I messed with environment variables being set for my script on this post where I needed the env variable $DBUS_SESSION_BUS_ADDRESS to be set, but it wouldn't when I called the script as root. You can read through that, but in the end you can check whether %ENV contains your needed variables and if not add them.

From perlvar

   %ENV
   $ENV{expr}
           The hash %ENV contains your current environment.  Setting a value in "ENV" changes
           the environment for any child processes you subsequently fork() off.

My problem was that I was running the script under sudo and that didn't preserve all my user's env variables, are you running the script under sudo or as some other user, say www-data (apache)?

Simple test:

user@host:~$ perl -e 'print $ENV{q/MY_ENV_VARIABLE/} . "\n"'

and if that doesn't work then you will need to add it to %ENV at the top of your script.

查看更多
男人必须洒脱
4楼-- · 2020-02-05 18:44

try system("echo \$SHELL"); on your system.

查看更多
The star\"
5楼-- · 2020-02-05 18:45

system() calls /bin/sh as a shell. If you are on a somewhat different box like ARM it would be good to read the man page for the exec family of calls -- default behavior. You can invoke your .profile if you need to, since system() takes a command

system(" . myhome/me/.profile && /path/to/mycommand")
查看更多
一纸荒年 Trace。
6楼-- · 2020-02-05 18:48

It's complicated. Perl does not necessarily invoke a shell. Perldoc says:

If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp , which is more efficient.

So it actually looks like you would have the arguments passed right to execvp. Furthermore, whether the shell loaded your .bashrc, .profile, or .bash_profile depends on whether the shell is interactive. Likely it isn't, but you can check like this.

查看更多
兄弟一词,经得起流年.
7楼-- · 2020-02-05 18:56

If you don't want to invoke a shell, call system with a list:

system 'mycommand', 'arg1', '...';
system qw{mycommand arg1 ...};

If you want a specific shell, call it explicitly:

system "/path/to/mysh -c 'mycommand arg1 ...'";
查看更多
登录 后发表回答