Reputation: 485
This is a little tricky to explain, so I apologize in advance.
I have a command line application written in Python. It logs to stderr and stdout; the logging filters are configured as follows:
class StdErrFilter(logging.Filter):
def filter(self,record):
return 1 if record.levelno >= 30 else 0
class StdOutFilter(logging.Filter):
def filter(self,record):
return 1 if record.levelno <= 20 and record.levelno > 10 else 0
and the function that sets up logging looks like this:
def setup_logging(logger_name):
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(fmt=LOG_FMT)
err_handler = logging.StreamHandler(sys.__stderr__)
err_handler.addFilter(StdErrFilter())
err_handler.setFormatter(formatter)
logger.addHandler(err_handler)
out_handler = logging.StreamHandler(sys.__stdout__)
out_handler.addFilter(StdOutFilter())
out_handler.setFormatter(formatter)
logger.addHandler(out_handler)
return logger
When the application is invoked directly it works as I'd expect, i.e. info()
and below print to stdout, and warn()
and above print to stderr. However, when the exact same call is made inside a bash script, info and below don't print to the terminal, but stderr still works as expected. I can make the script pipe stdout to a file, but not to the terminal. Any ideas what's going on?
EDIT I should have shown the bash script as well. There's some other logic related to the building the args for the Python app in there, but the actual call is near the bottom in the for
loop. Note that the Python app is an executable module.
#!/bin/bash
# provide one argument, the directory to search for ".xml" files.
dir_to_index=$1
FIND=/usr/bin/find
PYTHON=/usr/bin/python
SOLR="http://localhost:8983/solr/pul-development"
BIN="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
marc_to_solr=$BIN/../marc_to_solr
PYTHONPATH=$marc_to_solr:$PYTHONPATH
db_config=$BIN/../etc/database.ini
config=db_config=$BIN/../etc/config.ini
for f in `$FIND $dir_to_index -name "*.xml"`; do
echo "File: $f"
cmd="$PYTHON -m marc_to_solr -d $db_config -s $SOLR -c etc/config.ini -i $f"
`$cmd`
done
Upvotes: 1
Views: 3060
Reputation: 3493
I believe the problem lies in the invocation of your python script. By placing $cmd
within the ticks, you're telling bash to run the stdout
output of the program as a bash command. This is the simplest case I could contrive
echo 'import sys
sys.stdout.write(str(1))
sys.stderr.write(str(2))' > test.py
cmd='python test.py'
And now we can try invoking it a couple different ways
# If you invoke it like this, it works fine
$cmd
# And this will work, too
bash -c "$cmd"
# If you invoke it like this, you'll get some complaints
`$cmd`
Upvotes: 2
Reputation: 176
The problem is in the line
`$cmd`
Backticks in bash mean to redirect stdout to an internal bash buffer that you can include in another command or assign to a bash variable. Just omit the backticks and it will do what you expect.
Upvotes: 2