这有点难以解释,所以我提前道歉。
我有一个用Python编写的命令行应用程序。它记录stderr和stdout;日志过滤器配置如下: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
设置日志记录的函数如下所示:
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
当应用程序被直接调用时,它像我期望的那样工作,即info()
及以下打印到stdout, warn()
及以上打印到stderr。但是,当在bash脚本中执行完全相同的调用时,info和以下内容不会打印到终端,但是stderr仍然按预期工作。我可以让脚本将标准输出(stdout)管道到一个文件,但不能将其管道到终端。知道是怎么回事吗?
EDIT我也应该显示bash脚本。还有一些其他的逻辑与构建Python应用程序的参数有关,但实际的调用是在for
循环的底部附近。请注意,Python应用程序是一个可执行模块。
#!/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
问题在这一行
`$cmd`
bash中的反号表示将标准输出重定向到内部bash缓冲区,您可以将其包含在另一个命令中或分配给bash变量。只要省略反引号,它就会按照您的期望运行。
我认为问题出在python脚本的调用上。通过将$cmd
放在刻度中,您告诉bash将程序的stdout
输出作为bash命令运行。这是我能想到的最简单的情况
echo 'import sys
sys.stdout.write(str(1))
sys.stderr.write(str(2))' > test.py
cmd='python test.py'
现在我们可以尝试用不同的方式调用
# 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`