Stephen Cattaneo wrote:Because $HOSTNAME is a bash specific variable, set by bash but NOT>I am attempting to execute an automated test (written in Python) via
cron. I have to check the HOSTNAME variable as part of the test, oddly
under cron the HOSTNAME environment variable is not in the os.environ
dictionary. I know that cron runs in a subshell that does not have all
of the normally set environment variables. HOSTNAME is not one of those
variables, it is set even in cron's subshell. Why doesn't python get
this variable? Is this a bug in python2.4?
EXPORTED! Like $0 and a bunch of other "private" variables, subprocesses
do not inherit this value. From "man bash":
Shell Variables
The following variables are set by the shell:
[...]
HOSTNAME
Automatically set to the name of the current host.
Note that "set" does not imply "exported". Only exported vairables are
seen by subprocesses.
Cron doesn't normally use a shell at all. It just runs theThis statement is false.
requested program in a subprocess. So there's no shell involved,
and you don't get a shell-type user environment.
Cron hands _all_ jobs to a shell. From "man 5 crontab":
The ``sixth'' field (the rest of the line) specifies the command to be
run. The entire command portion of the line, up to a newline or % char-
acter, will be executed by /bin/sh or by the shell specified in the SHELL
variable of the cronfile.
That's from Vixie cron, but all UNIX crons hand the command part of the
cron line to a shell, usually /bin/sh.
You're probably confused by the fact that cron does not invoke "login" shells
(with their associated initialisation from /etc/profile and $HOME/.profile).
If you haveNot so. A shell will be interpreting the string "/usr/bin/python
a crontab line like
10 3 * * * /usr/bin/python someprogram.py
there's no shell.
someprogram.py", mch as happens when you type this on the command line.
You can tryEven more not so. The command "/bin/sh /usr/bin/python someprogram.py"
10 3 * * * /bin/sh /usr/bin/python someprogram.py
which will load a shell, which in turn will load Python.
will attempt to parse the file "/usr/bin/python" as though it were a
shell script. That's almost certainly not what you wanted.
To do what you describe requires the line:
/bin/sh -c '/usr/bin/python someprogram.py'
which hands the command string "/usr/bin/python someprogram.py" to
/bin/sh for interpretation. Were you to do this as a cron line, the
string: "/bin/sh -c '/usr/bin/python someprogram.py'" would be handed
to /bin/sh for interpretation. That interpreter in turn then hands
"/usr/bin/python someprogram.py" to /bin/sh for interpretation.
A parent-child nested process listing (with some fake quoting tossed in
to show the strings) would look like this:
/bin/sh -c "/bin/sh -c '/usr/bin/python someprogram.py'"
/bin/sh -c '/usr/bin/python someprogram.py'
/usr/bin/python someprogram.py
i.e. three process alive.
Or, in Python, you can use "socket.gethostname()", which willOr, on a cron line (after the time fields, omitted here):
get you the host name used for networking purposes.
HOSTNAME=`hostname`; export HOSTNAME; python someprogram.py
Cheers,
--
Cameron Simpson <cs@zip.com.auDoD#743
http://www.cskk.ezoshosting.com/cs/
186,282 miles per second - Not just a good idea, It's the Law!