73

我的 PostgreSQL 数据库中有一个表,它有 3 列-c_uid和. 简单地存储用户的名称,并且是一段很长的文本,其中包含该用户的大量数据。c_defaultsc_settingsc_uidc_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 脚本。

4

9 回答 9

143

试试这个:

#!/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'"
于 2013-08-14T05:32:28.540 回答
41

您可以如下连接到 psql 并像在块内的常规 postgres 函数中一样编写 sql 查询。在那里,可以使用 bash 变量。但是,脚本应该是严格的 sql,即使对于您需要使用的注释 - 而不是 #:

#!/bin/bash
psql postgresql://<user>:<password>@<host>/<db> << EOF
       <your sql queries go here>
EOF
于 2015-05-21T20:56:48.403 回答
17

如果您打算从单独的 sql 文件运行它。这是一个很好的例子(取自一个很棒的页面来学习如何使用 postgresql 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
于 2015-05-19T19:46:09.850 回答
12

以 身份登录后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.

于 2013-08-14T05:29:33.960 回答
3

在脚本中传递命令的最安全方法psql是通过管道传输字符串或传递 here-doc。

-c/--command选项的 man 文档在应避免使用时进行了更详细的介绍。

   -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
于 2016-06-23T11:31:36.307 回答
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 历史记录中可见。有关更多信息,请参见此处

更新:我在 docker 容器中运行数据库,我只需要命令:docker exec -i container_name psql -U postgres -d postgres -c "$SQL_COMMAND"

于 2020-07-30T10:00:43.440 回答
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 
于 2020-05-26T21:27:28.100 回答
1

为了回答@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}

但是您必须非常小心密码:我无法使用 a'和/或 a:来设置密码以这种方式工作。所以最后放弃了。

-S

于 2019-02-05T18:26:55.577 回答
-1

这个例子可能对在 Kubernetes 中运行 Postgres 数据库的人有用。

此示例考虑到您正在使用helm chart.

将存储库添加azure-marketplace到您的掌舵图:

helm repo add azure-marketplace https://marketplace.azurecr.io/helm/v1/repo

安装数据库:

helm install postgres-db azure-marketplace/postgresql -f postgres-values.yaml

postgres-values.yaml

postgresqlDatabase: mydb
postgresqlUsername: mydb

将密码保存在变量中:

export POSTGRES_PASSWORD=$(kubectl get secret --namespace default postgresql-db -o jsonpath="{.data.postgresql-password}" | base64 --decode)

通过将 替换为您的命令来执行您希望的-c "SELECT ..."命令:

$ kubectl run postgresql-client \
--rm -i --restart='Never' --namespace default \
--image marketplace.azurecr.io/bitnami/postgresql:11.13.0-debian-10-r40 \
--env="PGPASSWORD=$POSTGRES_PASSWORD" \
--command -- psql --host postgresql-db -U mydb -d mydb -p 5432 \
-c "SELECT datname FROM pg_database;"
于 2021-10-18T14:12:11.577 回答