I can connect to the console as root using an environment variable:
mysql -u root -p${MYSQL_ROOT_PASSWORD}
I’d like to be able to use a different environment variable in a statement
CREATE USER ${MYSQL_USER} IDENTIFIED BY ${MYSQL_USER_PASSWORD};
Which obviously doesn’t work (or why would I be asking). Is there any way I can use an environment variable in the console?
I don't think there's any way to access environment variables from MySQL queries. But you can construct the MySQL query and substitute variables in the shell.
mysql -e "CREATE USER '{$MYSQL_USER}' IDENTIFIED BY '${MYSQL_USER_PASSWORD}'"
The shell will substitute the variables into the string before it's passed to the mysql command. For longer queries you can use a here-doc:
mysql <<EOF
CREATE USER '{$MYSQL_USER}'
IDENTIFIED BY '${MYSQL_USER_PASSWORD}'
EOF
Related
You can avoid re-entering mysql command line password by putting the queries into a file.
In my case, the later queries are not determined until after the first queries have finished.
This happens in a non-interactive script so running a mysql console is not an option.
Is there any notion of a session for mysql command line interactions? Or can I set it up to listen for commands on a local unix socket (the output is required to be returned)? Or something like that?
User #smcjones mentions using the .my.cnf file or mysql_config_editor. Those are good suggestions, I give my +1 vote to him.
Another solution is to put the credentials in any file of your choosing and then specify that file when you invoke MySQL tools:
mysql --defaults-extra-file=my_special.cnf ...other arguments...
And finally, just for completeness, you can use environment variables for some options, like host and password. But strangely, not the user. See http://dev.mysql.com/doc/refman/5.7/en/environment-variables.html
export MYSQL_HOST="mydbserver"
export MYSQL_PWD="Xyzzy"
mysql ...other arguments...
I don't really recommend using an environment variable for the password, since anyone who can run ps on your client host can see the environment variables for the mysql client process.
There are a few ways to handle this in MySQL.
Put password in hidden .my.cnf in the home directory of the user the script is running as.
[client]
user=USER
password=PASSWORD
Use mysql_config_editor
mysql_config_editor set --login-path=client --host=localhost
--user=localuser --password
When prompted to enter your password, enter it like you otherwise would.
IMO this is the worst option, but I'll add it for the sake of completeness.
You could always create a function wrapper for MySQL that appends your set password.
#! /bin/bash
local_mysql_do_file() {
mysql -u localuser -h localhost -pPASSWORD_NO_SPACE < $1
}
# usage
local_mysql_do_file file.sql
I would like to create a shell script to run in docker CLI and create a MySQL user with the host IP passed as a command line variable.
So with my script it would be ./create_user.sh 172.17.0.1
I tried starting with inserting variable only in the sql statements part and using something like this:
#!/bin/sh
docker exec -i atb-mariadb bash <<'EOF'
mysql -uroot -pmypass
set #ip='172.17.0.1';
CREATE USER 'exporter'##ip IDENTIFIED BY 'mypass';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'exporter'#'172.17.0.1';
GRANT SELECT ON performance_schema.* TO 'exporter'#'172.17.0.1';
SELECT user, host FROM mysql.user;
exit
EOF
This results in syntax error, along with some others i tried :
CREATE USER CONCAT_WS('exporter','#',#ip) IDENTIFIED BY 'mypass';
CREATE USER 'exporter'#CONCAT_WS('',#ip) IDENTIFIED BY 'mypass';
This is of course only the variable within the sql statements part of the script. Using a variable in the overall shell script and passing that into the sql bash is a problem that I have not even been able to come to yet.
Thanks in advance for any help!
UPDATED
I tried Raymond Nijland's solution and it worked for the sql variable part. However, trying to pass the variable value through the command line is still failing for the following script:
#!/bin/sh
echo script received $1
docker exec -e ipa=$1 -i atb-mariadb bash <<'EOF'
echo exec received $ipa
mysql -uroot -pmypass -e "
SET #ip='${ipa}';
SET #createUser = 'CONCAT("CREATE USER exporter#",#ip,"IDENTIFIED BY'mypass'")';
PREPARE smtpCreateUser FROM #createUser;
EXECUTE smtpCreateUser;";
exit
EOF
with the output
$ ./create_user.sh 172.18.0.5
script received 172.18.0.5
exec received 172.18.0.5
mysql Ver 15.1 Distrib 10.2.9-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
Usage: mysql [OPTIONS] [database]
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf ~/.my.cnf
The following groups are read: mysql client client-server client-mariadb
The following options may be given as the first argument:
--print-defaults Print the program argument list and exit.
......and so on
I understad the usual approach is to run a separate .sql script file with the -e handle but unfortunately bind-mounting this file into the default mariadb container or creating a custom image are both not possible appraoches given the current requirements.
You should be able to generate dynamic SQL statements with CONCAT, PREPARE and execute them.
Query
SET #ip = '172.17.0.1';
SET #createUser = CONCAT(
"CREATE USER exporter#",#ip, " IDENTIFIED BY 'mypass'"
);
PREPARE smtpCreateUser FROM #createUser;
EXECUTE smtpCreateUser;
You need to grab the variable from the shell before it can be used in the query. I think you are looking for something like (make sure to remove the quotes from EOF):
#!/bin/sh
docker exec -i atb-mariadb bash <<EOF
ip="${1:-127.0.0.1}"
echo mysql -uroot -pmypass
echo CREATE USER 'exporter'#'${ip}' IDENTIFIED BY 'mypass';
GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'exporter'#'172.17.0.1';
GRANT SELECT ON performance_schema.* TO 'exporter'#'172.17.0.1';
SELECT user, host FROM mysql.user;
exit
EOF
I am using Ubuntu-server. Can I setup / configure 'mysql' to auto-connect to another host? I mean if I type mysql on my terminal, it will connect automatically to specific host.
Thanks.
There are two parts for the answer.
First - how to make an alias, a word that if you type it, a specific command will execute (taken from here:
Create ~/.bash_aliases if not exists
touch ~/.bash_aliases
Open ~/.bash_aliases in a editor and append alias MY_COMMAND_ALIAS="THE COMMAND YOU WANT"
or use command echo 'alias MY_COMMAND_ALIAS="THE COMMAND YOU WANT"' >> ~/.bash_aliases
Save it
Use reload source ~/.bash_profile command to reload profile or reopen the terminal
Second part - the command you want to run mysql command, it will be something like:
mysql -u $user -p$passsword -Bse "command1;command2;....;commandn"
You can write a simple wrapper like this:
#!/bin/sh
/usr/bin/mysql --user $MYSQL_USER -p $MYSQL_PASSWORD --host $MYSQL_HOST $*
Where that should work almost identically to the default mysql command with a few tiny exceptions, like how LOAD DATA INFILE will read files only on the server, not your local machine.
You may need to do the same for mysqldump and other related commands like mysqladmin if you use those.
Be sure to specify the actual path to the mysql binary you want to run. I'm using /usr/bin/mysql here but it could be something else.
You can avoid re-entering mysql command line password by putting the queries into a file.
In my case, the later queries are not determined until after the first queries have finished.
This happens in a non-interactive script so running a mysql console is not an option.
Is there any notion of a session for mysql command line interactions? Or can I set it up to listen for commands on a local unix socket (the output is required to be returned)? Or something like that?
User #smcjones mentions using the .my.cnf file or mysql_config_editor. Those are good suggestions, I give my +1 vote to him.
Another solution is to put the credentials in any file of your choosing and then specify that file when you invoke MySQL tools:
mysql --defaults-extra-file=my_special.cnf ...other arguments...
And finally, just for completeness, you can use environment variables for some options, like host and password. But strangely, not the user. See http://dev.mysql.com/doc/refman/5.7/en/environment-variables.html
export MYSQL_HOST="mydbserver"
export MYSQL_PWD="Xyzzy"
mysql ...other arguments...
I don't really recommend using an environment variable for the password, since anyone who can run ps on your client host can see the environment variables for the mysql client process.
There are a few ways to handle this in MySQL.
Put password in hidden .my.cnf in the home directory of the user the script is running as.
[client]
user=USER
password=PASSWORD
Use mysql_config_editor
mysql_config_editor set --login-path=client --host=localhost
--user=localuser --password
When prompted to enter your password, enter it like you otherwise would.
IMO this is the worst option, but I'll add it for the sake of completeness.
You could always create a function wrapper for MySQL that appends your set password.
#! /bin/bash
local_mysql_do_file() {
mysql -u localuser -h localhost -pPASSWORD_NO_SPACE < $1
}
# usage
local_mysql_do_file file.sql
i am trying to rewrite a script that is written in c-shell script to that uses sql plus command to get information from an oracle database but i am replacing it with mysql and i would like to replace all sqlplus syntax with mysql syntax. I am asking all the c-shell gurus to explain to me what this command means
set SQLPLUS=${ORACLE_HOME}/bin/sqlplus
set REPORT=${MYBD_HOME}/Scripts/report.sql
so somewhere along the line i invoke the sql plus command using the follwing
${SQLPLUS} ${MYDBUSER} # &{REPORT}
i am able to say i undertand what the right hand values mean ({ORACLE_HOME}/bin/sqlplus) is the path to where my sqplus command is located and thus i need it to invoke the command and the {REPORT=$(MYBD_HOME}/Scripts.report.sql) is the path where my sql script that is to be ran by invoking the sqplus command resides correct?
what i dont understand is what the set command is initializing this to. is SQLPLUS a variable so i dont have to type the path when i try to put it in my .csh script?
If so then all i need to do to run this script on a mysql database is simply set the SQLPLUS(problably change it to MYSQL) to point to the path where my msql exec is right
set MYSQL=${MYSQL_HOME}/bin/mysql
then just invoke mysql and run the sql statement
${MYSQL}${MYDBUSER}#${REPORT}
is this what i need to do ro tun the same .tsch script to get data from a mysql table?
You'll need something like this:
${MYSQL} -u $username -p$password -D $database < ${REPORT}
(The username and password are passed in differently to the mysql executable than they are passed to SQLPlus. You'll need to parse out the username and the password from ${MYDBUSER}. Likely, that contains a string such as "scott/tiger". The equivalent on the mysql command line client would be "-u scott -ptiger -D scott".
That # (at sign) is a SQLPlus thing; it tells SQLPLus to read input from the specified filename. The equivalent in mysql would be the source command, e.g.
${MYSQL} -u $username -p$password <_EOD!
use $database
source ${REPORT}
_EOD!
Also, your report.sql file likely includes spool and other SQLPLus specific commands. The mysql command line client is NOT ANYWHERE near as powerful a reporting tool as SQLPlus is.
Addendum:
Q: what exactly does the spool do?
The SQLPlus spool command directs output to a file. It's frequently used to create a log file from a SQLPLus session, and is also useful for creating report files.
set trimspool on
spool /tmp/file.lis
select 'foo' as foo from dual;
spool off
Q: Why can't i set the user name and passowrd to a variable and use that?
You could set a variable, the end result of the command line sent to the OS would be the same.
set MYDBUSER="-u username -ppassword -D database"
${MYSQL} ${MYDBUSER} <${REPORT}
Q:Seems like mysql is more verbose than sqlplus.
The mysql command line client takes unix-style options. These are equivalent:
mysql -u myusername -pmypassword -D mydatabase
mysql --user=myusername --password=mypassword --database=mydatabase