更改为其他用户时设置环境

时间:2010-08-20 08:38:07

标签: python environment-variables setuid

我有一个以root(cron)身份运行的bash备份脚本,它将某些任务委托给不同用户拥有的其他特定bash脚本。 (简单的例子,原则是,有些事情必须以root身份完成,不同的任务被委托给具有适当环境的用户(oracle,amazon,...)

mkdir -p /tmp/backup$NAME
su - oracle -c "~/.backups/export-test.sh"
tar cf /tmp/backup/$NOW.tar /tmp/backup$NAME
su - amazon upload_to_amazon.sh /tmp/backup/$NOW.tar

这个脚本本身就像用户oracle那样执行一些任务:

mkdir -p $TMP_LOCATION
cd ~/.backups
exp $TMP_LOCATION/$NAME-$NOW

当我尝试在python中模仿这种行为时,我想出了以下内容(从cron作为root开始)

name = "oracle"

# part run as root
os.makedirs(tmp_backup + name)


os.setegid(pwd.getpwnam(name)[3])
os.seteuid(pwd.getpwnam(name)[2])

# part run as oracle
os.makedirs(tmp_location)
os.chdir(os.path.expanduser("~{user}/.backups".format(user=name)))
subprocess.check_call(["exp",
                       "os.path.join(tmp_location, name+'-'+now)"
                      ])

在bash中使用su - 时,会调用一个真正的新shell,并设置该用户的所有环境变量。 如何为我的python脚本改进这个?我可以遵循标准配方吗?我正在考虑环境变量,umask,......

环境是Solaris,如果这可能很重要。

2 个答案:

答案 0 :(得分:1)

  

设置该用户的所有环境变量

通常因为shell在启动时运行.profile文件。

你有几个选择。

  1. 使用subprocess.Popen创建一个合适的子流程来执行shell .profile - 与su -相同。

  2. 仔细找到环境变量设置并在Python中模仿它们。问题是.profile可以做各种疯狂的事情,这使得确定.profile的确切影响成为潜在的问题。

  3. 或者您可以提取相关的环境变量,以使shell环境和Python程序都可以访问。

  4. 首先。阅读每个用户的.profile以清楚它设置的环境变量(不同于别名或其他不适用于您的Python脚本的疯狂)。其中一些环境变量与您正在运行的脚本相关。有些不相关。

    二。将“相关”环境变量拆分为整齐的env_backups.sh脚本或env_uploads.sh脚本。

    获得这些环境变量脚本后,请更新.profile文件,将source env_backup.shsource env_uploads.sh替换为环境变量设置。

    第三。在运行Python程序之前,请获取相关的env_thisenv_that脚本。现在,您的Python环境与shell环境共享变量,您只能将它们保存在一个位置。

    my_script.sh

    source ~oracle/env_backup.sh
    source ~amazon/env_uploads.sh
    python my_script.py
    

    这对我来说似乎最好。 (因为我们是这样做的。)

答案 1 :(得分:0)

我可以以root身份运行amazon,毕竟不需要环境变量。 我使用了boto

至于oracle环境变量,我使用了这段代码:

if "ORACLE_HOME" not in os.environ or os.environ["ORACLE_HOME"] != ORACLE_HOME:
    logger.debug("setting ORACLE_HOME='{oh}'".format(oh=ORACLE_HOME))
    os.environ['ORACLE_HOME'] = ORACLE_HOME
if ORACLE_HOME + "/bin" not in os.environ["PATH"].split(":"):
    logger.debug("setting PATH='{p}'".format(p=os.path.expandvars(ORACLE_PATH)))
    os.environ['PATH'] = os.path.expandvars(ORACLE_PATH)
if "NLS_LANG" not in os.environ or os.environ["NLS_LANG"] != NLS_LANG:
    logger.debug("setting NLS_LANG='{n}'".format(n=NLS_LANG))
    os.environ['NLS_LANG'] = NLS_LANG