【问题标题】:pg_dump & pg_restore password using python module subprocesspg_dump & pg_restore 密码使用 python 模块子进程
【发布时间】:2017-09-08 20:50:00
【问题描述】:

问题:在 Python 脚本中使用 PSQL pg_dumppg_restore 并使用 subprocess 模块。

背景:我正在使用来自本地主机的以下python 2.7 脚本(即Ubuntu 14.04.5 LTS)在PSQL 服务器(即PostgreSQL 9.4.11)中创建表的备份并恢复它在较新版本的 PSQL 服务器(即PostgreSQL 9.6.2)中进入远程主机(即Ubuntu 16.04.2 LTS)。

#!/usr/bin/python

from subprocess import PIPE,Popen

def dump_table(host_name,database_name,user_name,database_password,table_name):

    command = 'pg_dump -h {0} -d {1} -U {2} -p 5432 -t public.{3} -Fc -f /tmp/table.dmp'\
    .format(host_name,database_name,user_name,table_name)

    p = Popen(command,shell=True,stdin=PIPE)

    return p.communicate('{}\n'.format(database_password))

def restore_table(host_name,database_name,user_name,database_password):

    command = 'pg_restore -h {0} -d {1} -U {2} < /tmp/table.dmp'\
    .format(host_name,database_name,user_name)

    p = Popen(command,shell=True,stdin=PIPE)

    return p.communicate('{}\n'.format(database_password))

def main():
    dump_table('localhost','testdb','user_name','passwd','test_tbl')
    restore_table('remotehost','new_db','user_name','passwd')

if __name__ == "__main__":
    main()

当我按上述顺序使用函数时,dump_table() 函数成功完成并创建了/tmp/table.sql 文件,但restore_table() 函数返回以下错误:

('', '密码: \npg_restore: [archiver (db)] 连接到数据库 “database_name”失败:致命:用户密码验证失败 "username"\nFATAL: 用户密码验证失败 "用户名"\n')*

我已经通过在 shell 中执行 pg_restore 的命令检查了凭据和输出,并且我还包含了 .pgpass 的凭据(尽管不相关,因为我在 p.communicate() 中传递了密码)

有人有类似经历吗?我几乎被困住了!

问候, D.

【问题讨论】:

    标签: python subprocess psql pg-dump pg-restore


    【解决方案1】:

    评论以下作品和所做的更改。

    我不确定为什么pg_restore 在使用完整命令(即未在列表中拆分)并在Popen 中使用shell=True 时会产生密码验证错误,但另一方面pg_dump 有效可以使用 shell=True 和完整的命令。 &lt; 和它有什么关系吗?

    #!/usr/bin/python
    
    from subprocess import PIPE,Popen
    import shlex
    
    def dump_table(host_name,database_name,user_name,database_password,table_name):
    
        command = 'pg_dump -h {0} -d {1} -U {2} -p 5432 -t public.{3} -Fc -f /tmp/table.dmp'\
        .format(host_name,database_name,user_name,table_name)
    
        p = Popen(command,shell=True,stdin=PIPE,stdout=PIPE,stderr=PIPE)
    
        return p.communicate('{}\n'.format(database_password))
    
    def restore_table(host_name,database_name,user_name,database_password):
    
        #Remove the '<' from the pg_restore command.
        command = 'pg_restore -h {0} -d {1} -U {2} /tmp/table.dmp'\
                  .format(host_name,database_name,user_name)
    
        #Use shlex to use a list of parameters in Popen instead of using the
        #command as is.
        command = shlex.split(command)
    
        #Let the shell out of this (i.e. shell=False)
        p = Popen(command,shell=False,stdin=PIPE,stdout=PIPE,stderr=PIPE)
    
        return p.communicate('{}\n'.format(database_password))
    
    def main():
        dump_table('localhost','testdb','user_name','passwd','test_tbl')
        restore_table('localhost','testdb','user_name','passwd')
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

      【解决方案2】:

      您可以为 pg_dump 使用环境变量 https://www.postgresql.org/docs/11/libpq-envars.html 和“--no-password”选项。

          def dump_schema(host, dbname, user, password, **kwargs):
              command = f'pg_dump --host={host} ' \
                  f'--dbname={dbname} ' \
                  f'--username={user} ' \
                  f'--no-password ' \
                  f'--format=c ' \
                  f'--file=/tmp/schema.dmp '
      
              proc = Popen(command, shell=True, env={
                  'PGPASSWORD': password
              })
              proc.wait()
      

      【讨论】:

      • 在遇到 (Python 3.7.4) subprocess.run(...) 未能使用 input= 关键字后,我找到了这个页面。没有使用 shell=True 关键字,但 env= 成功了。一些模糊的 tty 相关问题。
      【解决方案3】:

      这是一个用于获取 postgres 转储并将其恢复到新数据库的 python 脚本。

      import subprocess
      
      DB_NAME = 'PrimaryDB'  # your db name
      
      DB_USER = 'postgres' # you db user
      DB_HOST = "localhost"
      DB_PASSWORD = 'sarath1996'# your db password
      dump_success = 1
      print ('Backing up %s database ' % (DB_NAME))
      command_for_dumping = f'pg_dump --host={DB_HOST} ' \
                  f'--dbname={DB_NAME} ' \
                  f'--username={DB_USER} ' \
                  f'--no-password ' \
                  f'--file=backup.dmp '
       try:
           proc = subprocess.Popen(command, shell=True, env={
                         'PGPASSWORD': DB_PASSWORD
                         })
           proc.wait()
      
       except Exception as e:
              dump_success = 0
              print('Exception happened during dump %s' %(e))
      
      
       if dump_success:
          print('db dump successfull')
       print(' restoring to a new database database')
      
       """database to restore dump must be created with 
      the same user as of previous db (in my case user is 'postgres'). 
      i have #created a db called ReplicaDB. no need of tables inside. 
      restore process will #create tables with data.
      """
      
      backup_file = '/home/Downloads/BlogTemplate/BlogTemplate/backup.dmp' 
      """give absolute path of your dump file. This script will create the backup.dmp in the same directory from which u are running the script """
      
      
      
      if not dump_success:
          print('dump unsucessfull. retsore not possible')
       else:
          try:
              process = subprocess.Popen(
                              ['pg_restore',
                               '--no-owner',
                               '--dbname=postgresql://{}:{}@{}:{}/{}'.format('postgres',#db user
                                                                             'sarath1996', #db password
                                                                             'localhost',  #db host
                                                                             '5432', 'ReplicaDB'), #db port ,#db name
                               '-v',
                               backup_file],
                              stdout=subprocess.PIPE
                          )
              output = process.communicate()[0]
      
           except Exception as e:
                 print('Exception during restore %e' %(e) )
      

      【讨论】:

      • 这里要注意,您必须在 command_for_dumping 中提供 --format=custom 才能使用 pg_restore。
      猜你喜欢
      • 2019-06-26
      • 1970-01-01
      • 2015-08-09
      • 2011-01-06
      • 2018-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      相关资源
      最近更新 更多