Linux环境下如何免密码执行psql并提取指定查询结果?
我来逐个帮你梳理并解决这三个问题:
1. 无需输入密码运行psql的几种方案
在bash脚本里自动化执行psql命令,避免手动输密码,有几个更可靠的方式,比expect脚本更简洁:
使用
.pgpass文件(推荐)
这是PostgreSQL官方推荐的方式,创建一个~/.pgpass文件(对应执行脚本的用户,比如root或者ambari用户),格式为:hostname:port:database:username:password比如你的场景可以写:
localhost:5432:ambari:ambari:your_password_here然后设置文件权限为600,否则PostgreSQL会忽略它:
chmod 600 ~/.pgpass之后直接运行你的命令就不需要输密码了。
设置环境变量
PGPASSWORD
在脚本里临时设置环境变量,比如:PGPASSWORD=your_password_here psql -U ambari ambari -c "select * from blueprint"注意这种方式密码会在进程列表里可见,安全性稍差,不推荐在生产环境用。
修改
pg_hba.conf配置
如果是本地访问,可以修改PostgreSQL的pg_hba.conf文件(通常在/var/lib/pgsql/data/目录下),添加一行:local ambari ambari trust然后重启PostgreSQL服务,这样本地用ambari用户连接ambari数据库就不需要密码了。不过这种方式安全性最低,只适合测试环境。
Expect脚本(备选)
如果上面的方法都不适用,可以用expect脚本自动输入密码,示例脚本:#!/usr/bin/expect -f set password "your_password_here" spawn psql -U ambari ambari -c "select * from blueprint" expect "Password:" send "$password\r" interact赋予执行权限后运行即可,但维护起来不如前几种方便。
2. 执行su - postgres -c " psql -tc \"SELECT * FROM BLUEPRINT\" "报错的原因
这个报错有两个核心原因:
- 数据库不对:
su - postgres后,psql默认会连接到postgres数据库,而你的blueprint表是在ambari数据库里的,所以需要指定数据库名。 - 表名大小写问题:PostgreSQL默认会把未加引号的标识符(表名、列名)转为小写,你写的
BLUEPRINT会被转为blueprint,但如果你的表名确实是大写的(不过通常Ambari的表都是小写),需要加双引号。不过更可能的是你没指定数据库。
正确的命令应该是:
su - postgres -c "psql -d ambari -tc \"SELECT * FROM blueprint\""
或者如果要以ambari用户身份查询(因为postgres用户可能没有ambari表的权限),可以这样:
su - postgres -c "psql -U ambari -d ambari -tc \"SELECT * FROM blueprint\""
3. 提取blueprint_name的更优方案
原来用grep -v row | tail -2 | awk '{print $1}'的方法很脆弱,一旦查询结果行数变化或者输出格式调整就会失效,推荐用以下几种更可靠的方式:
直接在SQL中只查询需要的字段
这是最简洁的方式,只返回blueprint_name列,避免后续处理:psql -U ambari ambari -t -A -c "SELECT blueprint_name FROM blueprint"其中:
-t:去掉表头和表尾的统计信息-A:关闭对齐模式,输出无多余空格
这样输出就是纯blueprint_name的值,不需要额外处理。
用psql的CSV格式输出+cut
如果需要处理多列,CSV格式更稳定:psql -U ambari ambari --csv -t -c "SELECT blueprint_name FROM blueprint" | cut -d',' -f1这种方式即使字段值有空格也能正确提取。
用awk直接定位列
如果一定要查询所有列,用awk根据行号定位(更可靠):psql -U ambari ambari -c "select * from blueprint" | awk 'NR==2{print $1}'不过还是推荐只查询需要的字段,效率更高也更稳定。
内容的提问来源于stack exchange,提问作者enodmilvado

