Bash script for interactive ssh and mysql commands - mysql

I'm studying MySQL, and every time I have to
Enter ssh XXX#XXX command, and enter my password to the school server.
Enter mysql -u XXX -p command, and enter MySQL password.
I want to create a Bash script for performing the steps above automatically.
I can accomplish the first step with this code:
#!/usr/bin/expect -f
set address xxx.com
set password xxx
set timeout 10
spawn ssh xxx#$address
expect { "*yes/no" { send "yes\r"; exp_continue} "*password:" { send "$password\r" } }
send clear\r
interact
But I don't know how to automatically input the next command (mysql -u xxx -p) and the password.
How can I do this?

You don't need such a complex script to just enter the MySQL console on remote machine. Use the features of the ssh tool:
ssh -tt user#host -- mysql -uuser -ppassword
The -t option forces pseudo-terminal allocation. Multiple -t force tty allocation, even if ssh has no local tty (see man ssh). Note the use of -p option. There must be no spaces between -p and password (see the manual for mysql).
Or even connect via mysql directly, if the MySQL host is accessible from your local machine:
mysql -hhost -uuser -p
Don't forget to adjust the shebang:
#!/bin/bash -

Use my.cnf to store your password securly like ssh keys.
https://easyengine.io/tutorials/mysql/mycnf-preference/
Same way ssh is also possible through ssh -i parameter and passing the private key path of the remote host.
Best of luck!

Related

Import mysql dump from local to SSH

I cannot find a solution to this particular demand.
I have a mysql dump on my computer and I want to import it in a web server using SSH.
How do I do that ?
Can I add the ssh connection to the mysql command ?
Edit :
I did it with SCP
scp -r -p /Users/me/files/dump.sql user#server:/var/www/private
mysql -hxxx -uxxx -pxxx dbname < dump.sql
As the comment above says, the simplest solution is to scp the whole dump file up to your server, and then restore it normally. But that means you have to have enough free disk space to store the dump file on your webserver. You might not.
An alternative is to set up a temporary ssh tunnel to your web server. Read https://www.howtogeek.com/168145/how-to-use-ssh-tunneling/ for full instructions, but it would look something like this:
nohup ssh -L 8001:localhost:3306 -N user#webserver >/dev/null 2>&1 &
This means when I connect to port 8001 on my local host (you can pick any unused port number here), it's really being given a detour through the ssh tunnel to the webserver, where it connects to port 3306, the MySQL default port.
In the example above, your user#webserver is just a placeholder, so you must replace it with your username and your webserver hostname.
Then restore your dump file as if you're restoring to a hypothetical MySQL instance running on port 8001 on the local host. This way you don't have to scp the dump file up to your webserver. It will be streamed up to the webserver via the ssh tunnel, and then applied to your database directly.
pv -pert mydumpfile.sql | mysql -h 127.0.0.1 -P 8001
You have to specify 127.0.0.1, because the MySQL client uses "localhost" as a special name for a non-network connection.
I like to use pv to read the dumpfile, because it outputs a progress bar.
You can try this solution for your problem :
Login using SSH details :-
SSH Host name : test.com
SSH User : root
SSH Password : 123456
Connect SSH :-
ssh root#test.com
enter password : 123456
Login MySQL :-
mysql -u [MySQL User] -p
Enter Password :- MySQL Password
Used following command for Import databases :-
show databases; // List of Databased
use databasedname; // Enter You databased name to Import databased
source path; // Set path for Import databased for ex : /home/databased/import.sql
I hope this will helps you.
Yes, you can do it with one command, just use 'Pipeline' or 'Process Substitution'
For your example with 'Pipeline':
ssh user#server "cat /Users/me/files/dump.sql" | mysql -hxxx -uxxx -pxxx dbname
or use 'Process Substitution':
mysql -hxxx -uxxx -pxxx dbname < <(ssh user#server "cat /Users/me/files/dump.sql")
Example 2, get database dump from remote server1 and restore on remote server2 with 'Pipeline':
ssh user#server1 "mysqldump -uroot -p'xxx' dbname" | ssh user#server2 "mysql -uroot -p'xxx' dbname"
or 'Process Substitution':
ssh user#server2 "mysql -uroot -p'xxx' dbname" < <(ssh user#server1 "mysqldump -uroot -p'xxx' dbname")
Additional links:
what is 'Process Substitution':
http://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html
what is 'Pipeline':
http://www.gnu.org/software/bash/manual/html_node/Pipelines.html

Expect scripting: remote database backup automation

I'm looking for a kind of remote database backup automation.
Then, I came across a scripting language which commonly used for administrative tasks, "Expect scripting" and I believe it could serve my purpose very well.
what I'd like to do is I want to perform login to a remote server using the following bash script from my local linux box. (supposed everything has been set properly, SSH authentication via generated key pair, so no password is required)
For the most important part, I'd like to send a mysqldump command to perform backup for my database on that server.
#!/usr/bin/expect
set login "root"
set addr "192.168.1.1"
spawn ssh $login#$addr
expect "#"
send "cd /tmp\r"
expect "#"
send "mysqldump -u root -ppassword my_database > my_database.sql\r"
expect "#"
send "exit\r"
The only problem I found here was after the line send "mysqldump -u root....... ".
It was never waiting until the process to finish, but immediately exit the shell with 'send "exit\r"' command line.
what do I do to make it waits until mysqldump command finish and log off the SSH properly?
I don't know the answer to your question: add exp_internal 1 to the top of the program to see what's going on.
However, since you have ssh keys set up, you don't really need expect at all:
ssh $login#$addr 'cd /tmp && mysqldump -u root -ppassword my_database > my_database.sql'

Setting mysql as shell

I have a user on my machine that is only supposed to run mysql. Is there any way that I can set the shell of that user to mysql and login using password and username?
I know how to change the shell to the mysql binary
usermod -s /usr/bin/mysql
That is working indeed, only I can't provide a username/password in the program. Usually user/pw are given as
mysql -u $USER -p
I can not provide parameters for a shell as in
usermod -s "/usr/bin/mysql -u $USER -p" # Does not work!
Also using a simple shell-script as shell does not work:
#!/bin/sh # mysqlShell
/usr/bin/mysql -u $USER -p
----
usermod -s mysqlShell # does not work
So how can I provide parameters to a program I use as a shell for a user?
Thanks to Tom Regner I could figure out a solution using .my.cnf containing
[client]
host=localhost
user=$user
password=$pass
disable-auto-rehash
where mysql is set to the shell. I still would like give the password manually but this is the best I found.
Setup a $HOME/.my.cnf file for the user
[client]
host=localhost
user=mysqluser
password=mysqlpass
then set a bash as login shell and put the following in $HOME/.bashrc
exec mysql --host=localhost dbname
that should do what you want, while the user in question just has to give one password (the system account password on login).
exec replaces the shell process with the mysql process.
If this does not work as expected, you may need to adjust $HOME/.bash_profile to source .bashrc:
[[ -f ~/.bashrc ]] && . ~/.bashrc
It might be enough to provide an appropriate .my.cnf and setting /usr/bin/mysql as shell, but this way you can pass arbitrary commandline options/flags to the mysql client.
You can do that by editing the user's account details in the /etc/passwd and change the default shell.
You need a login password (unless you set up ssh appropriately). Use the following command: sudo passwd username to change that login password.
You also need a mysql password. Use SET PASSWORD Mysql request.
If you want the user to be connected to some fixed database with some fixed password, code a small C wrapper (then, make the executable only executable by your Unix user) doing mysql_real_connect, or calling some exec function for mysql --user=username --password=password databasename but I don't recommend doiing the later (because ps aux will show the password, and that is a security risk).
Perhaps, since MySQL is free software, you could customize the source code of mysql for your particular needs.
Perhaps using a restricted shell and carefully configuring it is better.

execute mysql on remote server via bash script

I need to execute a mysql command on a remote server but seem to be hitting problem when it comes to executing the actual mysql bit
#!/usr/bin/expect -f
spawn /usr/bin/ssh -t root#10.0.0.2
expect "password: "
sleep 1
send "password\r"
sleep 2
/usr/bin/mysql databasename -e "update device_log set status = 'Y' where device_id in ('1','2');"
basically I want to change the flag to Y on device id's 1&2
but the script outputs
invalid command name "/usr/bin/mysql"
Just append the mysql command to the ssh command to run it in one go, like this:
#!/usr/bin/expect -f
spawn /usr/bin/ssh -t root#10.0.0.2 /usr/bin/mysql databasename -e "the query"
expect "password: "
sleep 1
send "password\r"
I'm not very much into expect, but I'm expecting that your attempt in the mysql line isn't actually valid syntax for expect to run a command.
Additionally:
You should use SSH keys for passwordless login instead of having a root password hardcoded in a script.
Consider running MySQL remotely e.g. mysql -h 10.0.0.2 -e "the query", or
Use port forwarding in SSH to connect to MySQL securely, e.g. run ssh -L 3307:localhost:3306 root#10.0.0.2 in the background and then connect to TCP port 3307 on localhost mysql -h 127.0.0.1 -P 3307.
It sounds like /usr/bin/mysql is not the the path to the mysql binary on that remote server. You could use just mysql instead, assuming that the binary is somewhere in that remote server's PATH. Otherwise you will have to go and find out where the binary is actually located and alter the absolute path accordingly.

Making an alias for SSH MySQL login using ENDSSH heredoc

I want to make an alias that is kept in my bashrc file to log into a remote MySQL db via SSH.
Assume that I can't add/alter any files on the remote machine that I'm SSHing into. Here's the relevant code.
function ssh_mysql {
echo "SSHing to $server"
ssh -t -t $suser#$server <<ENDSSH
eval "mysql -h "$host" -u $user -p $pass $db"
ENDSSH
}
alias wt_mysql=ssh_mysql
The Problem: Entering 'wt_mysql' into the terminal as an alias SSHs and logs into MySQL fine.. but when trying to enter any command/query/etc at the MySQL prompt, none of what I've submitted is executed/run. Including the 'exit' command. I have to ctrl C to get back to my local terminal. although its a bit out of my understanding I believe the problem is related to this topic, Terminating SSH session executed by bash script
How can I make sure that mysql and any subsequent commands are executed remotely?
Thanks!
I don't understand why you're using eval (or why you're passing the -t switch twice).
I would expect this ssh command to do what you want:
ssh -t $suser#$server "mysql -h '$host' -u $user -p $pass $db"