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

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

system('myframework mycode');

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

我做错了什么?

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

【问题讨论】:

    标签: perl shell system


    【解决方案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 qw{mycommand arg1 ...};
      

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

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

      【讨论】:

        【解决方案3】:

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

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

        这也可以:

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

        这不会:

        $ A=5
        $ perl -e 'system(q{echo $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 端口)。然后以下解决了问题:

            $ENV{PERL5SHELL} = "sh";
            

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

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

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

            【讨论】:

              【解决方案6】:

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

              来自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.
              

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

              简单测试:

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

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

              【讨论】:

                【解决方案7】:

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

                【讨论】:

                • 这是错误的。 system 电话不以任何方式、形状或形式尊重 $SHELL。查看马特凯恩的回答
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-12-16
                • 2011-03-29
                • 2011-04-15
                • 2012-10-25
                • 1970-01-01
                • 2018-05-08
                • 1970-01-01
                相关资源
                最近更新 更多