2010-08-20 2 views
4

У меня есть сценарий резервного копирования bash, выполняемый как root (cron), который делегирует определенные задачи другим скриптам bash, принадлежащим разным пользователям. (Упрощенный пример, принцип, некоторые вещи, которые нужно сделать в корне различные задачи делегируются для пользователей с соответствующей средой (оракула, амазонка, ...)Настройка среды при изменении на другого пользователя

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 

Этот скрипт сам делает то некоторые задачи, пользователь оракул:

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

когда я пытаюсь имитировать это поведение в Python я придумал следующее (начал с хрон как корень)

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)" 
         ]) 

в Баш при использовании су -, вызывается реальная новая оболочка и устанавливаются все переменные среды этого пользователя. Как я могу улучшить это для моего скрипта python? Есть ли стандартный рецепт, которым я могу следовать? Я думаю о переменных окружения, umask, ...

Окружающая среда Solaris, если это может иметь значение.

ответ

1

все переменные окружения этого пользователя установлены

Обычно, потому что оболочка запускает .profile файл при запуске.

У вас есть несколько вариантов.

  1. Создание надлежащего подпроцесс с subprocess.Popen выполнить оболочку .profile - такой же, как su -.

  2. Осторожно найдите параметры переменной окружения и имитируйте их в Python. Проблема в том, что .profile может делать всевозможные сумасшедшие вещи, что делает его потенциальной проблемой для определения точных эффектов .profile.

  3. Или вы можете извлечь соответствующие переменные среды, чтобы сделать доступными как среду оболочки, так и ваши программы Python.

Первый. Прочитайте .profile для каждого пользователя, чтобы быть понятным, какие переменные среды он устанавливает (отличные от таких вещей, как псевдонимы или другие сумасшествия, которые не относятся к вашему сценарию Python). Некоторые из этих переменных среды относятся к сценариям, которые вы используете. Некоторые из них не актуальны.

Второй. Разделите «соответствующие» переменные окружения на аккуратный сценарий env_backups.sh или env_uploads.sh.

После того, как у вас есть эти сценарии переменных среды, обновите файлы .profile, чтобы заменить параметры переменных окружения source env_backup.sh или source env_uploads.sh.

В-третьих. Отправьте соответствующие сценарии env_this и env_that перед запуском программы Python. Теперь ваша среда Python разделяет переменные с оболочкой, и вы поддерживаете их только в одном месте.

my_script.sh

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

Это кажется мне лучшим. (Так как мы это делаем.)

+0

Что касается (1), вы можете выполнить .profile как подпроцесс целый день, и это не будет изменять окружение родителя - на самом деле это не вариант. (3) лучше, но страдает от потенциальной проблемы, что переменные окружения оракула могут быть перезаписаны амазонами. – bstpierre

+0

(3) не создает разделение пользовательских окружений: при запуске части оракула ключи амазонки также находятся в окружении – Joram

+0

@ Джорам: Итак? Какая проблема? –

0

Я могу запустить амазонку как root, не требуя при этом переменных окружения. Я использовал boto для этого.

Что касается переменных окружения оракула я использовал этот кусок кода:

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 
Смежные вопросы