[英]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的問題,該變量會以某種方式受到影響。
我嘗試不使用“ 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
環境將忽略%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.
實際上,當考慮它時,整個問題是在我的一個庫在上面的子進程(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.