subprocess.run中stdout=outfile对pg_restore无效但对psql有效的原因排查
subprocess.run中stdout=outfile对pg_restore无效但对psql有效的原因排查
这个问题我碰到过好几次啦,核心原因其实和pg_restore本身的输出行为有关,和subprocess的用法关系不大~
1. 关键差异:pg_restore的verbose输出走的是stderr而非stdout
很多命令行工具会做这样的区分:
- 把实际业务数据输出(比如psql的查询结果、命令执行的正常输出)放到
stdout; - 把日志、进度、提示类信息(比如pg_restore的
-vverbose输出)放到stderr。
你用了pg_restore的-v参数,那些打印的恢复进度、表处理信息全都是输出到stderr的,而不是stdout。所以你只指定stdout=outfile自然抓不到这些内容,而psql的常规输出刚好走stdout,所以能被正确捕获。
2. 验证这个结论的小技巧
你可以在终端直接跑一遍pg_restore命令,手动分开重定向stdout和stderr,就能直观看到差异:
/usr/bin/pg_restore -w -v -U user -h host -F d -j 3 -d db directory > stdout_test.log 2> stderr_test.log
打开stderr_test.log,你会发现那些verbose日志全在里面;而stdout_test.log大概率是空的(除非你用-f参数让pg_restore输出备份内容到stdout,但你这里是直接恢复到数据库,所以stdout没有有效输出)。
3. 解决办法:捕获stderr输出
如果你想把pg_restore的verbose信息也写入到outfile里,有两种常用方式:
方式一:把stderr单独写入同一个文件
直接给subprocess.run加上stderr=outfile参数,让stdout和stderr都写到同一个日志文件:
with open("stdout.log", "w") as outfile: subprocess.run( ['/usr/bin/pg_restore', '-w', '-v', '-U', user, '-h', host, '-F', 'd', '-j', '3', '-d', db, directory], stdout=outfile, stderr=outfile, # 同时捕获stderr到文件 text=True, env={'PGPASSFILE': pgpassfile} )
方式二:把stderr合并到stdout后写入文件
如果不需要区分stdout和stderr,可以用stderr=subprocess.STDOUT把两者合并,一起写入文件:
with open("stdout.log", "w") as outfile: subprocess.run( ['/usr/bin/pg_restore', '-w', '-v', '-U', user, '-h', host, '-F', 'd', '-j', '3', '-d', db, directory], stdout=outfile, stderr=subprocess.STDOUT, # 合并stderr到stdout text=True, env={'PGPASSFILE': pgpassfile} )
备注:内容来源于stack exchange,提问作者Linna
相关产品推荐
相关产品推荐

