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

Posted

技术标签:

【中文标题】Perl system() 调用使用哪个 shell?【英文标题】:Which shell does a Perl system() call use? 【发布时间】:2011-05-12 15:00:28 【问题描述】:

我正在使用系统调用来完成一些任务

system('myframework mycode');

但它抱怨缺少环境变量。 这些环境变量是在我的 bash shell 中设置的(从我运行 Perl 代码的地方)。

我做错了什么?

system 调用是否创建了一个全新的 shell(没有环境变量设置)?我怎样才能避免这种情况?

【问题讨论】:

【参考方案1】:

这很复杂。 Perl 不一定调用 shell。 Perldoc 说:

如果只有一个标量参数,则检查参数是否有 shell 元字符,如果有,则将整个参数传递给系统的命令 shell 进行解析(在 Unix 平台上是 /bin/sh -c,但在其他平台上有所不同)。如果参数中没有shell元字符,则将其拆分为单词并直接传递给 execvp ,这样效率更高。

所以实际上看起来你会将参数直接传递给 execvp。此外,shell 是否加载了您的 .bashrc、.profile 或 .bash_profile 取决于 shell 是否是交互式的。可能不是,但您可以查看 this。

【讨论】:

【参考方案2】:

如果您不想调用 shell,请使用列表调用 system

system 'mycommand', 'arg1', '...';
system qwmycommand arg1 ...;

如果你想要一个特定的 shell,显式调用它:

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

【讨论】:

【参考方案3】:

我认为这不是 shell 选择的问题,因为环境变量总是由子进程继承,除非明确清理。 你确定你已经导出了你的变量吗? 这将起作用:

$ A=5 perl -e 'system(qecho $A);'
5
$

这也可以:

$ export A=5
$ perl -e 'system(qecho $A);'
5
$

这不会:

$ A=5
$ perl -e 'system(qecho $A);'

$

【讨论】:

【参考方案4】:

system() 将 /bin/sh 作为 shell 调用。如果您使用的是 ARM 等稍微不同的机器,最好阅读 exec 系列调用的手册页——默认行为。如果需要,您可以调用您的 .profile,因为 system() 需要一个命令

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

【讨论】:

【参考方案5】:

我为此苦苦挣扎了 2 天。就我而言,环境变量在 linux 下正确设置,但在 cygwin 下没有。

来自mkb's 的答案我想看看man perlrun,它提到了一个名为PERL5SHELL 的变量(特定于Win32 端口)。然后以下解决了问题:

$ENVPERL5SHELL = "sh";

通常情况下 - 我只能说“它对我有用”,尽管文档确实暗示这可能是一个明智的解决方案:

可以设置为 perl 必须在内部用于执行“反引号”命令或 system() 的替代 shell。

如果 perl 使用的 shell 没有隐式继承环境变量,那么它们不会为你设置。

【讨论】:

【参考方案6】:

我弄乱了在this post 上为我的脚本设置的环境变量,我需要设置环境变量$DBUS_SESSION_BUS_ADDRESS,但是当我以root 身份调用脚本时它不会。您可以通读它,但最后您可以检查 %ENV 是否包含您需要的变量,如果没有则添加它们。

来自perlvar

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

我的问题是我在 sudo 下运行脚本并且没有保留我所有用户的环境变量,您是在 sudo 下运行脚本还是作为其他用户运行脚本,比如 www-data (apache)?

简单测试:

user@host:~$ perl -e 'print $ENVq/MY_ENV_VARIABLE/ . "\n"'

如果这不起作用,那么您需要将其添加到脚本顶部的 %ENV。

【讨论】:

【参考方案7】:

在您的系统上尝试system("echo \$SHELL");

【讨论】:

这是错误的。 system 电话不以任何方式、形状或形式尊重 $SHELL。查看马特凯恩的回答

以上是关于Perl system() 调用使用哪个 shell?的主要内容,如果未能解决你的问题,请参考以下文章

通过从perl脚本调用的批处理文件设置环境变量

Perl和操作系统交互:systemexec和反引号

对 system() 的调用不会在我的 Windows 进程之间创建父子关系

perl 系统调用无法识别路径

Perl系统调用mplayer,视频之间的过渡不同

从 Perl 调用命令,需要查看输出