简体   繁体   English

Perl system()调用使用哪个shell?

[英]Which shell does a Perl system() call use?

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). 那些环境变量是在我的bash shell中设置的(从那里我运行Perl代码)。

What am I doing wrong? 我究竟做错了什么?

Does the system call create a brand new shell (without environment variable settings)? system调用是否会创建一个全新的shell(没有环境变量设置)? How can I avoid that? 我怎么能避免这种情况?

It's complicated. 情况很复杂。 Perl does not necessarily invoke a shell. Perl不一定会调用shell。 Perldoc says: Perldoc说:

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). 如果只有一个标量参数,则检查参数是否为shell元字符,如果有,则将整个参数传递给系统的命令shell进行解析(这在Unix平台上是/ bin / sh -c,但在其他平台)。 If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp , which is more efficient. 如果参数中没有shell元字符,则将其拆分为单词并直接传递给execvp,这样效率更高。

So it actually looks like you would have the arguments passed right to execvp. 所以它实际上看起来你会将参数传递给execvp。 Furthermore, whether the shell loaded your .bashrc, .profile, or .bash_profile depends on whether the shell is interactive. 此外,shell是否加载了.bashrc,.profile或.bash_profile取决于shell是否是交互式的。 Likely it isn't, but you can check like this . 可能它不是,但你可以像这样检查。

If you don't want to invoke a shell, call system with a list: 如果您不想调用shell,请使用列表调用system

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

If you want a specific shell, call it explicitly: 如果需要特定的shell,请明确调用它:

system "/path/to/mysh -c 'mycommand arg1 ...'";

I think it's not the question of shell choice, since environment variables are always inherited by subprocesses unless cleaned up explicitly. 我认为这不是shell选择的问题,因为除非明确地清除,否则环境变量总是由子进程继承。 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});'

$

I've struggled for 2 days working on this. 我在这方面努力了2天。 In my case, environment variables were correctly set under linux but not cygwin. 在我的例子中,环境变量在linux下正确设置但不是cygwin。

From mkb's answer I thought to check out man perlrun and it mentions a variable called PERL5SHELL ( specific to the Win32 port ). mkb的回答我想看看man perlrun ,它提到了一个名为PERL5SHELL的变量( 特定于Win32端口 )。 The following then solved the problem: 接下来解决了这个问题:

$ENV{PERL5SHELL} = "sh";

As is often the case - all I can really say is "it works for me", although the documentation does imply that this might be a sensible solution: 通常情况下 - 我只能说“它对我有用”,尽管文档确实暗示这可能是一个明智的解决方案:

May be set to an alternative shell that perl must use internally for executing "backtick" commands or system(). 可以设置为perl必须在内部用于执行“反引号”命令或system()的备用shell。

If the shell used by perl does not implicitly inherit the environment variables then they will not be set for you. 如果perl使用的shell没有隐式继承环境变量,那么就不会为它们设置它们。

system() calls /bin/sh as a shell. system()调用/ bin / sh作为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. 如果你在一个像ARM这样有点不同的盒子上,最好阅读exec系列调用的手册页 - 默认行为。 You can invoke your .profile if you need to, since system() takes a command 如果需要,可以调用.profile,因为system()接受命令

system(" . myhome/me/.profile && /path/to/mycommand")

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. 我在这篇文章中为我的脚本设置了环境变量,我需要设置env变量$ DBUS_SESSION_BUS_ADDRESS,但是当我以root身份调用脚本时它不会。 You can read through that, but in the end you can check whether %ENV contains your needed variables and if not add them. 您可以仔细阅读,但最后您可以检查%ENV是否包含您需要的变量,如果不包含它们。

From perlvar 来自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)? 我的问题是我在sudo下运行脚本并且没有保留我所有用户的env变量,你是在sudo下运行脚本还是像其他用户一样运行,比如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. 如果这不起作用,那么你需要将它添加到脚本顶部的%ENV。

try system("echo \\$SHELL"); 试试system("echo \\$SHELL"); on your system. 在你的系统上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM