替代 postgres 中用于脚本的 list 命令

Posted

技术标签:

【中文标题】替代 postgres 中用于脚本的 list 命令【英文标题】:Alternative to list command in postgres for scripting 【发布时间】:2014-02-11 02:45:31 【问题描述】:

不幸的是 psql -l 使用换行

示例 查看输出并考虑“访问”列

 数据库列表
          姓名 |所有者 |编码 |整理 |类型 |访问权限
-------------------------+------------+----------+ -------------+-------------+---------- -
 第一数据库 |后勤 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 |
 数据库 | scnduser | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 |
 数据库 | scnduser | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 |
 后勤 |后勤 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 |
 模板0 |后勤 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | =c/postgres +
                         | | | | | postgres=CTc/postgres
 模板1 |后勤 | UTF8 | de_DE.UTF-8 | de_DE.UTF-8 | =c/postgres +
                         | | | | | postgres=CTc/postgres
(6 行)

提示即使有一些选项,我也无法摆脱它:

$ 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|
模板0|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|=c/postgres
postgres=CTc/postgres
模板1|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|=c/postgres
postgres=CTc/postgres

问题有没有另一种方法来获取数据库列表,就像\list 打印它一样,所以我可以在脚本中使用它来解析,例如怎么了?

【问题讨论】:

【参考方案1】:

有趣的问题。您被 ACL 条目中的硬换行符咬住了。顺便说一句,它们并不是唯一可以出现的地方,只是最常见的地方。

使用空字节记录

与其避免使用换行符,不如使用不同的记录分隔符?一个空字节(\0)可能是好的;这就是-0 选项的用途。但是,仅当您的客户端可以处理空字节时,它才有用;适合xargs -0,不适合很多其他东西。空字节的方便之处在于它不会出现在psql 的输出中,否则不会有冲突的风险。 gawk 确实支持以空值分隔的记录,尽管它的文档记录严重不足。

试试,例如:

psql -Atlqn -0  | gawk -vRS=$'\0' ' gsub("\n", " "); print 

用空格替换数据库名称中的换行符(是的,它们可以出现在那里!)、ACL 条目等。

使用不同的记录

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

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

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

换行符和 shell 元字符

请注意,您仍然需要处理意外的换行符;考虑当一些@#$@ 这样做时会发生什么:

 CREATE DATABASE "my
 database";

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

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

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

是的,两者都是合法的数据库名称。是的,如果你没有正确地转义你的 shell 元字符,你错误地以 root 或postgres 用户运行你的 shell 脚本,那真的非常糟糕,而且他们感觉不好。

【讨论】:

psql 9.1.1 似乎不支持 -0 它从 9.2+ postgresql.org/docs/9.2/static/app-psql.html 开始支持,但是谢谢,是的,这可行:psql -Atlqn -F\| -R'~~SEP~~' | awk 'BEGIN FS="|"; RS="~~SEP~~"; print "nl:"$0 '跨度> 【参考方案2】:

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

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 命令中:

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

返回正确的格式

模板1|postgres|UTF8|de_DE.UTF-8|de_DE.UTF-8|=c/postgres,postgres=CTc/postgres 模板0|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|

【讨论】:

这不会保护您免受 datname 中的换行符(或更糟)的影响。

以上是关于替代 postgres 中用于脚本的 list 命令的主要内容,如果未能解决你的问题,请参考以下文章

sql 用于群集构建的Postgres脚本

postgres 中 SET XACT_ABORT ON 的替代方法是啥

在 Postgres 中存储大量 JSON 数据是不可行的,那么有啥替代方案呢?

sql 用于处理创建Postgres数据库的脚本:```PG :: InvalidParameterValue:ERROR:编码UTF8不是

sh 用于将.css.scss重命名为.scss的Shell脚本

基于表名的 Postgres 表分区