簡體   English   中英

PostgreSQL - 從 bash 腳本查詢作為數據庫用戶“postgres”

[英]PostgreSQL - query from bash script as database user 'postgres'

我的 PostgreSQL 數據庫中有一個表,它有 3 列 - c_uidc_defaultsc_settings c_uid僅存儲用戶的名稱,而c_defaults是一段長文本,其中包含該用戶的大量數據。

我必須從 bash 腳本中執行一條語句,該腳本根據c_uid值選擇c_defaults列的值,這需要由數據庫用戶“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 腳本進行。

試試這個:

#!/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'"

您可以按如下方式連接到 psql 並像在塊內的常規 postgres 函數中一樣編寫 sql 查詢。 在那里,可以使用 bash 變量。 但是,腳本應該是嚴格的 sql,即使對於您需要使用的注釋,也應該使用 -- 而不是 #:

#!/bin/bash
psql postgresql://<user>:<password>@<host>/<db> << EOF
       <your sql queries go here>
EOF

如果您打算從單獨的 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

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

在腳本中將命令傳遞給psql的最安全方法是通過管道傳輸字符串或傳遞 here-doc。

-c/--command選項的 man docs 更詳細地介紹了應該避免的情況。

   -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

回答@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

#!/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 

就我而言,包括身份驗證要求在內的最佳解決方案是:

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"

這個例子可能對在 Kubernetes 中運行 Postgres 數據庫的人有用。

此示例考慮到您正在使用helm chart運行 Postgres 數據庫。

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;"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM