3

I've got this /etc/profile.d/myfile.sh:

export MYVAR=myval

I also have a PassEnv MYVAR line in a <virtualhost> section of an apache conf dir.

That lets me do things like:

$ echo $MYVAR
myval
$ python
>>> import os; os.getenv('MYVAR')
'myval'
$ sudo echo $MYVAR
myval
$ sudo -i
root# echo $MYVAR
myval

But then, despite that being the case I get:

root# /sbin/service httpd restart
/sbin/service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd: [Mon Oct 22 14:44:02 2012] [warn] PassEnv variable MYVAR was undefined
                                                           [  OK  ]

And all of my attempts to access MYVAR from within my wsgi scripts just don't work.

Thoughts? Am I doing something obviously wrong?

EDIT for more detail

I've got a swarm of computers/VMs and a swarm of developers working on a swarm of projects. I need a simple central place to keep environment information, the most common is the "environment" (dev/stage/prod). The scheme that we've got (modifying *.wsgi programmatically) is turning out to be more fragile than we'd like.

The main options that I see are:

  • put things in the shell environment
  • put things in other config files

Getting things into the shell environment is the best, because we won't need to write yet more duplicated "what is my environment" code.

quodlibetor
  • 297
  • 2
  • 4
  • 12
  • 1
    Eight years later, so really only for future readers. `sudo echo $MYVAR` will evaluate `$MYVAR` and _then_ execute the resulting command. In your example it's `myval` so the effect is `sudo echo myval` which I imagine isn't what you'd intended – roaima Jun 25 '20 at 20:10
  • have you found a solution to this? im running into the exact same problem – Paul Ma Nov 02 '22 at 09:57
  • @PaulMa You should ask a new question with specific details. Maybe link to here. This one is already marked as answered so it's not so clear at first sight why the bounty was set. – cachius Nov 04 '22 at 14:13

1 Answers1

2

Apache isn't going to read the global user profile.

The big question is what are you actually wanting to do this for?

What you are doing is generally the wrong way of doing things with Apache, but because don't know the actual problem you are trying to solve, then can't say what you should be doing.

Amend your question and state what environment variables you are trying to set and why.


UPDATE 1

Not specifically what you are doing, but SetEnv in mod_wsgi doesn't set process wide environment variables. It sets per request variables in the WSGI environ dictionary.

PassEnv, which is related to SetEnv, would do the same thing but rather than the key/value being defined in Apache configuration file, it would come from the existing process environment variables that Apache inherited.

So, neither of the directives actually has the effect of setting a process wide environment variable for a WSGI application running under mod_wsgi. IOW, they would not be accessible via os.environ as you seem to want.

Now, for PassEnv specifically, if what you are wanting to do is have Apache process environment variables also be available to a WSGI application under mod_wsgi, then PassEnv is actually redundant as the Apache process environment variables will already be available.

This is because in embedded mode WSGI applications run inside the Apache child worker processes. Even in daemon mode, the daemon process is a direct fork of the Apache parent process (no exec of any separate application) and so is effectively also running inside of Apache.

So, PassEnv is not required as they would already be set.

To do it as you are wanting, you are simply doing it in the wrong place as Apache init.d startup scripts aren't going to source the global user login profile.

If you are using an Apache distribution from the Apache Software Foundation, or one that hasn't deviated to far from it, the correct place to set environment variables for Apache is in the 'envvars' file in same directory as the Apache executable. On various Linux distributions the Apache setup totally ignores that file and instead it is necessary to set them in some special file along with the system specific Apache init.d files. What exactly you have to do there will depend on the Linux distribution.

So as I said, Apache will not read that global profile file.

Doit in the right spot and technically it could work, but relying on setting environment variables which affect the whole of Apache wouldn't be what I would recommend.

You would be better having a WSGI script read a separate config file which sets the system status and then base things of that. Using a config file specifically for the purpose isn't as magic as relying on environment variable settings coming in from a file which isn't specifically part of the project but Apache init scripts.

Graham Dumpleton
  • 6,090
  • 2
  • 21
  • 19
  • 1
    Done, but could you tell my why this is the wrong way to do things with Apache? There's no good way to get correctly set environment variables into Apache wsgi subprocesses? The docs seem to be wrong, because they suggest that not only does it work, it looks easy. – quodlibetor Oct 22 '12 at 22:40
  • If you want to set a specific (system-)enviroment variable in apache, you must set it in the start skript since non-interactive shells do not use /etc/profile*. man bash explains this. If you want an apache-internal enviroment variable you set it in the apache config via SetEnv. All this has nothing to do with mod_wsgi. – tim Oct 22 '12 at 23:57
  • As explained, SetEnv does not set Apache internal process environment variables. SetEnv will only set process environment variables in situations like CGI where spawning a separate process. In mod_wsgi SetEnv variables only get passed across to WSGI per request environ dictionary as everything is already effectively running inside of Apache and you cannot go changing process environment variables on every request when can have multiple threads running in same process handling requests. – Graham Dumpleton Oct 23 '12 at 01:25
  • This is simply not true. See http://httpd.apache.org/docs/2.2/mod/mod_env.html for documentation... – tim Oct 23 '12 at 10:36
  • All I can say is that I have been telling people to put stuff in envvars or appropriate init.d file for years to have environment variables available to Apache and never have had to have someone use PassEnv to do it. I just went and verified it again with an ASF source distribution. The environment variable I set in envvars was automatically available in the environment variables visible to the WSGI script running with mod_wsgi. It was not necessary to use PassEnv. Despite it saying 'which are available to Apache HTTP Server modules', my experience has been that that is relevant only to CGI. – Graham Dumpleton Oct 23 '12 at 11:26
  • Part of the confusion here is perhaps in understanding what SetEnv does. What SetEnv does is set a variable in a dictionary associated with the Apache request structure called subprocess_env. It does not set process wide environment variables for Apache itself. When something like CGI processes are spawned, their process environment variables are copied from the subprocess_env. PassEnv will when a request is run, cause the named process wide variable to be copied to suprocess_env so that CGI processes will pick it up. So Apache internal environment variables means subprocess_env dictionary. – Graham Dumpleton Oct 23 '12 at 12:02
  • In the case of mod_wsgi, the subprocess_env dictionary is used in the per request WSGI environ dictionary, they are not used to set process wide environment variables. When you use PassEnv, the process wide environment variable of Apache ends up getting passed in the WSGI environ dictionary as a result. PassEnv is therefore meaningless if your intent is to have the process wide environment variable end up in WSGI script as it already is, which is what OP was after. So right now I really don't know what you are saying it not true. We obviously mustn't be talking about the same thing. – Graham Dumpleton Oct 23 '12 at 12:08
  • Just to be clear, this answer is both correct and disappointing, and I'm going with the suggestion to put things in a separate file. If the global environment files (profile.d/*.sh were *actually* global, then I'd be much more happy with things. Putting the same config in both `/etc/init.d/envvars` *and* `/etc/profile.d/myenv.sh` doesn't help any thing. – quodlibetor Oct 23 '12 at 17:20