繁体   English   中英

bash shellshock更新导致脚本行为不同

[英]bash shellshock update causing script to behave differently

这是自更新bash以来发生的事情之一(由于Shellshock的原因)

这是我正在测试的代码:

#!/usr/bin/python2.4
import subprocess, os
    p = subprocess.Popen(
            cmd,        
            shell = True,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE
        )
        out, err = p.communicate()

        print "out:", out
        print "err:", er

首先运行命令:

cmd = "cd /home/me/; pwd; p4 client -o"
out: /home/me/
err:
perforce client that is NOT mine ( some kind of a default template is trying to be used here )

第二个测试,我添加了以下Python参数:

env = os.environ.copy()
# and add "env" variable to the Popen command after "cmd, like:
env = env,

输出:

cmd = "cd /home/me/; pwd; p4 client -o"
out: /home/me/
err:
my perforce client information - as it should.

我的问题是,我似乎无法理解为什么“ env = env”在这里很重要。 我尝试运行几个命令,例如“ export”等,以了解使用/不使用它的区别-但结果是相同的,还检查了“ shell”是否都使用“ sh”。 因此,我不太确定环境的哪一部分会导致其无法正常工作,例如示例1。

我确定它与Perforce本身并没有真正的关系,Perforce可能只需要一些环境变量,由于bash Shellshock的问题,该变量会以某种方式受到影响。

编辑-澄清@ 5gon12eder建议

我尝试不使用“ env = env”(是os.environ.copy())查看ENV,

# 1
# The outouput is wrong ( generic Perforce views )
cd /home/me/; pwd; p4 client -o

# 2 - manually adding P4CONFIG
# The outouput is *correct*
cd /home/me/; pwd; P4CONFIG='.perforce'; p4 client -o


# But the environment variable looks like is there with the correct information ( can't paste it here )
subprocess.call("env") | grepping the script's output P4
> P4CONFIG=...
> P4PORT=...
> P4USER ...

注意,P4变量配置了两次:

/etc/profile
/home/me/.bash_profile

编辑2-以及用Perl复制:

环境将忽略%ENV中的P4CONFIG条目。

#!/usr/bin/perl -w

use strict;
use Data::Dumper;

my $dir = "/home/me/";
my $cmd1 = "cd $dir; p4 client -o";
my $cmd2 = "cd $dir; P4CONFIG='.perforce'; p4 client -o";

# Scenario 1 - does NOT work ! $ENV does have P4CONFIG with a correct value.  
`$cmd1`;
# ** still wrong result - generic Perforce views

# Scenario 2 - adding P4CONFIG= to the command:
`$cmd2`;
# Correct result - my .perforce client's views.

# Scenario 3 - Adding to the ENV P4CLIENT ( which does not exists in %ENV )
$ENV{'P4CLIENT'} = "my_client_name";
`$cmd1`;    # The one without the P4CONFIG enforcement. - WORK.

编辑3-如果我使用/不使用>>和|,会有区别。

实际上,当考虑它时,整个问题是在我的一个库在上面的子进程(Python)“ cmd”示例中具有“> / dev / null”重定向(导致脚​​本在超时时挂起并退出)时引入的。用“ -o file-output”替换它,问题消失了,但是后来我陷入了这个问题,所以我打开了这篇文章。

# I already found that adding this row - solving the ENV thing ( not really solving ... but )
$ENV{'P4CONFIG'} = ".perforce";

# Work, I see the excepted output
my $bla = `p4 client -o`;

# Doesn't work, script hangs and Perforce exit with a timeout ( like a P4PORT missing error )
# (I was just trying to remove all the comments-junk )
my $bla = `p4 client -o | grep -v '^#'`;

# Script doesn't hang for example if I just "echo"
my $bla = `echo 'p4 client bla bla' | grep -v '^#'`;

只是想再说一遍,这一切都在shellshock之前起作用(可能是现实的,也可能是巧合),但是exec()调用的环境有所不同...有什么想法吗?

您的代码是否正在修改环境? 事实是

os.putenv('VAR', 'VAL')

(可能)直接修改环境,但不更新os.environ

os.environ['VAR'] = 'VAL'

确实。 Python文档中

直接调用putenv()不会更改os.environ ,因此最好修改os.environ

如果未提供putenv()则可以将此映射的修改后的副本传递到适当的进程创建函数,以使子进程使用修改后的环境。

从本文档中并不清楚,但是在阅读了os Python模块和随附的posixmodule C模块的源代码后,有些不清楚的是,如果基础平台的C库没有putenv(3) C函数,则进行设置os.environ键仅影响Python词典,而os.putenv是no-op。 Lib/os.py

try:
    _putenv = putenv
except NameError:
    _putenv = lambda key, value: None
else:
    if "putenv" not in __all__:
        __all__.append("putenv")

Modules/posixmodule.c

static PyMethodDef posix_methods[] = {
  /* Lots and lots of code skipped... */
#ifdef HAVE_PUTENV
  {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__},
#endif
  /* Even more code skipped... */
};

出乎我的意料- -因此,你可以在你因为显示了两种情况下观察不同的行为,如果env=None被传递到subprocess.Popen构造,它不能代替os.environ作为默认,但是从使用值C标准库。

设置子进程环境的代码(在Lib/subprocess.py )是

if env is not None:
    env_list = [os.fsencode(k) + b'=' + os.fsencode(v)
                for k, v in env.items()]
    else:
        env_list = None  # Use execv instead of execve.

并且最近没有变化。 exec(3)的手册页中(强调我的):

execvpe() execle()execvpe()函数允许调用者通过参数envp指定执行程序的环境。 envp参数是指向以null终止的字符串的指针的数组,并且必须以null指针终止。 其他功能从调用过程中的外部变量环境获取新过程映像的environ

我走进的源代码Modules/_posixsubprocess.c (用于execv / execve )和Modules/posixmodule.c (用于putenv ),以检查它们是否真的调用系统功能描述和从我可以告诉,他们似乎做所以。 这两个C模块均未收到与该功能有关的最新更改。

读完您的问题后,我的第一个想法是,Python开发人员最终对传递给子流程的环境进行了完整性检查,但似乎没有。 抱歉,如果这不是一个答案,但我认为它可能对其他人仍然有用,可以帮助他们避免陷入CPython源代码。

作为进一步调试的建议,请尝试运行

$ python -c "import os; import subprocess; os.putenv('VAR', 'VAL'); subprocess.call('env');" | grep VAR=

以及各种变化以跟踪发生了什么。

脚注:我认为subprocess.Popen的功能比功能更多,因为它使Python代码在没有putenv理由提供或不提供putenv C函数的平台上表现不同。

因此,我想与所有人分享调查结果,以防其他人暂时陷入困境。 问题是,我们在以下位置具有一些导出功能:

/etc/profile

实施bash修补程序后,这导致环境的行为有所不同。 删除这些功能解决了我们所有脚本中的问题……并且不再需要更改环境变量。

谢谢大家的帮助!

暂无
暂无

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

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