簡體   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