简体   繁体   English

为什么 pg_restore 在 AWS ECS 中静默失败?

[英]Why does pg_restore fail silently in AWS ECS?

Consider this pg_restore command:考虑这个 pg_restore 命令:

pg_restore -h 123.123.123.123 -d my_database -U my_user --no-owner --no-privileges --no-password -t specific_table 616f6d35-202104.backup

When I run it locally it works.当我在本地运行它时,它可以工作。 But when I run it my ECS instance it does not restore.但是当我运行它时,我的 ECS 实例不会恢复。 There is no error and exit code is 0.没有错误,退出代码为 0。

If I create the db in the statement (by adding the --create flag and changing my_database to postgres) like so:如果我在语句中创建数据库(通过添加 --create 标志并将 my_database 更改为 postgres),如下所示:

pg_restore -h 123.123.123.123 -d postgres -U my_user --create --no-owner --no-privileges --no-password -t specific_table 616f6d35-202104.backup

It still works locally.它仍然在本地工作。 When I run it in ECS it creates the db but still does not restore the table.当我在 ECS 中运行它时,它会创建数据库,但仍然不会恢复表。 And if I exclude the specific table:如果我排除特定表:

pg_restore -h 123.123.123.123 -d my_database -U my_user --no-owner --no-privileges --no-password 616f6d35-202104.backup

Then it works.然后它工作。 But it loads the whole database which I don't want.但它加载了我不想要的整个数据库。 So it's something to do with the -t flag that works locally but not in my ECS instance.因此,这与在本地工作但在我的 ECS 实例中不起作用的 -t 标志有关。

EDIT: There does seem to be a version mis-match.编辑:似乎确实存在版本不匹配。 The closest I could get the environments was PostgreSQL v10.16 on the ECS and v10.4 on the target EC2 that has the Postgres server 123.123.123.123.我能得到的最接近的环境是ECS 上的 PostgreSQL v10.16和具有 Postgres 服务器 123.123.123.123的目标 EC2 上的 v10.4 Still does not work.还是不行。 Could this be the issue?这可能是问题吗? If so how do I install a specific minor version of postgresql or postgresql-client?如果是这样,我如何安装 postgresql 或 postgresql-client 的特定次要版本?

For the ECS in the docker file I have:对于 docker 文件中的 ECS,我有:

RUN apt-get update
RUN apt-get install -y curl ca-certificates gnupg
RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
RUN echo "deb http://apt.postgresql.org/pub/repos/apt buster-pgdg main" | tee /etc/apt/sources.list.d/docker.list
RUN apt-get update
RUN apt-get install -y postgresql-10

This gets me to v10.16 on the ECS (which still doesn't work).这让我在 ECS 上使用 v10.16(仍然无法正常工作)。 But if I change that last line to specify a specific minor version (to more closely match the EC2's version) it can't find it.但是,如果我更改最后一行以指定特定的次要版本(以更接近地匹配 EC2 的版本),它就找不到它。

RUN apt-get install -y postgresql-10.5

E: Unable to locate package postgresql-10.5
E: Couldn't find any package by glob 'postgresql-10.5'
E: Couldn't find any package by regex 'postgresql-10.5'

Again, locally it works - and the version I have locally is v10.5 .再次,它在本地工作 - 我在本地拥有的版本是 v10.5

EDIT-2 : I have a little more visibility on this. EDIT-2 :我对此有更多的了解。 Looks like it outputs these two lines and then stops - still no error:看起来它输出这两行然后停止 - 仍然没有错误:

pg_restore: connecting to database for restore
pg_restore: implied data-only restore

It seems 'implied data-only restore' might not be causing an issue though - there seems to be output that should come after it.似乎“隐含的仅数据恢复”可能不会导致问题 - 似乎应该有 output 紧随其后。 But output just stops in my case.但是 output 在我的情况下只是停止。

I never figured out why the -t/--table flag wasn't working remotely.我从来不明白为什么 -t/--table 标志不能远程工作。 But I found a different solution that did exactly what I needed.但我找到了一个完全符合我需要的不同解决方案。 I did this in Python but it can be done in bash or other languages.我在 Python 中完成了此操作,但可以在 bash 或其他语言中完成。

I switched to the -l list/-L use-list flag.我切换到-l list/-L use-list标志。

 os.system(f'pg_restore -l {backup_file} > list1.list')

pg_restore -l outputs a.list file that looks something like this: pg_restore -l输出一个看起来像这样的.list 文件:

;
; Archive created at 2021-04-23 08:06:25
;     dbname: abc
;     TOC Entries: 2069
;     Compression: -1
;     Dump Version: 1.13-0
;     Format: CUSTOM
;     Integer: 4 bytes
;     Offset: 8 bytes
;     Dumped from database version: 9.6.16
;     Dumped by pg_dump version: 9.6.16
;
;
; Selected TOC Entries:
;
7380; 1262 16390 DATABASE - db9j0aedvewevi6fw ury3p1vgqirfm2wq
3; 2615 2200 SCHEMA - public ury3p1vgqirfm2wq
7381; 0 0 COMMENT - SCHEMA public ury3p1vgqirfm2wq
1; 3079 13308 EXTENSION - plpgsql 
7382; 0 0 COMMENT - EXTENSION plpgsql 
185; 1259 168687 TABLE public tableA ury3p1vgqirfm2wq
186; 1259 168693 TABLE public tableB ury3p1vgqirfm2wq
187; 1259 168699 TABLE public tableC ury3p1vgqirfm2wq
188; 1259 168702 TABLE public tableZ ury3p1vgqirfm2wq

The intention of this file is so that developers can restore by exclusion.该文件的目的是让开发人员可以通过排除来恢复。 They can peek in this file and comment out using ;他们可以查看此文件并使用;注释掉。 lines they don't want.他们不想要的线条。 Then they use -L/--use-list like pg_restore --use-list=my_list.list -U username... .然后他们使用-L/--use-listpg_restore --use-list=my_list.list -U username...

Since all I needed was a few tables and their data (and needed to do it programmatically) I used the generated .list file to generate my own, abbreviated file.由于我只需要一些表和它们的数据(并且需要以编程方式完成),因此我使用生成的.list文件来生成我自己的缩写文件。 I learned (by trial and error) that the lines responsible for creating the table and populating its data say: TABLE public tablename and TABLE DATA public tablename respectively.我(通过反复试验)了解到,负责创建表和填充其数据的行分别表示: TABLE public tablenameTABLE DATA public tablename

table_create = 'TABLE public '
table_data = 'TABLE DATA public '

So I looped over the .list file provided by pg_restore -l and looked for the lines for the needed tables.因此,我遍历了pg_restore -l提供的.list文件并查找所需表的行。 When I found the right lines I added them to a list.当我找到正确的行时,我将它们添加到列表中。

table_names = ['tablename1', 'tablename2']
full_list = 'list1.list'
list_lines = []
with open(full_list) as topo_file:
    for line in topo_file:
        for table_name in table_names:
            if table_data + table_name + ' ' in line or table_create + table_name + ' ' in line:
                print(line)
                list_lines.append(line)

Then I used that list to create my own .list file.然后我使用该列表创建我自己的.list文件。

restore_list = 'list2.list'
with open(restore_list, 'w') as f:
    for item in list_lines:
        f.write("%s\n" % item)

I found the header was not necessary.我发现 header 不是必需的。 So if I only wanted one table and its data the file would look very simple:因此,如果我只想要一个表及其数据,则文件看起来非常简单:

426; 1259 169557 TABLE public tablename1 ury3p1vgqirfm2wq
7130; 0 169557 TABLE DATA public tablename1 ury3p1vgqirfm2wq

If you notice the ;如果您注意到; comments things out.把事情评论出来。 So anything after it pg_restore doesn't care about.所以 pg_restore 之后的任何事情都不在乎。 And finally I used that list file for in the pg_restore command.最后,我在pg_restore命令中使用了该列表文件。

restore_command = f'pg_restore --use-list={restore_list} --host=localhost --username=postgres --dbname=test --no-owner --no-privileges --verbose "{backup_file}"'
os.system(restore_command)

pg_restore docs were the key - although I would have liked a little more context around the .list file syntax and structure. pg_restore 文档是关键——尽管我希望更多关于.list文件语法和结构的上下文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM