Loop, array, mysql, Bash, Linux - mysql

I want to write a script that sends the select to the database
data_path="https://localhost/public/"
data_name=(PXL_20220628_152928222.mp4 PXL_20220628_163301667.mp4)
for q in "${data_name[#]}";
do
data_l=$(sudo mysql -h localhost -P 3306 -u ck****** -p"*******" -e "SELECT iddata FROM
ck*****.data WHERE links = '$data_path$q'")
done
echo "$data_l"
In response I get only one record (id first file PXL_20220628_152928222.mp4 )
The loop is not working

I copied your script to a file with a shebang, added an echo in front of the sudo to show the command being executed and moved the one AFTER the loop inside to show the result.
#! /bin/bash
data_path="https://localhost/public/"
data_name=(PXL_20220628_152928222.mp4 PXL_20220628_163301667.mp4)
for q in "${data_name[#]}"; do
# data_l=$(sudo mysql -h localhost -P 3306 -u ck****** -p"*******" -e " SELECT iddata FROM ck*****.data WHERE links = '$data_path$q'
data_l=$(echo "$q")
echo "$data_l" # this was outside the loop
done
# echo "$data_l" # not here, this only reports the LAST value
Running it:
PXL_20220628_152928222.mp4
PXL_20220628_163301667.mp4
You were assigning it, but not reporting it, then overwriting with the second assignment, and only reporting that one after the loop was done.
Just move the echo at the end inside the loop.

Related

Expand selected variables within here-document while invoking Bash through SSH

I don't have remote access to a MySQL server, so I am trying to do it via an SSH session.
It partly works, but not correctly.
sshpass -p $password ssh user#$IP /bin/bash << EOF
mysql -N -uroot -ppassword test -e "select id from client where user ='$user'"
EOF
This will show the result of the select statement, but I'd like to be able to use that result in another echo statement.
eg:
The user ID is: xxxxx
I tried to assign the output to a variable using:
sshpass -p $password ssh user#$IP /bin/bash << EOF
res=$(mysql -N -uroot -ppassword test -e "select id from client where user ='$user'")
echo $res
EOF
But that results in:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/run/mysql/mysql.sock' (2)
If I quote EOF like 'EOF' then I can get the result into res but I lose the ability to use $user
Is there anyway to do this so I can use my variable in the heredoc and get the result of the MySQL query to a new variable ?
If I quote EOF like 'EOF' then I can get the result in to res but I lose the ability to use $user
You can pass $user to bash as a positional parameter and still have the quoted EOF and its advantages. E.g:
sshpass -p "$password" ssh "user#$IP" /bin/bash -s "$user" << 'EOF'
res=$(mysql -N -uroot -ppassword test -e "select id from client where user ='$1'")
echo $res
EOF
Bash manual describes the -s option as follows.
If the -s option is present, or if no arguments remain after option processing, then commands are read from the standard input. This option allows the positional parameters to be set when invoking an interactive shell or when reading input through a pipe.

Why is this bash variable blank when taking output from mysql?

I am trying to take the output from a MySQL query in bash and use it in a bash variable, but it keeps coming up blank when used in the script, but works perfectly from the terminal. What's wrong here?
I've tried changing the way the statement is written and changing the name of the variable just in case it was somehow reserved. I've also done a significant amount of searching but it turns out if you but 'bash', 'blank', and 'variable' in the search it usually comes up with some version of how to test for blank variables which I already know how to do.
tempo=$(mysql -u "$dbuser" -p"$dbpass" -D "$database" -t -s -r -N -B -e "select user from example where user='$temp' > 0;")
printf "the output should be: $tempo" # This is a test statement
The end result should be that the $tempo variable should either contain a user name from the database or be blank if there isn't one.
I think there is some error with your sql statement at user = '$temp' > 0.
But to get the result from MySql you have to redirect the standard error (stderr) to the standard output (stdout), you should use 2>&1.
Most probably you will run into MySql error but try running this on terminal.
tempo=$((mysql -u "$dbuser" -p"$dbpass" -D "$database" -t -s -r -N -B -e "select user from example where user='$temp' > 0;") 2>&1)
The solution was to echo the result of the sql query like this:
tempo=$(echo $(mysql -u "$dbuser" -p"$dbpass" -D "$database" -s -N -B -e "select user from example where user='$username' > 0;"))
Now I'm left with logic issues but I think I can handle that.

Execute bash command in batch with mysql results

I maintain several servers having the same web app through bash scripts. Commands include basically ssh and scp, and they are the same for every server, just the IP, the user and the port are different between servers. So far I wrote as many commands as servers to maintain in same script. This works well but as I start to have many servers to maintain, I would prefer to list these servers in a MySQL table, and then use this list in my bash scripts, thus I I would not need to keep all of them updated when I have new servers to maintain.
Currently I have problems to extract data from MySQL in a proper way that could be then executed in bash script.
My current approach is to use CONCAT function in the query as follow:
outputofquery=$($MYSQL -u"$USER" --batch -p"$PASSWORD" --skip-column-names -h"$HOST" -e "SELECT CONCAT('scp -P ', server_port, ' $file ', server_user, '#', server_ip, ':/var/www/html/site/') FROM server_ssh;" $DBNAME)
echo ${outputofquery%$'\t;'*}
Giving the following result:
scp -P 22 text.php user1#1.1.1.1:/var/www/html/site/ scp -P 12345 text.php user2#2.2.2.2:/var/www/html/site/
Every command resulting from the MySQL query is put on the same line, meaning that this cannot be executed..
I though to add a semicolon just after site/ in the query, so that even if every command is on the same line, they could be executed independently but it happens that only the last scp command gets executed and those before are ignored.
Could you please let me know how I could execute ssh and scp commands in batch with data coming from a MySQL table?
Finally I succeed to execute batch commands with MySQL data. I build the commands to execute with concatenate function, depending on the line number extracted from MySQL. Below is my script
#!/bin/sh
HOST="localhost"
USER="root"
DBNAME="mydb"
PASSWORD="mypassord"
MYSQL="/Applications/XAMPP/bin/mysql"
file='text.php'
i=0;
command='';
ips_and_ports=$($MYSQL -u"$USER" -p"$PASSWORD" -h"$HOST" -BNe "SELECT server_port,server_user,server_ip FROM server_ssh;" $DBNAME)
for line in $ips_and_ports
do
(( i++ )); #increment the line number
if [ $(($i % 3)) -eq 1 ] #check if it is the first element of a line extracted from MySQL (server_port)
then
command="scp -P $line"; #initialize a new command to execute
elif [ $(($i % 3)) -eq 2 ] #check if it is the second element of a line extracted from MySQL (server_user)
then
command+=" $file $line#"; #concatenate
elif [ $(($i % 3)) -eq 0 ] #check if it is the third element of a line extracted from MySQL (server_ip)
then
command+="$line:/var/www/html/my_web_app/;"; #concatenate
eval $command; #execute the command
fi
done;
I can't put a comment because I'm new.
Have you tried to put a \n or && at the end of your mysql concatenation ?
You can also change the approach and assign the server and the port to variables and loop over these variables to execute the ssh and the scp command. For example
ips_and_ports=$($MYSQL -u"$USER" --batch -p"$PASSWORD" --skip-column-names -h"$HOST" -e "SELECT server_port, server_ip FROM extranet.server_ssh;" $DBNAME)
for $line in $ips_and_ports
do
OLDIFS=$IFS;
IFS=" "; # set the separator to the tab character (PS: this is 4 spaces, change accordingly )
for $el in $line
do
set -- $el; # separate each line by tab and assign the variables to $1, $2 ..
port=$1;
ip=$2;
scp -P 22 text.php user1#$ip:/var/www/html/site/ scp -P $port
done;
IFS=$OLDIFS; # put the separator back to it's original value
done;
I haven't tested the code but I hope you got my idea !
Good luck
more infos about the IFS and OLDIFS in link

Bash script: MySQL query over SSH not queried as I want

I'm trying to run the following over SSH via a BASH script:
for register in ${#:3}; do
ssh host "mysql -u root -pPASSWORD -D DATABASE -e 'CALL DATABASE.domain('$2', '$register');'"
done
Where $2 is e.g "google.com" and $register is another domain which will loop depending how many registered domain I have, e.g "mydomain.com".
When I run the script the query cuts off ".com" only for $2 but inputs the right text for $register. So it looks like this if I use "google.com" and "mydomain.com":
for register in ${#:3}; do
ssh host "mysql -u root -pPASSWORD -D DATABASE -e 'CALL DATABASE.domain('google', 'mydomain.com');'"
done
When I echo out the text I get the full FQDN for $2 but not when I try to run it via mysql.

bash script to access multiple mysql databases

I all,
I have a series of MYSQL databases with different users and passwords, nevertheless the DB structure is the same for all databases.
I can't create a user with the same username and password to all of them and I need to quickly perform operations on all of them.
I was thinking about a bash script to run via cron.
Any suggestion? I was thinking to something like this but it is not working :(
#!/bin/bash
uconn=(
'mysql -u user_db1 --password=pass_db1 db1 '
'mysql -u user_db2 --password=pass_db2 db2 '
)
for f in "${uconn[#]}"
do
exec ${f}
echo `mysql show tables`
echo `mysql exit`
done
exit
Why not use the documented way?
do
${f} <<EOF
show tables
\\q
EOF
done
Just pasting the full code taking into consideration #Ansgar Wiechers:
#!/bin/bash
uconn=(
'mysql -u user_db1 --password=pass_db1 db1'
'mysql -u user_db2 --password=pass_db2 db2'
)
for f in "${uconn[#]}"
do
${f} <<EOF
show tables
\\q
EOF
done
exit
To execute the code from the local machine to the remote one this works for me:
ssh ssh_user#mydomain.com 'bash -s' < /local/path/to/multiple_db_connections.sh
where the content of multiple_db_connections.sh is the code above