4

我有一个 bash 备份脚本以 root (cron) 身份运行,它将某些任务委托给不同用户拥有的其他特定 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。

4

2 回答 2

1

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

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

你有几个选择。

  1. 创建一个适当的子进程subprocess.Popen来执行 shell .profile- 与su -.

  2. 仔细定位环境变量设置并在 Python 中模仿它们。问题在于,a.profile可以做各种疯狂的事情,这使得确定.profile.

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

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

第二。将“相关”的环境变量拆分成一个整洁的env_backups.sh脚本或env_uploads.sh脚本。

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

第三。在运行 Python 程序之前获取相关env_this和脚本。env_that现在,您的 Python 环境与您的 shell 环境共享变量,您只需将它们维护在一个地方。

我的脚本.sh

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

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

于 2010-08-20T10:26:24.497 回答
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
于 2011-12-02T08:10:19.793 回答