If I'm on the mysql command line and execute a shortcut to list OS data, such as the following:
tee /tmp/output.log
mysql> \! hostname
dbatestserver
mysql> \! date
Mon Feb 13 18:00:52 EST 2023
it does not save the resulting "dbatestserver" and date value in my output file. I'm more worried about hostname output, as there are multiple options to pull the date.
Is there an option or a switch that will allow me to have this output go to my log?
I log into mysql with following options:
mysql -p -v -c --show-warnings -A
No, there is no way to do this with the tee functionality within the MySQL client.
https://github.com/mysql/mysql-server/blob/8.0/client/mysql.cc#L4126-L4133
/*
The output of the shell command does not
get directed to the pager or the outfile
*/
if (system(shell_cmd) == -1) {
You can do it outside the MySQL client.
% mysql -e "\\! date" | tee err
Mon Feb 13 19:30:39 PST 2023
% more err
Mon Feb 13 19:30:39 PST 2023
Related
I am a new user on Stack Overflow, so I apologize in advance for any potential breaches of site etiquette.
I am attempting to create a BASH script that will generate a command to invoke the MariaDB monitor, i.e. mysql. I want this mysql command to include the --init-command option. I want the --init-command option to set a list of user variables to a their values, as specified in a configuration file.
The script builds a string that appears to be correct for my purpose but, when it invokes mysql, an error is generated. If I print out the generated string from the script, it appears to be exactly what I was attempting to create.
I have boiled it down to the following code example:
#!/bin/sh
declare foo="name"
declare bar="value"
declare invoke="mysql -p -D information_schema"
declare opts=" --init-command='SET #$foo:=\"$bar\"'"
invoke+=$opts
echo $invoke
$invoke
When I execute this script, the result looks like:
$ example.sh
mysql -p -D information_schema --init-command='SET #name:="value"'
Enter password:
ERROR 1044 (42000): Access denied for user 'Bill'#'%' to database '#name:="value"''
This error message doesn't even seem to make sense.
However, if I copy the generated command, and paste it back into the command prompt, it requests my password, and proceeds as I would expect, as follows:
$ mysql -p -D information_schema --init-command='SET #name:="value"'
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 171
Server version: 10.3.11-MariaDB Source distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [information_schema]> SELECT #name;
+-------+
| #name |
+-------+
| value |
+-------+
1 row in set (0.000 sec)
MariaDB [information_schema]>
Demonstrating that the SET command in the --init-command option was successfully passed to the MariaDB monitor, and executed.
I do not know whether this is a Linux issue, a BASH issue, or a MariaDB issue. So, while I have spent a good amount of time trying to find the answer, I really don't know where the problem originates, and therefore, where to focus my research.
Please note: I only used the information_schema database in my example because I expect that anyone attempting to recreate this problem would have that database available to them.
Thank you in advance for your assistance.
Some options:
Option 1:
#!/bin/sh
# USING BASH
# FILE: bash_mariadb.sh
foo="\`name\`"
bar="value"
mysql -p -D information_schema --init-command="SET #$foo:='$bar';"
Option 2:
#!/bin/sh
# USING BASH
# FILE: bash_mariadb.sh
foo="\`name\`"
bar="value"
opts=(--init-command="SET #$foo:='$bar';")
invoke=(mysql -p -D information_schema "$opts")
"${invoke[#]}"
Option 3:
#!/bin/sh
# USING BASH
# FILE: bash_mariadb.sh
foo="\`name\`"
bar="value"
#define
invoke() {
opts=(--init-command="SET #$foo:='$bar'")
if [[ -v opts ]]; then
invoke=(mysql -p -D information_schema "$opts")
else
invoke=(mysql -p -D information_schema)
fi
"${invoke[#]}"
}
#call
invoke
Option 4: DANGER, option not recommended for safety reasons.
#!/bin/sh
# USING BASH
# FILE: bash_mariadb.sh
foo="\`name\`"
bar="value"
invoke="mysql -p -D information_schema"
opts=" --init-command='SET #$foo:=\"$bar\"'"
invoke+=$opts
eval $invoke
In all cases:
$ ./bash_mariadb.sh
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 1
Server version: 10.3.11-MariaDB Source distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [information_schema]> SELECT #`name`;
+---------+
| #`name` |
+---------+
| value |
+---------+
1 row in set (0.000 sec)
Welcome to SO.
From a script you have to indicate the password you want to use.
The option -p force it for a interactive introduction of the password, wich don't works from a script.
If you instead use -ppassword (notice that you still write the "p", only that you write it next to the password, without spaces), your connection will work.
So, you just have to modify the line:
declare invoke="mysql -ppassword -D information_schema"
(Don't forget to write your password where I wrote "password", of course :) )
Using shell script to run mysql insert query, while running the query i am seeing connections are not being closed from shell script.
Server Response after running the shell script
$ date
Tue Feb 20 15:43:58
$ netstat -alnp | grep 3306 | wc -l
26
Where above 26 counts were like
tcp6 0 0 192.168.10.169:31503 192.168.10.170:3306 ESTABLISHED 11603/java
$ netstat -alnp | grep 3306 | wc -l
50
Where above 50 counts were like (TIME_WAIT - 22) and (ESTABLISHED - 28)
tcp6 0 0 192.168.10.169:48308 192.168.10.170:3306 ESTABLISHED 12603/java
tcp6 0 0 192.168.10.169:48990 192.168.10.170:3306 TIME_WAIT
$ date
Tue Feb 20 15:46:49
Does mysql connection ran through shell script doesn't get closed by self
What is greater impact if shell script with mysql insert command ran via cron job at every 30 minutes
Script
#!bin/bash
query="insert into table_name values ('foo', 'bar' , 123, NOW() )where column_name is NOT NUll"
mysql -u username -p password mysql <<EOF
$query;
EOF
What will be impact on mysql maximum connections, While ran to my system i got more than 100 connections ESTABLISHED
What STATUS value corresponds to connections ESTABLISHED?
What was the value of
`SHOW GLOBAL STATUS LIKE 'Max_used_connections';
I expect a small number like 1 or 2.
For
`SHOW GLOBAL STATUS LIKE 'Connections';
I expect over 100.
The commandline tool mysql will create a connection (bumping Connections and possibly increasing the "high water mark" for Max_used_connections), do the action, then close the connection (without decreasing any STATUS). Threads_running is also incremented and decremented.
Your cron job should not be threatening any limitations.
I'm trying to run following query inside a bash script.
When it is executed from mysql command promt, execution time was 0.06sec.
mysql> delete from assign_history where offer_id not in
->('7','8','9','10','11','12','13','14','32','157','211','240','241','242','273',
->'274','275','310','312','313','314','326','328','329','333','334','335','336',
->'337','342','343','355','362','374','375','376','378','379','383','384','409','411')
->and date(action_date) < "2015-06-25" order by id limit 1000;
Query OK, 1000 rows affected (0.06 sec)
But when run it inside a bash script, it takes more than 2 minutes.
[root#localhost umap]# cat ./history_del.sh
#! /bin/bash
echo $(date)
mysql -uroot -ppassword db_offers -e "delete from assign_history where offer_id not in ('7','8','9','10','11','12','13','14','32','157','211','240','241','242','273','274','275','310','312','313','314','326','328','329','333','334','335','336','337','342','343','355','362','374','375','376','378','379','383','384','409','411') and date(action_date) < "2015-06-25" limit 1000;"
echo $(date)
[root#localhost umap]# ./history_del.sh
Wed Aug 26 19:08:45 IST 2015
Wed Aug 26 19:10:48 IST 2015
I also tried with "mysql -Bse" options. No improvement. Any ideas?
Any ideas?
First, you need to escape double-quotes inside the query string: \"2015-06-25\" (try to output your query with echo and you'll see, why ). I dont know, how your request works without properly specified quotes...
Second, it is better and preferred to place your long-line-request in the file, so your command-line will look like this:
mysql -uroot -ppassword db_offers <YOUR_FILE
Request in YOUR_FILE will be the same as in the mysql prompt (of course, you dont need to escape double-quotes here).
And yes, when you call mysql utility - it can take unpredictably long time to connect to MySQL server, so 2 minutes include this time (but 0.06 sec in mysql prompt doesnt!), so you cant say, how much time does it take to connect to server and how much - to send and execute your query.
To know, how much time does it take to connect to mysql server, try to execute (wait several seconds after previous run of the mysql utility) any empty query, such as:
time mysql -u user -ppassword -Bs <<<'select null'
I'd like to get the result of a mysql query with a vertical output.
My problem when using --vertical (or G) is the starred lines.
$mysql -N -e 'select filed1, field2 from db.tlb\G'
*************************** 1. row ***************************
value1_field1
value1_field2
*************************** 2. row ***************************
value2_field1
value2_field2
...
Is there an option I didn't find to get rid of the lines ***[...] x. row [...]*** ?
At the moment, I'm using a egrep -v '^\*.*\*$', but I'm sure a better solution exists.
I'm not sure this is a good solution, but if explicitly using egrep is annoying, you could define a shell function to launch mysql with the desired pager. Assuming you're using a bash (or compatible):
# define a shell function to launch mysql with the required _pager_
sh$ mysql() { `which mysql` $* --pager="egrep -v '^\*.*\*$'" ; }
[ ... ]
# launch mysql "as usual" (in reality, this is the shell function that is invoked)
sh$ mysql -u user -p -h mysql-host mydb
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 67
Server version: 5.1.49-3 (Debian)
-- Use mysql normally -- but the "egrep pager" will remove the "star lines"
mysql> select * from T\G
col1: w
col2: x
col3: 0.4
1 row in set (0.00 sec)
As I said before, this is not a perfect solution since egrep will blindly remove from output any "star line" -- not only the one from an ego (\G) command.
try this (but I can not imagine why you need such an output)
mysql -N -B -e 'select * from db' mysql | tr "\t" "\n"
First Option
would be to change the MySQL pager like so:
test.sh
#!/usr/bin/env bash
# Some Basic Configuration
db="homestead"
dbuser="homestead"
dbhost="127.0.0.1"
# Executes the MySQL command using the basic configuration
# This also sets the MySql Pager to less -Sin to enable
# it also removes all lines starting with "*"
mysql -h $dbhost -u $dbuser -p --pager="grep -Ev '(^\*.*$)|(^$)' | less -Sin" $db
Usage
Firstly Edit the Config variables:
$ nano ./test.sh
Secondly Run the script
$ bash ./test.sh
Second Option
Change the pager after you're already in the MySQL CLI
$ mysql -u root -p -h 127.0.0.1 somedatabase
enter password:
mysql> pager grep -Ev '(^\*.*$)|(^$)' | less -Sin
I have set up a cronjob using crontab -e as follows:
12 22 * * * /usr/bin/mysql >> < FILE PATH >
This does not run the mysql command. It only creates a blank file.
Whereas mysqldump command is running via cron.
What could the problem be?
Surely mysql is the interactive interface into MySQL.
Assuming that you're just running mysql and appending the output to your file with >>, the first time it tries to read from standard input, it will probably get an end-of-file and exit.
Perhaps you might want to think about providing a command for it to process, something like:
12 22 * * * /usr/bin/mysql
-u me
-p never_you_mind
-e "select * from my_table"
-D my_database
>>/home/me/output_file
(split across multiple lines for readability, but should be on one line).
As an aside, that's not overly secure since your password may be visible from ps while the process is running. Since it's only an example, I'm not too worried, but you should consider storing the password in a properly secured my.cnf file if you go down this path.
In terms of running a shell script from cron which in turn executes MySQL commands, that should work as well. One choice is with a here-doc:
/usr/bin/mysql -u me -p never_you_mind -D my_database <<EOF
select * from my_table
select * from my_other_table where id = 74
EOF
12 22 * * * /usr/bin/mysql >> < FILE PATH > 2>&1
Redirect your error message to the same file so you can debug it.
There is also a good article about how to debug cron jobs:
How to debug a broken cron job