have an next case:
test3 = Mixlib::ShellOut.new("echo '1'")
test4 = Mixlib::ShellOut.new("mysql -u root --silent --skip-column-names --password='rootpass' -e 'some sql;'")
test3.run_command
test4.run_command
puts test3.stdout # => 1
puts test4.stdout # => empty string, nothing
expecting test4 to return result as test3
I guess maybe mysql returning result not to stdout, where then and how can I get the result
P.S I know about ruby gem mysql2 which I could use for doing this stuff, but to be honest no time to implement stuff like this just to getting only a simple SQL result, also I have tried run command without --silent and --skip-column-names flags, and this doesn't help too.
So the problem was, my command was returning code exit 1, it seems it was failing, so after fixing the command it works, the problem was in using single comma instead of double comma
Related
I need to suppress all error messages that the mysql command prints to stdout. I saw many other similar questions but all answers suggest workarounds to avoid these messages (check database/table/column exists before executing query). But I need the mysql command to return a failure exit code on error and don't print anything to output except the data explicitly requested in a query in a successful run. The -s key doesn't help in hiding error messages.
My task is to execute a MySQL query in a script and get either the requested data (printed with the -s key) or a non-zero exit code. I don't want to check each and every table/column/etc existence before executing a target query. How can I achieve this?
UPD: I tried this but it didn't help:
mysql ... db -s -N -e "SELECT config_id FROM core_config_data LIMIT 1;" 2> /dev/null
To sum it up:
You want the mysql command to:
not print any error
exit with a non-success code when a query fails
Then I've got good news for you! The output of errors will always be on stderr. Therefore you can just redirect the output to null or whatever you like.
root#icarus ~/so # mariadb -Dmaio290sql1 -e 'SELECT * FROM wp_users' -s 2> bla.txt
[actual content]
root#icarus ~/so # echo $?
0
root#icarus ~/so # mariadb -Dmaio290sql1 -e 'SELECT * FROM nope' -s 2> bla.txt
root#icarus ~/so # echo $?
1
The last query is throwing an error and therefore the exit code is not 0.
This was tested on MariaDB though: 10.3.27-MariaDB-0+deb10u1 Debian 10.
I'm developing an InSpec control that runs CIS compliance commands.
While working on MySQL, I'm stuck here:
Execute the following SQL statement to determine the value of datadir:
show variables where variable_name = 'datadir';
I need to extract the output from the above command and reuse it in the next command:
ls -l <THE OUTPUT OF THE PREVIOUS COMMAND>/.. | egrep "^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql"
The problem is that the first command is an SQL Request and the second command is a terminal command.
How can I put both of them (after getting the output of the first command and put it in the second one) in an InSpec control like the following:
control "mysql1" do
impact 1.0
title "Use dedicated Least Privileged Account for MySQL Daemon/Service"
desc "May reduce the impact of a MySQL-born vulnerability"
describe command ('ps -ef |e grep "^mysql.*$"') do
its('stdout') { should match ''}
end
end
Thank you for your help #Matt
I've read your answer and found it really helpful, except the last block of code : Does
egrep "^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql"
mean
it { expect(subject).to_not be_owned_by 'mysql' }
it { expect(subject).to_not be_grouped_into 'mysql' }
it { expect(subject).to_not be_executable_by 'mysql' }
?
Plus I did try all of the blocks you wrote previously and none of them did work.. And yes, I'm using linux 16.04
You can extract the output of the SQL request with the following method:
command('mysql -u <user> -p -e "show variables where variable_name = \'datadir\'"').stdout.split(' ')
The mysql -u <user> -p -e part is necessary to execute the SQL query from a Linux command. If you are using Window, you will probably need to make use of sqlcmd instead. This allows the SQL query to execute successfully with the command method.
The reason the command method works here is because it is a custom RSpec type (implicitly therefore also a class constructor in the sense that Ruby has constructors) that will execute locally or remotely on the tested system. The .stdout method is a member of the class to capture the stdout of the command. .split will ensure the output variables are stored in a whitespace-delimited array.
Now we can use it in the next command like so:
# store array of variables
variables = command('mysql -u <user> -p -e "show variables where variable_name = \'datadir\'"').stdout.split(' ')
# use array in command
variables.each do |variable|
describe command("ls -l #{variable}/.. | egrep \"^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql\"") do
its('stdout') { should match ''}
end
end
Above we iterate through the array of variables captured in the SQL query and test it in the describe command() RSpec test. A better way to execute this test would be to test the stdout of the command in the matcher and not the egrep. Doing that and cleaning up the match method:
# store array of variables
variables = command('mysql -u <user> -p -e "show variables where variable_name = \'datadir\'"').stdout.split(' ')
# use array in command
variables.each do |variable|
describe command("ls -l #{variable}/..") do
its('stdout') { should_not match(/^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql/)}
end
end
Updating to non-deprecated RSpec matchers and fixing the invoking of the stdout method as a string instead of a symbol we arrive at:
# store array of variables
variables = command('mysql -u <user> -p -e "show variables where variable_name = \'datadir\'"').stdout.split(' ')
# use array in command
variables.each do |variable|
describe command("ls -l #{variable}/..") do
its(:stdout) { is_expected.to_not match(/^d[r|w|x]{3}------\s*.\s*mysql\s*mysql\s*\d*.*mysql/)}
end
end
Another improvement we can make is to use a better suited file type and the permissions matchers instead of raw commands. This helps for platform-independent testing:
# store array of variables
variables = command('mysql -u <user> -p -e "show variables where variable_name = \'datadir\'"').stdout.split(' ')
# use array in file type
variables.each do |variable|
describe file("#{variable}/..") do
# check permissions
it { expect(subject).to_not be_owned_by 'mysql' }
it { expect(subject).to_not be_grouped_into 'mysql' }
it { expect(subject).to_not be_executable_by 'mysql' }
end
end
I understand there was a good bit here to implement the functionality you are looking for and many fixes and improvements as well, so be sure to examine the code and explanations closely to understand everything I did here.
So I need to read in a bunch of ID numbers from a file and do a mysql query on each of them. I started off with this:
#!/bin/bash
file="eidlist.txt"
while IFS= read -r line
do
mysql --host <redacted> --user <redacted> --password=<redacted> -N -e "use netops;select m_mailname from footprints where m_empno=$line;"
done <"$file"
This works and produces the expected output. Now I need to do the same thing but with a different list of IDs, querying a different field. Since the field I'm now querying on contains alphanumeric values (whereas the previous one was entirely numberic), I need to surround the value in quotes in the mysql query string, which I escape with \" like so:
#!/bin/bash
file="pidlist0.txt"
while IFS= read -r line
do
mysql --host <redacted> --user <redacted> --password=<redacted> -N -e "use netops;select m_mailname from footprints where m_stuid=\"$line\";"
done <"$file"
This doesn't work - the script produces no output. What am I doing wrong?
When I test the mysql command at the command line (with the $line variable pre-populated to one of the values from the file), it works, but when run from inside the script it produces no output. What's going on?
Just use m_stuid='$line';" ? Or change the double to single.
I am trying to execute an insert statement from linux shell where one of the columns has '$2a$10$zKjqmgld1gDYB/qkDuAS' in the value. When I see the inserted data the value is truncated and I get only 'aKjqmgld1gDYB/qkDuAS' as any digit followed by dollar is treated by linux as a parameter passed to the script.
This is how I am executing the script
mysql -u user --password=password -e "insert into users(id,name,password) values(1,'Some Name','\$2a\$10\$zKjqmgld1gDYB/qkDuAS')"
I have even tried escaping the $ like \$2a\$10\$zKjqmgld1gDYB/qkDuAS, but still it yields the same truncated data , however when I do echo '\$2a\$10\$zKjqmgld1gDYB/qkDuAS', I get the entire thing back.
Sameer
Single quotes don't nest in shell (do they anywhere else, anyway?). So, your string is effectively outside the quotes. Combine with double quotes and backslashes:
mysql -u user --password=password -e \
"insert into users(id,name,password) values(1,'Some Name','\$2a$10\$zKjqmgld1gDYB/qkDuAS')"
it was already in double quotes (sorry, for writing the wrong query). That didn't work either, however I found a workaround
echo "insert into users(id,name,password) values(1,'Some Name','\$2a\$10\$zKjqmgld1gDYB/qkDuAS')" >> temp.sql
mysql -u user --password=password < temp.sql
This finally worked.
everyone.
I'm a bash script noob, and I'm failing to figure out why I'm getting an unexpected end of file error.
This is my script:
#!/bin/bash
server=8100
while [ $server -le 8121 ]
do
ssh pos$server <<ENDEXP
mysql -u root -p12345 pos_master_prod <<ENDEXP
show slave status \G <<ENDEXP
\q <<ENDEXP
server=$(( $server + 1 ))
done
Any ideas?
Thanks!!
If I understand what it's supposed to do, this should work:
#!/bin/bash
for ((server=8100; server <= 8121; server++)); do
ssh pos$server <<-ENDEXP
mysql -u root -p12345 pos_master_prod
show slave status \G
\q
ENDEXP
done
(Note: be sure the lines to be sent to the remote server are indented with tabs, not spaces; <<- removes leading tabs, but not other forms of indentation.)
Looks like you want to use a here-doc but the syntax is a bit off..