2010-08-20 7 views
4

J'ai un script de sauvegarde bash exécuté en tant que root (cron) qui délègue certaines tâches à d'autres scripts bash spécifiques appartenant à différents utilisateurs. (Exemple simplifié, le principe est, certaines choses doivent être faites en tant que root, différentes tâches sont déléguées aux utilisateurs avec l'environnement approprié (oracle, amazone, ...)Configuration de l'environnement lors de la modification d'un autre utilisateur

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 

Ce script se fait alors quelques tâches utilisateur oracle:

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

lorsque je tente d'imiter ce comportement en python je suis venu avec les éléments suivants (démarré à partir cron en tant que 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)" 
         ]) 

en bash lors de l'utilisation su -, un Un nouveau shell réel est appelé et toutes les variables d'environnement de cet utilisateur sont définies. Comment puis-je améliorer cela pour mon script python? Y a-t-il une recette standard que je peux suivre? Je pense à des variables d'environnement, umask, ...

l'environnement est Solaris si cela peut avoir de l'importance.

Répondre

1

toutes les variables d'environnement de l'utilisateur sont définies

Habituellement parce qu'un shell exécute un fichier .profile lors de son démarrage.

Vous avez plusieurs choix.

  1. Créer un sous-processus approprié avec subprocess.Popen pour exécuter le shell .profile - même que su -.

  2. Recherchez avec précaution les paramètres de variable d'environnement et imitez-les en Python. Le problème est qu'un .profile peut faire toutes sortes de choses folles, ce qui en fait un problème potentiel pour déterminer les effets exacts du .profile. Ou vous pouvez extraire les variables d'environnement pertinentes pour les rendre accessibles à la fois à l'environnement shell et à vos programmes Python.

Premier. Lisez le .profile pour que chaque utilisateur soit clair sur les variables d'environnement qu'il définit (différentes des choses comme les alias ou autres folies qui ne s'appliquent pas à votre script Python). Certaines de ces variables d'environnement sont pertinentes pour les scripts que vous utilisez. Certains ne sont pas pertinents.

Deuxième. Divisez les variables d'environnement "pertinentes" en un script env_backups.sh ou env_uploads.sh bien rangé. Une fois que vous avez ces scripts de variable d'environnement, mettez à jour vos fichiers .profile pour remplacer les paramètres de variables d'environnement par source env_backup.sh ou source env_uploads.sh.

Troisième. Source les scripts pertinents env_this et env_that avant d'exécuter le programme Python. Maintenant, votre environnement Python partage les variables avec votre environnement shell et vous ne les maintenez que dans un seul endroit.

mon_script.sh

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

Cela me semble le mieux. (Puisque c'est ainsi que nous le faisons.)

+0

En ce qui concerne (1), vous pouvez exécuter .profile comme un sous-processus toute la journée et il ne modifiera pas l'environnement du parent - Ce n'est pas vraiment une option. (3) est meilleur, mais souffre du problème potentiel que les variables d'environnement d'Oracle peuvent être remplacées par celles d'Amazon. – bstpierre

+0

(3) ne donne pas la séparation des environnements utilisateur: lors de l'exécution de la partie oracle, les clés amazon sont également dans l'environnement – Joram

+0

@Joram: Alors? Quel problème cela cause-t-il? –

0

Je peux exécuter amazon en tant que root, sans avoir besoin de variables d'environnement après tout. J'ai utilisé boto pour cela.

En ce qui concerne les variables d'environnement Oracle J'ai utilisé ce morceau de code:

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 
Questions connexes