Invoking a bash command with an argument '#' in it - bash

Consider the following code:
sqls='/mnt/c/alias/Binn/SQLCMD.EXE -b -S HostName -U Username -P MyPW# -d dbName'
which is the prefix of the command to connect to the SQL Server DB dbName with username Username on the HostName
`$sqls -Q "select 1;"`
executes select 1 statement on it and it works as expected.
$($sqls -Q "select 1;")
fails. Why? Is it because of the '#' in the password? How should I change the sqls line above so it works with $(...) expression?

Storing a command in a string is prone to failure. We could work out why it's not working, but the better thing to do would be to use a function:
sql() {
/mnt/c/alias/Binn/SQLCMD.EXE -b -S HostName -U Username -P 'MyPW#' -d dbName -Q "$1"
}
This allows the password to be quoted, removing the possibility that it can break the command.
Use it like sql 'select 1'. Save the result using a standard command substitution:
foo=$(sql 'select 1')
Also bear in mind that you can use a config file (possibly $HOME/.my.cnf, but it looks like you're on Windows so not sure) to store default user, pass and database, enabling you to run queries without passing all those options every time.

Related

Insert json in postgres via bash script using kubectl

I'm trying to update a field in one of my table using bash script. I'm trying to insert json values inside of this field in postgress. The field type is 'text'. Here is the query which I try to execute:
TOKEN="${ENV_TOKEN}"
kubectl exec -it postgres-d5b5794-7fxxm -n eclipse-che -- bash -c "psql keycloak -c UPDATE federated_identity SET token ={"access_token":"'$TOKEN'","expires_in":86400,"scope":"user:full","token_type":"Bearer"} WHERE federated_username = 'admin'"
After executing this code I got the following error:
psql: warning: extra command-line argument "SET" ignored
psql: warning: extra command-line argument "token" ignored
psql: warning: extra command-line argument "=access_token:sha256~g1KaHT3-RSa2G1oPfDboc7jI90OLy67VQ4mJsVjFYZw" ignored
psql: warning: extra command-line argument "=expires_in:86400" ignored
psql: warning: extra command-line argument "=scope:user:full" ignored
psql: warning: extra command-line argument "=token_type:Bearer" ignored
psql: warning: extra command-line argument "WHERE" ignored
psql: warning: extra command-line argument "federated_username" ignored
psql: warning: extra command-line argument "=" ignored
psql: warning: extra command-line argument "admin" ignored
psql: FATAL: role "federated_identity" does not exist
command terminated with exit code 2
I've tried everyting to avoid the quotes but nothing works...
Can someone please help me to make work this query?
I have not tried to add JSON object but here is working syntax for CREATE & INSERT with kubectl. Best way would be to put your SQL statement within file to avoid the pain of ensuring double/sungle quotes are escaped properly or not. Escaping quotes becomes very complex with few values only. My recommendation is to use *.sql file with all your SQL statements.
SQL file execution with kubectl
kubectl exec -i <pod-name> -- bash -c "psql -U postgres -f /tmp/create.sql"
Create table
kubectl exec -i <pod-name> -- bash -c "psql -U postgres -c \"CREATE TABLE account1 (user_id INT PRIMARY KEY, username VARCHAR(50) NOT NULL, Password VARCHAR(50) NOT NULL, email VARCHAR(255) NOT NULL);\""
Insert record into table
kubectl exec -i <pod-name> -- bash -c "psql -U postgres -c \"INSERT INTO account1 VALUES (1, 'dummyuser', 'dummypassword', 'dummy#gmail.com');\""
The fundamental problem is that the string after psql -c should be quoted as a single argument, but you are already using both single and double quotes in it, so attempting to just add more quotes is not sufficient.
Because you can't easily escape single quotes within single quotes, the simplest solution is probably to add double quotes around the string, and backslash-escape any existing double quotes within.
kubectl exec -it postgres-d5b5794-7fxxm -n eclipse-che -- bash -c "psql keycloak -c \"UPDATE federated_identity SET token ={\\\"access_token\\\":\\\"'$TOKEN'\\\",\\\"expires_in\\\":86400,\\\"scope\\\":\\\"user:full\\\",\\\"token_type\\\":\\\"Bearer\\\"} WHERE federated_username = 'admin'\""
Because I had to guess which quotes belong to which level of nested string, this probably needs some adjustments. Try to add printf '%s\\n' in front of psql keycloak to have the container simply print out the result. I would imagine that you might need more quoting around the JSON string, but I'm not familiar enough with psql to guess what that should look like. Also, the quoting around $TOKEN looks wrong (and it seems rather pointless to copy $ENV_TOKEN to a new identical variable which you do not change at all).
If kubectl exec -it postgres-d5b5794-7fxxm -n eclipse-che -- bash lets you read from standard input (not in a place where I can check that) you might be able to use a here document instead:
kubectl exec -it postgres-d5b5794-7fxxm -n eclipse-che -- bash <<____
psql keycloak -c "UPDATE federated_identity SET token ={\"access_token\":\"'$TOKEN'\",\"expires_in\":86400,\"scope\":\"user:full\",\"token_type\":\"Bearer\"} WHERE federated_username = 'admin';"
____
Again, I had to guess some things. If you can't get this to work, perhaps update your question to explain in more detail what the code is expected to do.

PostgreSQL export result as CSV from remote server

I have read all other solutions and none adapts to my needs, I do not use Java, I do not have super user rights and I do not have API's installed in my server.
I have select rights on a remote PostgreSQL server and I want to run a query in it remotely and export its results into a .csv file in my local server.
Once I manage to establish the connection to the server I first have to define the DB, then the schema and then the table, fact that makes the following lines of code not work:
\copy schema.products TO '/home/localfolder/products.csv' CSV DELIMITER ','
copy (Select * From schema.products) To '/home/localfolder/products.csv' With CSV;
I have also tried the following bash command:
psql -d DB -c "select * from schema.products;" > /home/localfolder/products.csv
and logging it with the following result:
-bash: home/localfolder/products.csv: No such file or directory
I would really appreciate if someone can show a light on this.
Have you tried this? I do not have psql right now to test it.
echo “COPY (SELECT * from schema.products) TO STDOUT with CSV HEADER” | psql -o '/home/localfolder/products.csv'
Details:
-o filename Put all output into file filename. The path must be writable by the client.
echo builtin + piping (|) pass command to psql
Aftr a while a good colleague deviced this solution which worked perfectly for my needs, hope this can help someone.
'ssh -l user [remote host] -p [port] \'psql -c "copy (select * from schema.table_name') to STDOUT csv header" -d DB\' > /home/localfolder/products.csv'
Very similar to idobr's answer.
From http://www.postgresql.org/docs/current/static/sql-copy.html:
Files named in a COPY command are read or written directly by the server, not by the client application.
So, you'll always want to use psql's \copy meta command.
The following should do the trick:
\copy (SELECT * FROM schema.products) to 'products.csv' with csv
If the above doesn't work, we'll need an error/warning message to work with.
You mentioned that the server is remote, however you are connecting to a localhost. Add the -h [server here] or set the ENV variable
export PGHOST='[server here]'
The database name should be the last argument, and not with -d.
And finally that command should have not failed, my guess is that that directory does not exist. Either create it or try writing to tmp.
I would ask you to try the following command:
psql -h [server here] -c "copy (select * from schema.products) to STDOUT csv header" DB > /tmp/products.csv

run psql query in bash

I am new in bash and psql, I want to write a bash code that login a server the connect to psql database do a select query and then return the output. the set up I have as follow.
server named dbs, it has psql install and running. database name = dname, user= tester passwrod = 1234
in the database there is table called node_info it has 3 colons ip, mac, connection_time.
I want to run following query
select ip, connection_time from node_info where ip=10.10.10.2;
Any tips how to write a shell script to do this remotely?
If you have properly set your "pg_hba.conf" configuration file to achieve remote connections, you may try the following:
psql -U tester -h remoteip -p remoteport -d dname -W -c "select ip, connection_time from node_info where ip='10.10.10.2'"

How to get text that is printed into console using sybase procedure into shell script

I have a sybase procedure which prints data like: print 'Hello World'.
How can I get that text into shell script. In other words how can a shell script read from the console of the database?
You can do this a couple of different ways. If you have a script file that you are running, do the following to specify an output file:
isql -U username -P password -S servername -i Inputscript.name -o outputfile.name
It will run the script, and output the results into the file specified by the -o
To run isql 'interactively' in your script you can do the following within your shell script:
isql -U username -P password -S servername -b << ENDSQL >> outputfile.name
set nocount on \*stops displaying rows affected count*\
go
select some, data from table
go
ENDSQL
You can also use the example above to set the results of a query to a variable:
myvar = `isql -U username -P password -S servername << ENDSQL
sp_my_procedure
go
ENDSQL`
A couple of notes. If you are executing SQL statements, and are going to use the results in other processing (e.g. not just trying to print them), you will likely want to set nocount on within your SQL to prevent affected rowcount from printing, and use the -b flag in your isql connection string to prevent headers from being printed.

grant command is not working in shell script because of syntax error

I am stuck with an issue with shell scripting.
I have already used \ character before double quotes (") because of some reason, as in the following line of my shell script.
sql2=\"grant all on \${db_name}.* to \${db_user}#\${host} identified by \${dbpass};\";
But as in the MySQL "grant" command syntax, I need to put double quotes before and after \${dbpass}, which is the part of the shell script line I given above.When I put like this, \"\${dbpass}\", it is throwing syntax error during execution.What should I need to solve this.
This is an update.
This is the shell script which I want to run.
ssh -t qbadmin#10.3.2.0 '
su root -c "
echo \"Give db name :\";
read db_name;
echo \"Give password :\";
read db_pass;
host=localhost;
sql1=\"create database \$db_name;\";
sql2=\"grant all on \${db_name}.* to \${db_name}#\${host} identified by \"\${db_pass}\";\";
sql3=\"\${sql1}\${sql2}\";
echo \"==============\";
mysql -u root -p -e \"\${sql3}\";
";
'
Please refer this script and please let me know the necessary changes i need to do with this.
Thanks.
Try this
db_name="yourdbname"
db_user="yourdbuser"
host="yourhost"
dbpass="yourdbpass"
sql2="grant all on ${db_name}.* to ${db_user}#${host} identified by ${dbpass};"
echo $sql2 | mysql -u yourusername -pmysql

Resources