J'ai une table dans ma base de données PostgreSQL qui a 3 colonnes - c_uid
, c_defaults
et c_settings
. c_uid
stocke simplement le nom d'un utilisateur et c_defaults
est un long morceau de texte qui contient beaucoup de données avec cet utilisateur.
Je dois exécuter une instruction à partir d'un script bash qui sélectionne la valeur de la colonne c_defaults
en fonction de la valeur c_uid
et doit être effectuée par l'utilisateur de la base de données 'postgres'.
Sur la CLI, je peux effectuer les tâches suivantes:
[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';
Cependant, comment y parvenir à travers un script bash?
Le but est d’obtenir les informations de cette colonne, de les éditer et de les écrire dans cette colonne - tout au long d’un script bash.
Essaye celui-là:
#!/bin/bash
psql -U postgres -d database_name -c "SELECT c_defaults FROM user_info WHERE c_uid = 'testuser'"
Ou en utilisant su
:
#!/bin/bash
su -c "psql -d database_name -c \"SELECT c_defaults FROM user_info WHERE c_uid = 'testuser'\"" postgres
Et aussi Sudo
:
#!/bin/bash
Sudo -u postgres -H -- psql -d database_name -c "SELECT c_defaults FROM user_info WHERE c_uid = 'testuser'"
Vous pouvez vous connecter à psql comme ci-dessous et écrire vos requêtes SQL comme vous le faites dans une fonction postgres normale dans le bloc. Là, les variables bash peuvent être utilisées. Cependant, le script doit être strictement SQL, même pour les commentaires que vous devez utiliser - au lieu de #:
#!/bin/bash
psql postgresql://<user>:<password>@<Host>/<db> << EOF
<your sql queries go here>
EOF
si vous prévoyez de l'exécuter à partir d'un fichier SQL séparé. voici un bon exemple (tiré d'une page formidable pour apprendre à utiliser basg avec 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
Une fois connecté en tant que postgres
, vous devriez pouvoir écrire:
psql -t -d database_name -c $'SELECT c_defaults FROM user_info WHERE c_uid = \'testuser\';'
pour n'imprimer que la valeur de ce champ, ce qui signifie que vous pouvez le capturer (par exemple) dans une variable Bash
testuser_defaults="$(psql -t -d database_name -c $'SELECT c_defaults FROM user_info WHERE c_uid = \'testuser\';')"
Pour gérer la connexion en tant que postgres
, je vous recommande d’utiliser Sudo
. Vous pouvez donner à un utilisateur spécifique l'autorisation d'exécuter
Sudo -u postgres /path/to/this/script.sh
afin qu’ils ne puissent exécuter que le seul script en tant que postgres
.
Le moyen le plus sûr de passer des commandes à psql
dans un script consiste à rediriger une chaîne ou à transmettre un here-doc.
La documentation relative à l'option -c/--command
entre dans les détails lorsqu'elle doit être évitée.
-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
Pour répondre à la question de @Jason, dans mon script bash, j'ai écrit quelque chose comme ça (pour mon propos):
dbPass='xxxxxxxx'
.....
## Connect to the DB
PGPASSWORD=${dbPass} psql -h ${dbHost} -U ${myUsr} -d ${myRdb} -P pager=on --set AUTOCOMMIT=off
Une autre façon de le faire est:
psql --set AUTOCOMMIT=off --set ON_ERROR_STOP=on -P pager=on \
postgresql://${myUsr}:${dbPass}@${dbHost}/${myRdb}
mais vous devez faire très attention au mot de passe: je ne pouvais pas créer un mot de passe avec un '
et/ou un :
pour travailler de cette façon Alors abandonné à la fin.
-S