我的PostgreSQL数据库中有一个表,有3列 - c_uid
,c_defaults
和c_settings
。 c_uid
只存储用户的名称,c_defaults
是一段很长的文本,其中包含许多用户的数据。
我必须从bash脚本执行一个语句,该脚本根据c_defaults
值选择c_uid
列的值,这需要由数据库用户'postgres'完成。
在CLI上,我可以执行以下操作:
[mymachine]# su postgres
bash-4.1$psql
postgres=#\c database_name
You are now connected to database "database_name" as user "postgres".
database_name=#SELECT c_defaults FROM user_info WHERE c_uid = 'testuser';
但是,我如何通过bash脚本实现这一目标?
目的是从该列获取信息,编辑它并将其写回该列 - 所有这些都通过bash脚本完成。
答案 0 :(得分:83)
试试这个:
#!/bin/bash
psql -U postgres -d database_name -c "SELECT c_defaults FROM user_info WHERE c_uid = 'testuser'"
或使用su
:
#!/bin/bash
su -c "psql -d database_name -c \"SELECT c_defaults FROM user_info WHERE c_uid = 'testuser'\"" postgres
还有sudo
:
#!/bin/bash
sudo -u postgres -H -- psql -d database_name -c "SELECT c_defaults FROM user_info WHERE c_uid = 'testuser'"
答案 1 :(得分:17)
你可以像下面那样连接到psql并像在块中的常规postgres函数中一样编写sql查询。在那里,可以使用bash变量。但是,脚本应该是严格的sql,即使是你需要使用的注释 - 而不是#:
#!/bin/bash
psql postgresql://<user>:<password>@<host>/<db> << EOF
<your sql queries go here>
EOF
答案 2 :(得分:12)
如果您打算从单独的sql文件运行它。这是一个很好的例子(摘自一个很棒的页面来学习如何使用postgresql进行bash http://www.manniwood.com/postgresql_and_bash_stuff/index.html
#!/bin/bash
set -e
set -u
if [ $# != 2 ]; then
echo "please enter a db host and a table suffix"
exit 1
fi
export DBHOST=$1
export TSUFF=$2
psql \
-X \
-U user \
-h $DBHOST \
-f /path/to/sql/file.sql \
--echo-all \
--set AUTOCOMMIT=off \
--set ON_ERROR_STOP=on \
--set TSUFF=$TSUFF \
--set QTSTUFF=\'$TSUFF\' \
mydatabase
psql_exit_status = $?
if [ $psql_exit_status != 0 ]; then
echo "psql failed while trying to run this sql script" 1>&2
exit $psql_exit_status
fi
echo "sql script successful"
exit 0
答案 3 :(得分:7)
以postgres
身份登录后,您应该能够写下:
psql -t -d database_name -c $'SELECT c_defaults FROM user_info WHERE c_uid = \'testuser\';'
只打印出该字段的值,这意味着您可以捕获它(例如)保存在Bash变量中:
testuser_defaults="$(psql -t -d database_name -c $'SELECT c_defaults FROM user_info WHERE c_uid = \'testuser\';')"
要以postgres
方式登录,建议您使用sudo
。您可以授予特定用户运行权限
sudo -u postgres /path/to/this/script.sh
这样他们就可以只运行一个脚本postgres
。
答案 4 :(得分:2)
在脚本中将命令传递给psql
的最安全方法是通过管道传输字符串或传递here-doc。
-c/--command
选项的man doc会在应该避免的时候详细说明。
-c command
--command=command
Specifies that psql is to execute one command string, command, and then exit. This is useful in shell scripts. Start-up files (psqlrc and ~/.psqlrc)
are ignored with this option.
command must be either a command string that is completely parsable by the server (i.e., it contains no psql-specific features), or a single
backslash command. Thus you cannot mix SQL and psql meta-commands with this option. To achieve that, you could pipe the string into psql, for
example: echo '\x \\ SELECT * FROM foo;' | psql. (\\ is the separator meta-command.)
If the command string contains multiple SQL commands, they are processed in a single transaction, unless there are explicit BEGIN/COMMIT commands
included in the string to divide it into multiple transactions. This is different from the behavior when the same string is fed to psql's standard
input. Also, only the result of the last SQL command is returned.
Because of these legacy behaviors, putting more than one command in the -c string often has unexpected results. It's better to feed multiple
commands to psql's standard input, either using echo as illustrated above, or via a shell here-document, for example:
psql <<EOF
\x
SELECT * FROM foo;
EOF
答案 5 :(得分:1)
#!/bin/bash
password='complex=!password'
PGPASSWORD=$(echo $password) psql -h example.com -U example_user -d example_db -t -c "select * from example_table1" -o example_out.txt
答案 6 :(得分:1)
就我而言,包括身份验证要求的最佳解决方案是:
username="admin"
new_password="helloworld"
PGPASSWORD=DB_PASSWORD \
psql -h HOSTNAME -U DB_USERNAME -d DATABASE_NAME -c \
"UPDATE user SET password = '$new_password' WHERE username = '$username'"
此命令将更新用户密码,例如恢复情况。
信息:这里的权衡是您需要记住密码将在bash历史记录中可见。有关更多信息,请参见here。
更新:我正在docker容器中运行数据库,在那里我只需要以下命令:docker exec -i container_name psql -U postgres -d postgres -c "$SQL_COMMAND"
答案 7 :(得分:0)
为了回答@Jason的问题,在我的bash脚本中,我已经将这样的球罩了(出于我的目的):
dbPass='xxxxxxxx'
.....
## Connect to the DB
PGPASSWORD=${dbPass} psql -h ${dbHost} -U ${myUsr} -d ${myRdb} -P pager=on --set AUTOCOMMIT=off
另一种方法是:
psql --set AUTOCOMMIT=off --set ON_ERROR_STOP=on -P pager=on \
postgresql://${myUsr}:${dbPass}@${dbHost}/${myRdb}
但是您必须非常小心密码:我无法使用'
和/或:
来设置密码,以这种方式工作。所以最终放弃了。
-S