~percona-toolkit-dev/percona-toolkit/fix-empty-table-bug-987393

« back to all changes in this revision

Viewing changes to lib/bash/collect_mysql_info.sh

  • Committer: Daniel Nichter
  • Date: 2012-04-03 16:14:55 UTC
  • mfrom: (217.6.22 2.0.3)
  • Revision ID: daniel@percona.com-20120403161455-ntv33vju9o6njtqv
Merge summary-tools-2.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# This program is copyright 2011-2012 Percona Inc.
 
2
# Feedback and improvements are welcome.
 
3
#
 
4
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 
5
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 
6
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
7
#
 
8
# This program is free software; you can redistribute it and/or modify it under
 
9
# the terms of the GNU General Public License as published by the Free Software
 
10
# Foundation, version 2; OR the Perl Artistic License.  On UNIX and similar
 
11
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
 
12
# licenses.
 
13
#
 
14
# You should have received a copy of the GNU General Public License along with
 
15
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
16
# Place, Suite 330, Boston, MA  02111-1307  USA.
 
17
# ###########################################################################
 
18
# collect_mysql_info package
 
19
# ###########################################################################
 
20
 
 
21
# Package: collect_mysql_info
 
22
# collect collects mysql information.
 
23
 
 
24
# XXX
 
25
# THIS LIB REQUIRES log_warn_die.sh, summary_common.sh, and alt_cmds.sh!
 
26
# XXX
 
27
 
 
28
CMD_MYSQL="${CMD_MYSQL:-""}"
 
29
CMD_MYSQLDUMP="${CMD_MYSQLDUMP:-""}"
 
30
 
 
31
# Simply looks for instances of mysqld in the outof of ps.
 
32
collect_mysqld_instances () {
 
33
   local variables_file="$1"
 
34
 
 
35
   local pids="$(_pidof mysqld)"
 
36
 
 
37
   if [ -n "$pids" ]; then
 
38
 
 
39
      for pid in $pids; do
 
40
         local nice="$( get_nice_of_pid $pid )"
 
41
         local oom="$( get_oom_of_pid $pid )"
 
42
         echo "internal::nice_of_$pid    $nice" >> "$variables_file"
 
43
         echo "internal::oom_of_$pid    $oom" >> "$variables_file"
 
44
      done
 
45
 
 
46
      pids="$(echo $pids | sed -e 's/ /,/g')"
 
47
      ps ww -p "$pids" 2>/dev/null
 
48
   else
 
49
      echo "mysqld doesn't appear to be running"
 
50
   fi
 
51
 
 
52
}
 
53
 
 
54
# Tries to find the my.cnf file by examining 'ps' output.
 
55
# You have to specify the port for the instance you are
 
56
# interested in, in case there are multiple instances.
 
57
find_my_cnf_file() {
 
58
   local file="$1"
 
59
   local port="${2:-""}"
 
60
 
 
61
   local cnf_file=""
 
62
   if test -n "$port" && grep -- "/mysqld.*--port=$port" "${file}" >/dev/null 2>&1 ; then
 
63
      cnf_file="$(grep -- "/mysqld.*--port=$port" "${file}" \
 
64
         | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \
 
65
         | head -n1)"
 
66
   else
 
67
      cnf_file="$(grep '/mysqld' "${file}" \
 
68
         | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \
 
69
         | head -n1)"
 
70
   fi
 
71
 
 
72
   if [ ! -n "${cnf_file}" ]; then
 
73
      # "Cannot autodetect config file, trying common locations"
 
74
      cnf_file="/etc/my.cnf";
 
75
      if [ ! -e "${cnf_file}" ]; then
 
76
         cnf_file="/etc/mysql/my.cnf";
 
77
      fi
 
78
      if [ ! -e "${cnf_file}" ]; then
 
79
         cnf_file="/var/db/mysql/my.cnf";
 
80
      fi
 
81
   fi
 
82
 
 
83
   echo "$cnf_file"
 
84
}
 
85
 
 
86
collect_mysql_variables () {
 
87
   $CMD_MYSQL $EXT_ARGV -ss  -e 'SHOW /*!40100 GLOBAL*/ VARIABLES'
 
88
}
 
89
 
 
90
collect_mysql_status () {
 
91
   $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW /*!50000 GLOBAL*/ STATUS'
 
92
}
 
93
 
 
94
collect_mysql_databases () {
 
95
   $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW DATABASES' 2>/dev/null
 
96
}
 
97
 
 
98
collect_mysql_plugins () {
 
99
   $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW PLUGINS' 2>/dev/null
 
100
}
 
101
 
 
102
collect_mysql_slave_status () {
 
103
   $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW SLAVE STATUS' 2>/dev/null
 
104
}
 
105
 
 
106
collect_mysql_innodb_status () {
 
107
   $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW /*!50000 ENGINE*/ INNODB STATUS' 2>/dev/null
 
108
}
 
109
 
 
110
collect_mysql_processlist () {
 
111
   $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW FULL PROCESSLIST' 2>/dev/null
 
112
}
 
113
 
 
114
collect_mysql_users () {
 
115
   $CMD_MYSQL $EXT_ARGV -ss -e 'SELECT COUNT(*), SUM(user=""), SUM(password=""), SUM(password NOT LIKE "*%") FROM mysql.user' 2>/dev/null
 
116
}
 
117
 
 
118
collect_master_logs_status () {
 
119
   local master_logs_file="$1"
 
120
   local master_status_file="$2"
 
121
   $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER LOGS' > "$master_logs_file" 2>/dev/null
 
122
   $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER STATUS' > "$master_status_file" 2>/dev/null
 
123
}
 
124
 
 
125
# Somewhat different from the others, this one joins the status we got earlier
 
126
collect_mysql_deferred_status () {
 
127
   local status_file="$1"
 
128
   collect_mysql_status > "$TMPDIR/defer_gatherer"
 
129
   join "$status_file" "$TMPDIR/defer_gatherer"
 
130
}
 
131
 
 
132
collect_internal_vars () {
 
133
   local mysqld_executables="${1:-""}"
 
134
 
 
135
   local FNV_64=""
 
136
   if $CMD_MYSQL $EXT_ARGV -e 'SELECT FNV_64("a")' >/dev/null 2>&1; then
 
137
      FNV_64="Enabled";
 
138
   else
 
139
      FNV_64="Unknown";
 
140
   fi
 
141
 
 
142
   local now="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT NOW()')"
 
143
   local user="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT CURRENT_USER()')"
 
144
   local trigger_count=$($CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS" 2>/dev/null)
 
145
 
 
146
   echo "pt-summary-internal-mysql_executable    $CMD_MYSQL"
 
147
   echo "pt-summary-internal-now    $now"
 
148
   echo "pt-summary-internal-user   $user"
 
149
   echo "pt-summary-internal-FNV_64   $FNV_64"
 
150
   echo "pt-summary-internal-trigger_count   $trigger_count"
 
151
 
 
152
   if [ -e "$mysqld_executables" ]; then
 
153
      local i=1
 
154
      while read executable; do
 
155
         echo "pt-summary-internal-mysqld_executable_${i}   $(has_symbols "$executable")"
 
156
         i=$(($i + 1))
 
157
      done < "$mysqld_executables"
 
158
   fi
 
159
}
 
160
 
 
161
# Uses mysqldump and dumps the results to FILE.
 
162
# args and dbtodump are passed to mysqldump.
 
163
get_mysqldump_for () {
 
164
   local args="$1"
 
165
   local dbtodump="${2:-"--all-databases"}"
 
166
 
 
167
   $CMD_MYSQLDUMP $EXT_ARGV --no-data --skip-comments \
 
168
      --skip-add-locks --skip-add-drop-table --compact \
 
169
      --skip-lock-all-tables --skip-lock-tables --skip-set-charset \
 
170
      ${args} --databases $( local IFS=,; echo ${dbtodump})
 
171
}
 
172
 
 
173
# Returns a string with arguments to pass to mysqldump.
 
174
# Takes one argument, which should be a
 
175
get_mysqldump_args () {
 
176
   local file="$1"
 
177
   local trg_arg=""
 
178
 
 
179
   # If mysqldump supports triggers, then add options for routines.
 
180
   if $CMD_MYSQLDUMP --help --verbose 2>&1 | grep triggers >/dev/null; then
 
181
      # "mysqldump supports triggers"
 
182
      trg_arg="--routines"
 
183
   fi
 
184
 
 
185
   if [ "${trg_arg}" ]; then
 
186
      # Find out if there are any triggers.  If there are none, we will skip
 
187
      # that option to mysqldump, because when mysqldump checks for them, it
 
188
      # can take a long time, one table at a time.
 
189
      local triggers="--skip-triggers"
 
190
      local trg=$(get_var "pt-summary-internal-trigger_count" "$file" )
 
191
      if [ -n "${trg}" ] && [ "${trg}" -gt 0 ]; then
 
192
         triggers="--triggers"
 
193
      fi
 
194
      trg_arg="${trg_arg} ${triggers}";
 
195
   fi
 
196
   echo "${trg_arg}"
 
197
}
 
198
 
 
199
collect_mysqld_executables () {
 
200
   local mysqld_instances="$1"
 
201
 
 
202
   for pid in $( grep '/mysqld' "$mysqld_instances" | awk '/^ .*[0-9]/{print $1}' ); do
 
203
      ps -o cmd -p $pid | sed -e 's/^\(.*mysqld\) .*/\1/' | grep -v '^CMD$'
 
204
   done | sort -u
 
205
}
 
206
 
 
207
collect_mysql_info () {
 
208
   local dir="$1"
 
209
 
 
210
   collect_mysql_variables     > "$dir/mysql-variables"
 
211
   collect_mysql_status        > "$dir/mysql-status"
 
212
   collect_mysql_databases     > "$dir/mysql-databases"
 
213
   collect_mysql_plugins       > "$dir/mysql-plugins"
 
214
   collect_mysql_slave_status  > "$dir/mysql-slave"
 
215
   collect_mysql_innodb_status > "$dir/innodb-status"
 
216
   collect_mysql_processlist   > "$dir/mysql-processlist"   
 
217
   collect_mysql_users         > "$dir/mysql-users"
 
218
 
 
219
   collect_mysqld_instances   "$dir/mysql-variables"  > "$dir/mysqld-instances"
 
220
   collect_mysqld_executables "$dir/mysqld-instances" > "$dir/mysqld-executables"
 
221
 
 
222
   local binlog="$(get_var log_bin "$dir/mysql-variables")"
 
223
   if [ "${binlog}" ]; then
 
224
      # "Got a binlog, going to get MASTER LOGS and MASTER STATUS"
 
225
      collect_master_logs_status "$dir/mysql-master-logs" "$dir/mysql-master-status"
 
226
   fi
 
227
 
 
228
   local uptime="$(get_var Uptime "$dir/mysql-status")"
 
229
   local current_time="$($CMD_MYSQL $EXT_ARGV -ss -e \
 
230
                         "SELECT LEFT(NOW() - INTERVAL ${uptime} SECOND, 16)")"
 
231
 
 
232
   local port="$(get_var port "$dir/mysql-variables")"
 
233
   local cnf_file="$(find_my_cnf_file "$dir/mysqld-instances" ${port})"
 
234
 
 
235
   cat "$cnf_file" > "$dir/mysql-config-file"
 
236
 
 
237
   local pid_file="$(get_var "pid_file" "$dir/mysql-variables")"
 
238
   local pid_file_exists=""
 
239
   [ -e "${pid_file}" ] && pid_file_exists=1
 
240
   echo "pt-summary-internal-pid_file_exists    $pid_file_exists" >> "$dir/mysql-variables"
 
241
 
 
242
   # TODO: Do these require a file of their own?
 
243
   echo "pt-summary-internal-current_time    $current_time" >> "$dir/mysql-variables"
 
244
   echo "pt-summary-internal-Config_File_path    $cnf_file" >> "$dir/mysql-variables"
 
245
   collect_internal_vars "$dir/mysqld-executables" >> "$dir/mysql-variables"
 
246
 
 
247
   if [ -n "${OPT_DATABASES}" ]; then
 
248
      # "--dump-schemas passed in, dumping early"
 
249
      local trg_arg="$( get_mysqldump_args "$dir/mysql-variables" )"
 
250
      get_mysqldump_for "${trg_arg}" "${OPT_DATABASES}" > "$dir/mysqldump"
 
251
   fi
 
252
 
 
253
   # TODO: gather this data in the same format as normal: TS line, stats
 
254
   (
 
255
      sleep $OPT_SLEEP
 
256
      collect_mysql_deferred_status "$dir/mysql-status" > "$dir/mysql-status-defer"
 
257
   ) &
 
258
   _d "Forked child is $!"
 
259
}
 
260
 
 
261
# ###########################################################################
 
262
# End collect_mysql_info package
 
263
# ###########################################################################