关于postgresql:postgres中用于编写脚本的list命令的替代方法

Alternative to list command in postgres for scripting

不幸的是psql -l使用了换行符


查看输出并查看"访问"列

1
2
3
4
5
6
7
8
9
10
11
12
                                          List OF DATABASES
          Name           |   Owner    | Encoding |   COLLATE   |    Ctype    |   Access privileges
-------------------------+------------+----------+-------------+-------------+-----------------------
 firstdb                 | postgres   | UTF8     | de_DE.UTF-8 | de_DE.UTF-8 |
 secnddb                 | scnduser   | UTF8     | de_DE.UTF-8 | de_DE.UTF-8 |
 thrddb                  | scnduser   | UTF8     | de_DE.UTF-8 | de_DE.UTF-8 |
 postgres                | postgres   | UTF8     | de_DE.UTF-8 | de_DE.UTF-8 |
 template0               | postgres   | UTF8     | de_DE.UTF-8 | de_DE.UTF-8 | =c/postgres          +
                         |            |          |             |             | postgres=CTc/postgres
 template1               | postgres   | UTF8     | de_DE.UTF-8 | de_DE.UTF-8 | =c/postgres          +
                         |            |          |             |             | postgres=CTc/postgres
(6 ROWS)

提示甚至有一些选择,我不能让它消失:

1
2
3
4
5
6
7
8
9
$ psql -Atlqn
firstdb|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|
secnddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8|
thrddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8|
postgres|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|
template0|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|=c/postgres
postgres=CTc/postgres
template1|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|=c/postgres
postgres=CTc/postgres

问题是否有另一种方法以\list打印它的方式获取数据库列表,因此我可以在脚本中使用它来解析例如AWK?


有趣的问题。你被ACL条目中的硬线包裹所困扰。那些不是他们可以出现的唯一的地方,只是最常见的。

使用空字节记录

而不是试图避免换行,为什么不使用不同的记录分隔符?空字节(\0)可以是好的;这就是-0选项的用途。但是,只有当您的客户端可以处理空字节时才有用;适合xargs -0,不适合很多其他东西。关于空字节的一个方便之处是它不会出现在psql的输出中,否则就不存在冲突的风险。 gawk确实支持空分隔的记录,尽管它的记录很糟糕。

试试,例如:

1
2
psql -Atlqn -0  | gawk -vRS=$'\0' '{ gsub("
",""); print }

它取代了数据库名称中的换行符(是的,它们可以出现在那里!),带有空格的ACL条目等。

使用不同的记录

或者,使用-R,例如-R '!'-R '--SEPARATOR--'或任何易于解析且不太可能出现在输出中的内容。

自己查询目录,转义字符串

根据您需要的信息,您也可以直接查询目录或information_schema。你仍然需要处理有趣的字符,所以你可能想要一个正则表达式来逃避任何有趣的业务。

换行符和shell元字符

请注意,您仍然需要处理意外的换行;考虑一些@#$ @执行此操作时会发生什么:

1
2
 CREATE DATABASE"my
 database"
;

是的,这是一个合法的数据库名称。两者都是:

1
2
3
 CREATE DATABASE"$(rm -rf /gladthisisnotroot);";

 CREATE DATABASE"$(createuser -l -s my_haxxor -W top_secret)"

是的,两者都是合法的数据库名称。是的,如果你没有正确地逃避你的shell元字符,那真是非常糟糕,你犯了以root用户身份运行shell脚本或postgres用户的错误,他们感觉不舒服。


所有相关数据均在pg_databasepg_user
见http://www.postgresql.org/docs/current/static/catalog-pg-database.html

1
SELECT pg_database.datname,pg_user.usename,pg_encoding_to_char(pg_database.encoding),pg_database.datcollate,pg_database.datctype,pg_database.datacl FROM pg_database,pg_user WHERE pg_database.datdba = pg_user.usesysid;

在shell上,用psql命令包装:

1
psql -AStnq -c"select [...]"

返回格式正确

1
2
3
4
5
6
template1|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|{=c/postgres,postgres=CTc/postgres}
template0|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|{=c/postgres,postgres=CTc/postgres}
postgres|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|
firstdb|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|
secnddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8|
thrddb|scnduser|UTF8|de_DE.UTF-8|de_DE.UTF-8|