我有一个以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,如果这可能很重要。
答案 0 :(得分:1)
设置该用户的所有环境变量
通常因为shell在启动时运行.profile
文件。
你有几个选择。
使用subprocess.Popen
创建一个合适的子流程来执行shell .profile
- 与su -
相同。
仔细找到环境变量设置并在Python中模仿它们。问题是.profile
可以做各种疯狂的事情,这使得确定.profile
的确切影响成为潜在的问题。
或者您可以提取相关的环境变量,以使shell环境和Python程序都可以访问。
首先。阅读每个用户的.profile
以清楚它设置的环境变量(不同于别名或其他不适用于您的Python脚本的疯狂)。其中一些环境变量与您正在运行的脚本相关。有些不相关。
二。将“相关”环境变量拆分为整齐的env_backups.sh
脚本或env_uploads.sh
脚本。
获得这些环境变量脚本后,请更新.profile
文件,将source env_backup.sh
或source env_uploads.sh
替换为环境变量设置。
第三。在运行Python程序之前,请获取相关的env_this
和env_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