insert bash-variables in psql-command - bash

I'm going crazy while trying to insert bash-variables in a psql commands as connection paramters as well as variables in the command itself. The following example works properly:
psql -U postgres -h localhost -p 5432 -c "CREATE DATABASE testdb WITH ENCODING='UTF8' OWNER=postgres TABLESPACE=pg_default TEMPLATE=template_postgis CONNECTION LIMIT=-1;"
Now I'm trying to exchange each parameter through a variable, which is held in special config-file.
Non-working example:
dbserver=localhost
dbport=5432
dbowner=postgres
dbname=testdb
dbtemplate=template_postgis
dbtablespace=pg_default
psql -U '$dbowner' -h '$dbserver' -p '$dbport' -c "CREATE DATABASE '$dbname' WITH ENCODING='UTF8' OWNER='§dbowner' TABLESPACE='$dbtablespace' TEMPLATE='$dbtemplate'
CONNECTION LIMIT=-1;"
I've tried several quotings, backquotes and escape-slashes already but smhow it still won't work.
Thanks in advance, knutella

Use double quotes ("). Single quotes (') does not interpret shell variables inside.
Try it
echo '$USER' "$USER"
See man bash.

This works... most of the quotes are not needed:
psql -U $dbowner -h $dbserver -p $dbport -c "CREATE DATABASE $dbname WITH ENCODING='UTF8' OWNER=$dbowner TABLESPACE=$dbtablespace TEMPLATE=$dbtemplate CONNECTION LIMIT=-1;"

Related

How do I add '\c' to a psql command executed from a bash script?

To set up my project, I have to do quite a few commands and I'm trying to script this away. Some of these are in psql; so normally I'd go
psql -U postgres -h localhost -p 5433
(psql) create database test_database
(psql) \c test_database
(psql) \i integration-test/src/test/resources/init.sql
The .init.sql contains stuff to fill the database with mock data.
In my bash script, I tried reducing this to
psql -U postgres -h localhost -p 5433 -c "create database test_database; \c test_database; \i integration-test/src/test/resources/init.sql"
However, this gets me
ERROR: syntax error at or near "\"
LINE 1: create database test_database; \c fcs_analytics; \i integrat...
^
How do I execute these commands properly from my script?
Have you tried ?
psql -U postgres -h localhost -p 5433 << 'EOF'
create database test_database
\c test_database
\i integration-test/src/test/resources/init.sql
EOF

How to escape 3 level in bash (su command, psql, then query)

I'm working on a bash script used to install an application on a server and create a postgresql user for the application.
The matter is that if the user contains a special char, it's not escaped. So I would like to escape the name in the query.
Here is a part of my code:
db_user="test-test"
db_password=1234
su - postgres -c "psql -c \"CREATE USER $db_user WITH PASSWORD '$db_password';\""
So I have to escape:
the command for su -c ...
the query for psql -c ...
the user name in $db_user
the password in $db_password
Of course, if I add quotes around $db_user it's not working anymore. I tried others solutions, but none working.
Any idea?
Thanks
Let the shell do the work for you for you. In this case, that means printf '%q' -- which returns an eval-safe version of each literal argument.
cmd=( psql -c "CREATE USER $db_user WITH PASSWORD '$db_password';" )
printf -v cmd_q '%q ' "${cmd[#]}"
su - postgres -c "$cmd_q"
By the way, substituting literal text into SQL queries this way is massively insecure -- but if you follow the process above you're prone to only SQL injection bugs, not shell injection bugs.
To avoid SQL injection bugs as well, you want to avoid textual substitution of values into your queries at all.
# This is inefficient, but makes it completely unambiguous that our heredocs are literal
query=$(cat <<'EOF'
CREATE USER :new_user_name WITH PASSWORD :'new_user_password';
EOF
)
cmd=(
psql \
--set=new_user_name="$db_user" \
--set=new_user_password="$db_password"
-c "$query"
)
printf -v cmd_q '%q ' "${cmd[#]}"
su - postgres -c "$cmd_q"
See http://caryrobbins.com/dev/postgres-scripting/ for more on this technique. The classic XKCD linked in its header (also useful as a concrete example of the risks the original code was taking!) has its original source at https://xkcd.com/327/.

Get list of database names using psql

I'm trying to get a list of database names using the psql command. So far I have:
psql -h example.com -U backup -c '\l'
This however gives me the results in a table-like format. I ONLY want the table names (one on each line). How would I accomplish this?
This does it:
psql -h example.com -U backup -t -A -c "SELECT datname FROM pg_database WHERE datname <> ALL ('{template0,template1,postgres}')"
Using the system catalog pg_database.
Read the manual about psql.
I don't think you can use \l for that.
But the following should do it:
psql -h example.com -U backup -t -c "select datname from pg_database"
\t turns off the header and the other "noise". And the select statement only returns the database name.
Not sure if you need to use single quotes or double quotes for the SQL statement - on my Windows console I had to use double quotes.

bash script returns error "ERROR: syntax error at end of input LINE 1: SELECT" for psql request to copy the table to an external file

What should I do for making it work?
#!/bin/bash
TABLENAMES="user_stats"
ssh -t railsapps#xxx.xxx.xxx.xx -p xxx bash -c "'
for TABLENAME in $TABLENAMES
do
psql -d mydb -P format=unaligned -P tuples_only -P fieldsep=\, -c "SELECT * FROM $TABLENAME" > /tmp/$TABLENAME
done
'"
General problem: how to periodically dump the database tables to a local machine from a psql database in a single bash script run on Mac OS X?
Firstly, you should test your SQL and bash scripts remotely (do SSH interactively).
I think your problem is caused by a bad mix of quote / double-quote. I think the star (*) and $TABLENAME are expensed before the SSH call, so too early. Try to put a backslash before the $ sign.
You should use the verbose or the debug option, to help to understand what is really executed:
ssh -t railsapps#xxx.xxx.xxx.xx -p xxx bash -vxc "'
for TABLENAME in \$TABLENAMES; do
psql -d mydb -P format=unaligned -P tuples_only -P fieldsep=\, -c "SELECT \* FROM \$TABLENAME" > /tmp/\$TABLENAME
done
'"

Executing Bash script: ERROR: unterminated quoted string at or near

I get an error while executing the following psql statement inside a bash script:
execlog "psql -h $HOST -p $PORT -U $USER -d $DB -q -c 'CREATE EXTENSION hstore;'"
The raised error is:
ERROR: unterminated quoted string at or near "'CREATE"
LINE 1: 'CREATE
^
Thus, the single terminating quote is not recognize as it should be.
When using escaped double quotes instead single quotes (...\"CREATE EXTENSION hstore;\") I get the same error.
When executing the command directly from the command line, everything works fine.
Does someone know what's going wrong?
To give some additional info:
OS: Ubuntu 11.10, Postgresql Verion: 9.1
Thanks in advance,
Richard
Solved: The execlog function produces the error. Now I am calling
log "exec psql -h $HOST -p $PORT -U $USER -d $DB -q -c 'CREATE EXTENSION hstore;'"
which works fine!
Thanks for your help!
The problem is that after quote removal, the single quotes are no longer treated as syntax to escape the space, but literal characters as part of the string. Try
execlog psql -h $HOST -p $PORT -U $USER -d $DB -q -c 'CREATE EXTENSION hstore;'
(I can't find any information on execlog, so I don't know if the above will work.)

Resources