Python subprocess stdin传递PostgreSQL密码失败问题求助
解决pg_dump通过stdin传递密码失败的问题
我懂你现在的困扰——明明用popen.stdin.write()把密码写进去了,pg_dump就是不买账,对吧?这其实是因为pg_dump默认不会从标准输入读取密码,它优先找终端交互,或者用环境变量、pgpass配置文件这些方式来获取密码。
为什么你的原代码不生效?
pg_dump的密码输入逻辑是和终端(tty)绑定的,不是普通的标准输入流。所以哪怕你通过stdin.write()把密码传进去,它也不会读取这部分内容,还是会等着从终端输入,这就是为什么你的代码没效果。
可行的解决方案
1. 使用PGPASSWORD环境变量(快速临时方案)
你可以把密码放到PGPASSWORD环境变量里,pg_dump会自动读取这个变量的值作为密码。这种方式不用改太多代码,适合临时测试:
import gzip import subprocess import os # 复制系统原有环境变量,避免破坏其他配置 env_vars = os.environ.copy() # 添加PGPASSWORD变量 env_vars['PGPASSWORD'] = 'rootVidhyaDhan123#!' with gzip.open('backup.gz', 'wb') as f: popen = subprocess.Popen( ['pg_dump', '--no-owner', '--no-acl', '-U', 'postgres', '-d', 'database_name', '-h', '178.111.11.111'], stdout=subprocess.PIPE, universal_newlines=True, env=env_vars # 传入带密码的环境变量 ) # 不需要sleep和stdin.write了 for stdout_line in iter(popen.stdout.readline, ""): f.write(stdout_line.encode('utf-8')) popen.stdout.close() popen.wait()
2. 使用.pgpass配置文件(推荐,更安全)
硬编码密码在脚本里不安全,推荐用PostgreSQL的pgpass文件来管理密码,这样脚本里完全不用出现密码:
创建pgpass文件:
- Linux/macOS:在用户主目录下创建
.pgpass文件,内容格式为:
格式说明:178.111.11.111:5432:database_name:postgres:rootVidhyaDhan123#!主机名:端口:数据库名:用户名:密码(端口默认5432,如果你改了就填实际端口) - Windows:在
%APPDATA%\postgresql目录下创建pgpass.conf文件,内容格式和上面一样。
- Linux/macOS:在用户主目录下创建
设置文件权限(仅Linux/macOS需要):
必须把文件权限设为600,确保只有你自己能读取:chmod 600 ~/.pgpass修改后的脚本:
现在脚本里不用处理密码了,直接运行pg_dump即可,它会自动读取pgpass文件的内容:import gzip import subprocess with gzip.open('backup.gz', 'wb') as f: popen = subprocess.Popen( ['pg_dump', '--no-owner', '--no-acl', '-U', 'postgres', '-d', 'database_name', '-h', '178.111.11.111'], stdout=subprocess.PIPE, universal_newlines=True ) for stdout_line in iter(popen.stdout.readline, ""): f.write(stdout_line.encode('utf-8')) popen.stdout.close() popen.wait()
总结
- 临时用脚本测试的话,用PGPASSWORD环境变量最快;
- 长期使用的话,强烈推荐pgpass文件,既安全又不用在脚本里暴露密码。
内容的提问来源于stack exchange,提问作者Jinto Antony
相关产品推荐
相关产品推荐

