Merge lp:~percona-toolkit-dev/percona-toolkit/summary-tools-2.1 into lp:percona-toolkit/2.1
- summary-tools-2.1
- Merge into 2.1
Proposed by
Daniel Nichter
Status: | Merged |
---|---|
Approved by: | Daniel Nichter |
Approved revision: | 239 |
Merged at revision: | 231 |
Proposed branch: | lp:~percona-toolkit-dev/percona-toolkit/summary-tools-2.1 |
Merge into: | lp:percona-toolkit/2.1 |
Diff against target: |
35981 lines (+30662/-3529) 203 files modified
bin/pt-mysql-summary (+2083/-683) bin/pt-summary (+2022/-839) lib/bash/alt_cmds.sh (+25/-1) lib/bash/collect_mysql_info.sh (+263/-0) lib/bash/collect_system_info.sh (+574/-0) lib/bash/log_warn_die.sh (+6/-0) lib/bash/report_formatting.sh (+117/-0) lib/bash/report_mysql_info.sh (+1391/-0) lib/bash/report_system_info.sh (+1050/-0) lib/bash/summary_common.sh (+155/-0) t/lib/bash/collect_mysql_info.sh (+197/-0) t/lib/bash/collect_system_info.sh (+307/-0) t/lib/bash/parse_options.sh.~1~ (+241/-0) t/lib/bash/report_formatting.sh (+109/-0) t/lib/bash/report_mysql_info.sh (+734/-0) t/lib/bash/report_system_info.sh (+1569/-0) t/lib/bash/report_system_info.t (+212/-0) t/lib/bash/summary_common.sh (+79/-0) t/pt-deadlock-logger/basics.t (+1/-1) t/pt-mysql-summary/find_my_cnf_file.sh (+0/-20) t/pt-mysql-summary/format_binlog_filters.sh (+0/-12) t/pt-mysql-summary/format_innodb_status.sh (+0/-147) t/pt-mysql-summary/format_overall_db_stats.sh (+0/-61) t/pt-mysql-summary/format_status_variables.sh (+0/-97) t/pt-mysql-summary/fuzz.sh (+0/-7) t/pt-mysql-summary/get_mysql_info.sh (+0/-26) t/pt-mysql-summary/parse_mysqld_instances.sh (+0/-47) t/pt-mysql-summary/pretty_print_cnf_file.sh (+0/-40) t/pt-mysql-summary/pt-mysql-summary.t (+54/-2) t/pt-mysql-summary/samples/expected_output_temp002.txt (+276/-0) t/pt-mysql-summary/samples/expected_output_temp003.txt (+219/-0) t/pt-mysql-summary/samples/expected_output_temp004.txt (+218/-0) t/pt-mysql-summary/samples/expected_output_temp005.txt (+291/-0) t/pt-mysql-summary/samples/expected_result_report_summary.txt (+257/-0) t/pt-mysql-summary/samples/mysql-variables-with-semisync.txt (+326/-0) t/pt-mysql-summary/samples/temp001/mysql-status (+304/-0) t/pt-mysql-summary/samples/temp001/mysql-variables (+356/-0) t/pt-mysql-summary/samples/temp002/innodb-status (+118/-0) t/pt-mysql-summary/samples/temp002/mysql-config-file (+26/-0) t/pt-mysql-summary/samples/temp002/mysql-databases (+6/-0) t/pt-mysql-summary/samples/temp002/mysql-plugins (+35/-0) t/pt-mysql-summary/samples/temp002/mysql-processlist (+12/-0) t/pt-mysql-summary/samples/temp002/mysql-status (+370/-0) t/pt-mysql-summary/samples/temp002/mysql-status-defer (+370/-0) t/pt-mysql-summary/samples/temp002/mysql-users (+1/-0) t/pt-mysql-summary/samples/temp002/mysql-variables (+372/-0) t/pt-mysql-summary/samples/temp002/mysqld-instances (+4/-0) t/pt-mysql-summary/samples/temp002/mysqldump (+396/-0) t/pt-mysql-summary/samples/temp003/innodb-status (+77/-0) t/pt-mysql-summary/samples/temp003/mysql-config-file (+26/-0) t/pt-mysql-summary/samples/temp003/mysql-databases (+2/-0) t/pt-mysql-summary/samples/temp003/mysql-master-logs (+1/-0) t/pt-mysql-summary/samples/temp003/mysql-master-status (+1/-0) t/pt-mysql-summary/samples/temp003/mysql-plugins (+10/-0) t/pt-mysql-summary/samples/temp003/mysql-processlist (+9/-0) t/pt-mysql-summary/samples/temp003/mysql-status (+291/-0) t/pt-mysql-summary/samples/temp003/mysql-status-defer (+291/-0) t/pt-mysql-summary/samples/temp003/mysql-users (+1/-0) t/pt-mysql-summary/samples/temp003/mysql-variables (+285/-0) t/pt-mysql-summary/samples/temp003/mysqld-instances (+2/-0) t/pt-mysql-summary/samples/temp004/innodb-status (+77/-0) t/pt-mysql-summary/samples/temp004/mysql-config-file (+26/-0) t/pt-mysql-summary/samples/temp004/mysql-databases (+3/-0) t/pt-mysql-summary/samples/temp004/mysql-master-logs (+2/-0) t/pt-mysql-summary/samples/temp004/mysql-master-status (+1/-0) t/pt-mysql-summary/samples/temp004/mysql-plugins (+10/-0) t/pt-mysql-summary/samples/temp004/mysql-processlist (+9/-0) t/pt-mysql-summary/samples/temp004/mysql-status (+291/-0) t/pt-mysql-summary/samples/temp004/mysql-status-defer (+291/-0) t/pt-mysql-summary/samples/temp004/mysql-users (+1/-0) t/pt-mysql-summary/samples/temp004/mysql-variables (+285/-0) t/pt-mysql-summary/samples/temp004/mysqld-instances (+2/-0) t/pt-mysql-summary/samples/temp005/innodb-status (+108/-0) t/pt-mysql-summary/samples/temp005/mysql-config-file (+26/-0) t/pt-mysql-summary/samples/temp005/mysql-databases (+3/-0) t/pt-mysql-summary/samples/temp005/mysql-master-logs (+1/-0) t/pt-mysql-summary/samples/temp005/mysql-master-status (+1/-0) t/pt-mysql-summary/samples/temp005/mysql-plugins (+28/-0) t/pt-mysql-summary/samples/temp005/mysql-processlist (+18/-0) t/pt-mysql-summary/samples/temp005/mysql-status (+304/-0) t/pt-mysql-summary/samples/temp005/mysql-status-defer (+304/-0) t/pt-mysql-summary/samples/temp005/mysql-users (+1/-0) t/pt-mysql-summary/samples/temp005/mysql-variables (+363/-0) t/pt-mysql-summary/samples/temp005/mysqld-executables (+1/-0) t/pt-mysql-summary/samples/temp005/mysqld-instances (+4/-0) t/pt-mysql-summary/samples/temp005/mysqldump (+1084/-0) t/pt-mysql-summary/samples/tempdir/innodb-status (+77/-0) t/pt-mysql-summary/samples/tempdir/mysql-config-file (+26/-0) t/pt-mysql-summary/samples/tempdir/mysql-databases (+3/-0) t/pt-mysql-summary/samples/tempdir/mysql-master-logs (+3/-0) t/pt-mysql-summary/samples/tempdir/mysql-master-status (+1/-0) t/pt-mysql-summary/samples/tempdir/mysql-plugins (+10/-0) t/pt-mysql-summary/samples/tempdir/mysql-processlist (+9/-0) t/pt-mysql-summary/samples/tempdir/mysql-status (+291/-0) t/pt-mysql-summary/samples/tempdir/mysql-status-defer (+291/-0) t/pt-mysql-summary/samples/tempdir/mysql-users (+5/-0) t/pt-mysql-summary/samples/tempdir/mysql-variables (+283/-0) t/pt-mysql-summary/samples/tempdir/mysqld-instances (+4/-0) t/pt-mysql-summary/samples/tempdir/mysqldump (+328/-0) t/pt-mysql-summary/samples/tempdir/tempfile (+130/-0) t/pt-mysql-summary/summarize_binlogs.sh (+0/-13) t/pt-mysql-summary/summarize_processlist.sh (+0/-64) t/pt-summary/format_vmstat.sh (+0/-37) t/pt-summary/parse_arcconf.sh (+0/-176) t/pt-summary/parse_dmidecode_mem_devices.sh (+0/-104) t/pt-summary/parse_ethernet_controller_lspci.sh (+0/-11) t/pt-summary/parse_fdisk.sh (+0/-16) t/pt-summary/parse_filesystems.sh (+0/-52) t/pt-summary/parse_free_minus_b.sh (+0/-67) t/pt-summary/parse_fusionmpt_lsiutil.sh (+0/-50) t/pt-summary/parse_hpacucli.sh (+0/-26) t/pt-summary/parse_ip_s_link.sh (+0/-28) t/pt-summary/parse_lsi_megaraid.sh (+0/-696) t/pt-summary/parse_netstat.sh (+0/-49) t/pt-summary/parse_proc_cpuinfo.sh (+0/-74) t/pt-summary/parse_raid_controller_dmesg.sh (+0/-32) t/pt-summary/parse_raid_controller_lspci.sh (+0/-39) t/pt-summary/parse_virtualization_dmesg.sh (+0/-10) t/pt-summary/pt-summary.t (+12/-2) t/pt-summary/samples/BSD/freebsd_001/mounted_fs (+7/-0) t/pt-summary/samples/BSD/freebsd_001/notable_procs (+2/-0) t/pt-summary/samples/BSD/freebsd_001/processes (+10/-0) t/pt-summary/samples/BSD/freebsd_001/summary (+10/-0) t/pt-summary/samples/BSD/freebsd_001/sysctl (+1481/-0) t/pt-summary/samples/BSD/freebsd_001/uptime (+1/-0) t/pt-summary/samples/BSD/freebsd_001/vmstat (+7/-0) t/pt-summary/samples/BSD/netbsd_001/mounted_fs (+5/-0) t/pt-summary/samples/BSD/netbsd_001/notable_procs (+2/-0) t/pt-summary/samples/BSD/netbsd_001/proc_cpuinfo_copy (+14/-0) t/pt-summary/samples/BSD/netbsd_001/processes (+10/-0) t/pt-summary/samples/BSD/netbsd_001/summary (+10/-0) t/pt-summary/samples/BSD/netbsd_001/swapctl (+1/-0) t/pt-summary/samples/BSD/netbsd_001/sysctl (+511/-0) t/pt-summary/samples/BSD/netbsd_001/uptime (+1/-0) t/pt-summary/samples/BSD/netbsd_001/vmstat (+7/-0) t/pt-summary/samples/BSD/openbsd_001/mounted_fs (+4/-0) t/pt-summary/samples/BSD/openbsd_001/notable_procs (+2/-0) t/pt-summary/samples/BSD/openbsd_001/processes (+10/-0) t/pt-summary/samples/BSD/openbsd_001/summary (+10/-0) t/pt-summary/samples/BSD/openbsd_001/swapctl (+1/-0) t/pt-summary/samples/BSD/openbsd_001/sysctl (+423/-0) t/pt-summary/samples/BSD/openbsd_001/uptime (+1/-0) t/pt-summary/samples/BSD/openbsd_001/vmstat (+7/-0) t/pt-summary/samples/Linux/001/dmesg_file (+786/-0) t/pt-summary/samples/Linux/001/dmidecode (+412/-0) t/pt-summary/samples/Linux/001/ip (+24/-0) t/pt-summary/samples/Linux/001/lspci_file (+17/-0) t/pt-summary/samples/Linux/001/lvs (+1/-0) t/pt-summary/samples/Linux/001/memory (+50/-0) t/pt-summary/samples/Linux/001/mounted_fs (+12/-0) t/pt-summary/samples/Linux/001/netstat (+6/-0) t/pt-summary/samples/Linux/001/notable_procs (+5/-0) t/pt-summary/samples/Linux/001/partitioning (+30/-0) t/pt-summary/samples/Linux/001/proc_cpuinfo_copy (+58/-0) t/pt-summary/samples/Linux/001/proc_cpuinfo_copy.unq (+1/-0) t/pt-summary/samples/Linux/001/processes (+10/-0) t/pt-summary/samples/Linux/001/summary (+23/-0) t/pt-summary/samples/Linux/001/sysctl (+905/-0) t/pt-summary/samples/Linux/001/uptime (+1/-0) t/pt-summary/samples/Linux/001/vmstat (+7/-0) t/pt-summary/samples/Linux/002/dmesg_file (+283/-0) t/pt-summary/samples/Linux/002/memory (+34/-0) t/pt-summary/samples/Linux/002/mounted_fs (+3/-0) t/pt-summary/samples/Linux/002/netstat (+6/-0) t/pt-summary/samples/Linux/002/notable_procs (+2/-0) t/pt-summary/samples/Linux/002/partitioning (+9/-0) t/pt-summary/samples/Linux/002/proc_cpuinfo_copy (+19/-0) t/pt-summary/samples/Linux/002/processes (+10/-0) t/pt-summary/samples/Linux/002/summary (+19/-0) t/pt-summary/samples/Linux/002/uptime (+1/-0) t/pt-summary/samples/Linux/002/vmstat (+7/-0) t/pt-summary/samples/Linux/003/dmesg_file (+283/-0) t/pt-summary/samples/Linux/003/memory (+34/-0) t/pt-summary/samples/Linux/003/mounted_fs (+3/-0) t/pt-summary/samples/Linux/003/netstat (+6/-0) t/pt-summary/samples/Linux/003/notable_procs (+2/-0) t/pt-summary/samples/Linux/003/partitioning (+1/-0) t/pt-summary/samples/Linux/003/proc_cpuinfo_copy (+19/-0) t/pt-summary/samples/Linux/003/processes (+10/-0) t/pt-summary/samples/Linux/003/summary (+19/-0) t/pt-summary/samples/Linux/003/uptime (+1/-0) t/pt-summary/samples/Linux/003/vmstat (+7/-0) t/pt-summary/samples/Linux/output_002.txt (+82/-0) t/pt-summary/samples/Linux/output_003.txt (+79/-0) t/pt-summary/samples/MegaCli64_AdpAllInfo_aALL001.txt (+227/-0) t/pt-summary/samples/MegaCli64_LdPdInfo_aALL_886223 (+214/-0) t/pt-summary/samples/arcconf-001.txt (+133/-0) t/pt-summary/samples/arcconf-003_900285.txt (+228/-0) t/pt-summary/samples/arcconf-004_917781.txt (+162/-0) t/pt-summary/samples/arcconf-004_917781.txt.bak.~1~ (+162/-0) t/pt-summary/samples/dmesg-005.txt (+787/-0) t/pt-summary/samples/dmesg-007.txt (+136/-0) t/pt-summary/samples/hpaculi-001.txt (+11/-0) t/pt-summary/samples/hpaculi-002.txt (+354/-0) t/pt-summary/samples/hpaculi-003.txt (+11/-0) t/pt-summary/samples/ip-s-link-003.txt (+24/-0) t/pt-summary/samples/lspci-005.txt (+38/-0) t/pt-summary/samples/netstat-002.txt (+1328/-0) t/pt-summary/samples/proc_cpuinfo001.txt (+57/-0) t/pt-summary/samples/proc_cpuinfo001.txt.unq (+1/-0) t/pt-summary/samples/proc_cpuinfo002.txt (+57/-0) t/pt-summary/samples/proc_cpuinfo002.txt.unq (+1/-0) util/test-bash-functions (+48/-0) |
To merge this branch: | bzr merge lp:~percona-toolkit-dev/percona-toolkit/summary-tools-2.1 |
Related bugs: | |
Related blueprints: |
Redesign pt-mysql-summary
(Essential)
Redesign pt-summary
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Nichter | Approve | ||
Review via email: mp+100545@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 236. By Brian Fraser <email address hidden>
-
Fix a section() bug.
Turns out that awk's indexes are documented to start from 1;
So what happens if you use 0? Apparently it's undefined behavior, so
substr(var, 0, 5);
and
substr(var, 1, 5);
May or may not actually do the same thing. In Debian 6, the former
doesn't quite work, and actually returns something like substr(var, 1, 4),
which broke section()'s output. - 237. By Brian Fraser <email address hidden>
-
section(): Less printf, more awk
- 238. By Brian Fraser <email address hidden>
-
Other instances of the substr(var, 0, n) bug
- 239. By Brian Fraser <email address hidden>
-
Fix for a bug in 32-bit Debian.
Namely, awk's printf("%d") doing what it's supposed to do, cast
it's operand to (int), which screws up large numbers.
The fix is simple, although it mostly just pushes the problem
under the rug; using %.0f instead of %d.
Revision history for this message
Daniel Nichter (daniel-nichter) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bin/pt-mysql-summary' | |||
2 | --- bin/pt-mysql-summary 2012-03-07 23:41:54 +0000 | |||
3 | +++ bin/pt-mysql-summary 2012-04-03 15:57:31 +0000 | |||
4 | @@ -4,14 +4,421 @@ | |||
5 | 4 | # See "COPYRIGHT, LICENSE, AND WARRANTY" at the end of this file for legal | 4 | # See "COPYRIGHT, LICENSE, AND WARRANTY" at the end of this file for legal |
6 | 5 | # notices and disclaimers. | 5 | # notices and disclaimers. |
7 | 6 | 6 | ||
8 | 7 | set -u | ||
9 | 8 | |||
10 | 9 | # ########################################################################### | ||
11 | 10 | # log_warn_die package | ||
12 | 11 | # This package is a copy without comments from the original. The original | ||
13 | 12 | # with comments and its test file can be found in the Bazaar repository at, | ||
14 | 13 | # lib/bash/log_warn_die.sh | ||
15 | 14 | # t/lib/bash/log_warn_die.sh | ||
16 | 15 | # See https://launchpad.net/percona-toolkit for more information. | ||
17 | 16 | # ########################################################################### | ||
18 | 17 | |||
19 | 18 | |||
20 | 19 | set -u | ||
21 | 20 | |||
22 | 21 | PTFUNCNAME="" | ||
23 | 22 | PTDEBUG="${PTDEBUG:-""}" | ||
24 | 23 | EXIT_STATUS=0 | ||
25 | 24 | |||
26 | 25 | log() { | ||
27 | 26 | TS=$(date +%F-%T | tr :- _); | ||
28 | 27 | echo "$TS $*" | ||
29 | 28 | } | ||
30 | 29 | |||
31 | 30 | warn() { | ||
32 | 31 | log "$*" >&2 | ||
33 | 32 | EXIT_STATUS=1 | ||
34 | 33 | } | ||
35 | 34 | |||
36 | 35 | die() { | ||
37 | 36 | warn "$*" | ||
38 | 37 | exit 1 | ||
39 | 38 | } | ||
40 | 39 | |||
41 | 40 | _d () { | ||
42 | 41 | [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(log "$*")" >&2 | ||
43 | 42 | } | ||
44 | 43 | |||
45 | 44 | # ########################################################################### | ||
46 | 45 | # End log_warn_die package | ||
47 | 46 | # ########################################################################### | ||
48 | 47 | |||
49 | 48 | # ########################################################################### | ||
50 | 49 | # parse_options package | ||
51 | 50 | # This package is a copy without comments from the original. The original | ||
52 | 51 | # with comments and its test file can be found in the Bazaar repository at, | ||
53 | 52 | # lib/bash/parse_options.sh | ||
54 | 53 | # t/lib/bash/parse_options.sh | ||
55 | 54 | # See https://launchpad.net/percona-toolkit for more information. | ||
56 | 55 | # ########################################################################### | ||
57 | 56 | |||
58 | 57 | |||
59 | 58 | |||
60 | 59 | |||
61 | 60 | |||
62 | 61 | set -u | ||
63 | 62 | |||
64 | 63 | ARGV="" # Non-option args (probably input files) | ||
65 | 64 | EXT_ARGV="" # Everything after -- (args for an external command) | ||
66 | 65 | HAVE_EXT_ARGV="" # Got --, everything else is put into EXT_ARGV | ||
67 | 66 | OPT_ERRS=0 # How many command line option errors | ||
68 | 67 | OPT_VERSION="" # If --version was specified | ||
69 | 68 | OPT_HELP="" # If --help was specified | ||
70 | 69 | PO_DIR="" # Directory with program option spec files | ||
71 | 70 | |||
72 | 7 | usage() { | 71 | usage() { |
80 | 8 | if [ "${OPT_ERR}" ]; then | 72 | local file="$1" |
81 | 9 | echo "${OPT_ERR}" >&2 | 73 | |
82 | 10 | fi | 74 | local usage=$(grep '^Usage: ' "$file") |
83 | 11 | echo "Usage: pt-mysql-summary [MYSQL-OPTIONS]" >&2 | 75 | echo $usage |
84 | 12 | echo "For more information, 'man pt-mysql-summary' or 'perldoc $0'" >&2 | 76 | echo |
85 | 13 | exit 1 | 77 | echo "For more information, 'man $TOOL' or 'perldoc $file'." |
86 | 14 | } | 78 | } |
87 | 79 | |||
88 | 80 | usage_or_errors() { | ||
89 | 81 | local file="$1" | ||
90 | 82 | |||
91 | 83 | if [ "$OPT_VERSION" ]; then | ||
92 | 84 | local version=$(grep '^pt-[^ ]\+ [0-9]' "$file") | ||
93 | 85 | echo "$version" | ||
94 | 86 | return 1 | ||
95 | 87 | fi | ||
96 | 88 | |||
97 | 89 | if [ "$OPT_HELP" ]; then | ||
98 | 90 | usage "$file" | ||
99 | 91 | echo | ||
100 | 92 | echo "Command line options:" | ||
101 | 93 | echo | ||
102 | 94 | perl -e ' | ||
103 | 95 | use strict; | ||
104 | 96 | use warnings FATAL => qw(all); | ||
105 | 97 | my $lcol = 20; # Allow this much space for option names. | ||
106 | 98 | my $rcol = 80 - $lcol; # The terminal is assumed to be 80 chars wide. | ||
107 | 99 | my $name; | ||
108 | 100 | while ( <> ) { | ||
109 | 101 | my $line = $_; | ||
110 | 102 | chomp $line; | ||
111 | 103 | if ( $line =~ s/^long:/ --/ ) { | ||
112 | 104 | $name = $line; | ||
113 | 105 | } | ||
114 | 106 | elsif ( $line =~ s/^desc:// ) { | ||
115 | 107 | $line =~ s/ +$//mg; | ||
116 | 108 | my @lines = grep { $_ } | ||
117 | 109 | $line =~ m/(.{0,$rcol})(?:\s+|\Z)/g; | ||
118 | 110 | if ( length($name) >= $lcol ) { | ||
119 | 111 | print $name, "\n", (q{ } x $lcol); | ||
120 | 112 | } | ||
121 | 113 | else { | ||
122 | 114 | printf "%-${lcol}s", $name; | ||
123 | 115 | } | ||
124 | 116 | print join("\n" . (q{ } x $lcol), @lines); | ||
125 | 117 | print "\n"; | ||
126 | 118 | } | ||
127 | 119 | } | ||
128 | 120 | ' "$PO_DIR"/* | ||
129 | 121 | echo | ||
130 | 122 | echo "Options and values after processing arguments:" | ||
131 | 123 | echo | ||
132 | 124 | for opt in $(ls "$PO_DIR"); do | ||
133 | 125 | local varname="OPT_$(echo "$opt" | tr a-z- A-Z_)" | ||
134 | 126 | local varvalue="${!varname}" | ||
135 | 127 | printf -- " --%-30s %s" "$opt" "${varvalue:-(No value)}" | ||
136 | 128 | echo | ||
137 | 129 | done | ||
138 | 130 | return 1 | ||
139 | 131 | fi | ||
140 | 132 | |||
141 | 133 | if [ $OPT_ERRS -gt 0 ]; then | ||
142 | 134 | echo | ||
143 | 135 | usage "$file" | ||
144 | 136 | return 1 | ||
145 | 137 | fi | ||
146 | 138 | |||
147 | 139 | return 0 | ||
148 | 140 | } | ||
149 | 141 | |||
150 | 142 | option_error() { | ||
151 | 143 | local err="$1" | ||
152 | 144 | OPT_ERRS=$(($OPT_ERRS + 1)) | ||
153 | 145 | echo "$err" >&2 | ||
154 | 146 | } | ||
155 | 147 | |||
156 | 148 | parse_options() { | ||
157 | 149 | local file="$1" | ||
158 | 150 | shift | ||
159 | 151 | |||
160 | 152 | ARGV="" | ||
161 | 153 | EXT_ARGV="" | ||
162 | 154 | HAVE_EXT_ARGV="" | ||
163 | 155 | OPT_ERRS=0 | ||
164 | 156 | OPT_VERSION="" | ||
165 | 157 | OPT_HELP="" | ||
166 | 158 | PO_DIR="$TMPDIR/po" | ||
167 | 159 | |||
168 | 160 | if [ ! -d "$PO_DIR" ]; then | ||
169 | 161 | mkdir "$PO_DIR" | ||
170 | 162 | if [ $? -ne 0 ]; then | ||
171 | 163 | echo "Cannot mkdir $PO_DIR" >&2 | ||
172 | 164 | exit 1 | ||
173 | 165 | fi | ||
174 | 166 | fi | ||
175 | 167 | |||
176 | 168 | rm -rf "$PO_DIR"/* | ||
177 | 169 | if [ $? -ne 0 ]; then | ||
178 | 170 | echo "Cannot rm -rf $PO_DIR/*" >&2 | ||
179 | 171 | exit 1 | ||
180 | 172 | fi | ||
181 | 173 | |||
182 | 174 | _parse_pod "$file" # Parse POD into program option (po) spec files | ||
183 | 175 | _eval_po # Eval po into existence with default values | ||
184 | 176 | |||
185 | 177 | if [ $# -ge 2 ] && [ "$1" = "--config" ]; then | ||
186 | 178 | shift # --config | ||
187 | 179 | local user_config_files="$1" | ||
188 | 180 | shift # that ^ | ||
189 | 181 | local IFS="," | ||
190 | 182 | for user_config_file in $user_config_files; do | ||
191 | 183 | _parse_config_files "$user_config_file" | ||
192 | 184 | done | ||
193 | 185 | else | ||
194 | 186 | _parse_config_files "/etc/percona-toolkit/percona-toolkit.conf" "/etc/percona-toolkit/$TOOL.conf" "$HOME/.percona-toolkit.conf" "$HOME/.$TOOL.conf" | ||
195 | 187 | fi | ||
196 | 188 | |||
197 | 189 | _parse_command_line "$@" | ||
198 | 190 | } | ||
199 | 191 | |||
200 | 192 | _parse_pod() { | ||
201 | 193 | local file="$1" | ||
202 | 194 | |||
203 | 195 | cat "$file" | PO_DIR="$PO_DIR" perl -ne ' | ||
204 | 196 | BEGIN { $/ = ""; } | ||
205 | 197 | next unless $_ =~ m/^=head1 OPTIONS/; | ||
206 | 198 | while ( defined(my $para = <>) ) { | ||
207 | 199 | last if $para =~ m/^=head1/; | ||
208 | 200 | chomp; | ||
209 | 201 | if ( $para =~ m/^=item --(\S+)/ ) { | ||
210 | 202 | my $opt = $1; | ||
211 | 203 | my $file = "$ENV{PO_DIR}/$opt"; | ||
212 | 204 | open my $opt_fh, ">", $file or die "Cannot open $file: $!"; | ||
213 | 205 | print $opt_fh "long:$opt\n"; | ||
214 | 206 | $para = <>; | ||
215 | 207 | chomp; | ||
216 | 208 | if ( $para =~ m/^[a-z ]+:/ ) { | ||
217 | 209 | map { | ||
218 | 210 | chomp; | ||
219 | 211 | my ($attrib, $val) = split(/: /, $_); | ||
220 | 212 | print $opt_fh "$attrib:$val\n"; | ||
221 | 213 | } split(/; /, $para); | ||
222 | 214 | $para = <>; | ||
223 | 215 | chomp; | ||
224 | 216 | } | ||
225 | 217 | my ($desc) = $para =~ m/^([^?.]+)/; | ||
226 | 218 | print $opt_fh "desc:$desc.\n"; | ||
227 | 219 | close $opt_fh; | ||
228 | 220 | } | ||
229 | 221 | } | ||
230 | 222 | last; | ||
231 | 223 | ' | ||
232 | 224 | } | ||
233 | 225 | |||
234 | 226 | _eval_po() { | ||
235 | 227 | local IFS=":" | ||
236 | 228 | for opt_spec in "$PO_DIR"/*; do | ||
237 | 229 | local opt="" | ||
238 | 230 | local default_val="" | ||
239 | 231 | local neg=0 | ||
240 | 232 | local size=0 | ||
241 | 233 | while read key val; do | ||
242 | 234 | case "$key" in | ||
243 | 235 | long) | ||
244 | 236 | opt=$(echo $val | sed 's/-/_/g' | tr [:lower:] [:upper:]) | ||
245 | 237 | ;; | ||
246 | 238 | default) | ||
247 | 239 | default_val="$val" | ||
248 | 240 | ;; | ||
249 | 241 | "short form") | ||
250 | 242 | ;; | ||
251 | 243 | type) | ||
252 | 244 | [ "$val" = "size" ] && size=1 | ||
253 | 245 | ;; | ||
254 | 246 | desc) | ||
255 | 247 | ;; | ||
256 | 248 | negatable) | ||
257 | 249 | if [ "$val" = "yes" ]; then | ||
258 | 250 | neg=1 | ||
259 | 251 | fi | ||
260 | 252 | ;; | ||
261 | 253 | *) | ||
262 | 254 | echo "Invalid attribute in $opt_spec: $line" >&2 | ||
263 | 255 | exit 1 | ||
264 | 256 | esac | ||
265 | 257 | done < "$opt_spec" | ||
266 | 258 | |||
267 | 259 | if [ -z "$opt" ]; then | ||
268 | 260 | echo "No long attribute in option spec $opt_spec" >&2 | ||
269 | 261 | exit 1 | ||
270 | 262 | fi | ||
271 | 263 | |||
272 | 264 | if [ $neg -eq 1 ]; then | ||
273 | 265 | if [ -z "$default_val" ] || [ "$default_val" != "yes" ]; then | ||
274 | 266 | echo "Option $opt_spec is negatable but not default: yes" >&2 | ||
275 | 267 | exit 1 | ||
276 | 268 | fi | ||
277 | 269 | fi | ||
278 | 270 | |||
279 | 271 | if [ $size -eq 1 -a -n "$default_val" ]; then | ||
280 | 272 | default_val=$(size_to_bytes $default_val) | ||
281 | 273 | fi | ||
282 | 274 | |||
283 | 275 | eval "OPT_${opt}"="$default_val" | ||
284 | 276 | done | ||
285 | 277 | } | ||
286 | 278 | |||
287 | 279 | _parse_config_files() { | ||
288 | 280 | |||
289 | 281 | for config_file in "$@"; do | ||
290 | 282 | test -f "$config_file" || continue | ||
291 | 283 | |||
292 | 284 | while read config_opt; do | ||
293 | 285 | |||
294 | 286 | echo "$config_opt" | grep '^[ ]*[^#]' >/dev/null 2>&1 || continue | ||
295 | 287 | |||
296 | 288 | config_opt="$(echo "$config_opt" | sed -e 's/^ *//g' -e 's/ *$//g' -e 's/[ ]*=[ ]*/=/' -e 's/[ ]*#.*$//')" | ||
297 | 289 | |||
298 | 290 | [ "$config_opt" = "" ] && continue | ||
299 | 291 | |||
300 | 292 | if ! [ "$HAVE_EXT_ARGV" ]; then | ||
301 | 293 | config_opt="--$config_opt" | ||
302 | 294 | fi | ||
303 | 295 | |||
304 | 296 | _parse_command_line "$config_opt" | ||
305 | 297 | |||
306 | 298 | done < "$config_file" | ||
307 | 299 | |||
308 | 300 | HAVE_EXT_ARGV="" # reset for each file | ||
309 | 301 | |||
310 | 302 | done | ||
311 | 303 | } | ||
312 | 304 | |||
313 | 305 | _parse_command_line() { | ||
314 | 306 | local opt="" | ||
315 | 307 | local val="" | ||
316 | 308 | local next_opt_is_val="" | ||
317 | 309 | local opt_is_ok="" | ||
318 | 310 | local opt_is_negated="" | ||
319 | 311 | local real_opt="" | ||
320 | 312 | local required_arg="" | ||
321 | 313 | local spec="" | ||
322 | 314 | |||
323 | 315 | for opt in "$@"; do | ||
324 | 316 | if [ "$opt" = "--" -o "$opt" = "----" ]; then | ||
325 | 317 | HAVE_EXT_ARGV=1 | ||
326 | 318 | continue | ||
327 | 319 | fi | ||
328 | 320 | if [ "$HAVE_EXT_ARGV" ]; then | ||
329 | 321 | if [ "$EXT_ARGV" ]; then | ||
330 | 322 | EXT_ARGV="$EXT_ARGV $opt" | ||
331 | 323 | else | ||
332 | 324 | EXT_ARGV="$opt" | ||
333 | 325 | fi | ||
334 | 326 | continue | ||
335 | 327 | fi | ||
336 | 328 | |||
337 | 329 | if [ "$next_opt_is_val" ]; then | ||
338 | 330 | next_opt_is_val="" | ||
339 | 331 | if [ $# -eq 0 ] || [ $(expr "$opt" : "-") -eq 1 ]; then | ||
340 | 332 | option_error "$real_opt requires a $required_arg argument" | ||
341 | 333 | continue | ||
342 | 334 | fi | ||
343 | 335 | val="$opt" | ||
344 | 336 | opt_is_ok=1 | ||
345 | 337 | else | ||
346 | 338 | if [ $(expr "$opt" : "-") -eq 0 ]; then | ||
347 | 339 | if [ -z "$ARGV" ]; then | ||
348 | 340 | ARGV="$opt" | ||
349 | 341 | else | ||
350 | 342 | ARGV="$ARGV $opt" | ||
351 | 343 | fi | ||
352 | 344 | continue | ||
353 | 345 | fi | ||
354 | 346 | |||
355 | 347 | real_opt="$opt" | ||
356 | 348 | |||
357 | 349 | if $(echo $opt | grep '^--no-' >/dev/null); then | ||
358 | 350 | opt_is_negated=1 | ||
359 | 351 | opt=$(echo $opt | sed 's/^--no-//') | ||
360 | 352 | else | ||
361 | 353 | opt_is_negated="" | ||
362 | 354 | opt=$(echo $opt | sed 's/^-*//') | ||
363 | 355 | fi | ||
364 | 356 | |||
365 | 357 | if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then | ||
366 | 358 | val="$(echo $opt | awk -F= '{print $2}')" | ||
367 | 359 | opt="$(echo $opt | awk -F= '{print $1}')" | ||
368 | 360 | fi | ||
369 | 361 | |||
370 | 362 | if [ -f "$TMPDIR/po/$opt" ]; then | ||
371 | 363 | spec="$TMPDIR/po/$opt" | ||
372 | 364 | else | ||
373 | 365 | spec=$(grep "^short form:-$opt\$" "$TMPDIR"/po/* | cut -d ':' -f 1) | ||
374 | 366 | if [ -z "$spec" ]; then | ||
375 | 367 | option_error "Unknown option: $real_opt" | ||
376 | 368 | continue | ||
377 | 369 | fi | ||
378 | 370 | fi | ||
379 | 371 | |||
380 | 372 | required_arg=$(cat "$spec" | awk -F: '/^type:/{print $2}') | ||
381 | 373 | if [ "$required_arg" ]; then | ||
382 | 374 | if [ "$val" ]; then | ||
383 | 375 | opt_is_ok=1 | ||
384 | 376 | else | ||
385 | 377 | next_opt_is_val=1 | ||
386 | 378 | fi | ||
387 | 379 | else | ||
388 | 380 | if [ "$val" ]; then | ||
389 | 381 | option_error "Option $real_opt does not take a value" | ||
390 | 382 | continue | ||
391 | 383 | fi | ||
392 | 384 | if [ "$opt_is_negated" ]; then | ||
393 | 385 | val="" | ||
394 | 386 | else | ||
395 | 387 | val="yes" | ||
396 | 388 | fi | ||
397 | 389 | opt_is_ok=1 | ||
398 | 390 | fi | ||
399 | 391 | fi | ||
400 | 392 | |||
401 | 393 | if [ "$opt_is_ok" ]; then | ||
402 | 394 | opt=$(cat "$spec" | grep '^long:' | cut -d':' -f2 | sed 's/-/_/g' | tr [:lower:] [:upper:]) | ||
403 | 395 | |||
404 | 396 | if grep "^type:size" "$spec" >/dev/null; then | ||
405 | 397 | val=$(size_to_bytes $val) | ||
406 | 398 | fi | ||
407 | 399 | |||
408 | 400 | eval "OPT_$opt"="'$val'" | ||
409 | 401 | |||
410 | 402 | opt="" | ||
411 | 403 | val="" | ||
412 | 404 | next_opt_is_val="" | ||
413 | 405 | opt_is_ok="" | ||
414 | 406 | opt_is_negated="" | ||
415 | 407 | real_opt="" | ||
416 | 408 | required_arg="" | ||
417 | 409 | spec="" | ||
418 | 410 | fi | ||
419 | 411 | done | ||
420 | 412 | } | ||
421 | 413 | |||
422 | 414 | size_to_bytes() { | ||
423 | 415 | local size="$1" | ||
424 | 416 | echo $size | perl -ne '%f=(B=>1, K=>1_024, M=>1_048_576, G=>1_073_741_824, T=>1_099_511_627_776); m/^(\d+)([kMGT])?/i; print $1 * $f{uc($2 || "B")};' | ||
425 | 417 | } | ||
426 | 418 | |||
427 | 419 | # ########################################################################### | ||
428 | 420 | # End parse_options package | ||
429 | 421 | # ########################################################################### | ||
430 | 15 | 422 | ||
431 | 16 | # ########################################################################### | 423 | # ########################################################################### |
432 | 17 | # tmpdir package | 424 | # tmpdir package |
433 | @@ -22,18 +429,21 @@ | |||
434 | 22 | # See https://launchpad.net/percona-toolkit for more information. | 429 | # See https://launchpad.net/percona-toolkit for more information. |
435 | 23 | # ########################################################################### | 430 | # ########################################################################### |
436 | 24 | 431 | ||
437 | 432 | |||
438 | 433 | set -u | ||
439 | 434 | |||
440 | 25 | TMPDIR="" | 435 | TMPDIR="" |
441 | 26 | 436 | ||
442 | 27 | mk_tmpdir() { | 437 | mk_tmpdir() { |
444 | 28 | local dir=${1:-""} | 438 | local dir="${1:-""}" |
445 | 29 | 439 | ||
446 | 30 | if [ -n "$dir" ]; then | 440 | if [ -n "$dir" ]; then |
447 | 31 | if [ ! -d "$dir" ]; then | 441 | if [ ! -d "$dir" ]; then |
449 | 32 | mkdir $dir || die "Cannot make tmpdir $dir" | 442 | mkdir "$dir" || die "Cannot make tmpdir $dir" |
450 | 33 | fi | 443 | fi |
451 | 34 | TMPDIR="$dir" | 444 | TMPDIR="$dir" |
452 | 35 | else | 445 | else |
454 | 36 | local tool=`basename $0` | 446 | local tool="${0##*/}" |
455 | 37 | local pid="$$" | 447 | local pid="$$" |
456 | 38 | TMPDIR=`mktemp -d /tmp/${tool}.${pid}.XXXXX` \ | 448 | TMPDIR=`mktemp -d /tmp/${tool}.${pid}.XXXXX` \ |
457 | 39 | || die "Cannot make secure tmpdir" | 449 | || die "Cannot make secure tmpdir" |
458 | @@ -42,7 +452,7 @@ | |||
459 | 42 | 452 | ||
460 | 43 | rm_tmpdir() { | 453 | rm_tmpdir() { |
461 | 44 | if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then | 454 | if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then |
463 | 45 | rm -rf $TMPDIR | 455 | rm -rf "$TMPDIR" |
464 | 46 | fi | 456 | fi |
465 | 47 | TMPDIR="" | 457 | TMPDIR="" |
466 | 48 | } | 458 | } |
467 | @@ -51,27 +461,68 @@ | |||
468 | 51 | # End tmpdir package | 461 | # End tmpdir package |
469 | 52 | # ########################################################################### | 462 | # ########################################################################### |
470 | 53 | 463 | ||
492 | 54 | # ######################################################################## | 464 | # ########################################################################### |
493 | 55 | # Some global setup is necessary for cross-platform compatibility, even | 465 | # alt_cmds package |
494 | 56 | # when sourcing this script for testing purposes. | 466 | # This package is a copy without comments from the original. The original |
495 | 57 | # ######################################################################## | 467 | # with comments and its test file can be found in the Bazaar repository at, |
496 | 58 | AP_AWK="$(which awk)" | 468 | # lib/bash/alt_cmds.sh |
497 | 59 | which gawk >/dev/null 2>&1 && AP_AWK="$(which gawk)" | 469 | # t/lib/bash/alt_cmds.sh |
498 | 60 | AP_SED="$(which sed)" | 470 | # See https://launchpad.net/percona-toolkit for more information. |
499 | 61 | which gsed >/dev/null 2>&1 && AP_SED="$(which gsed)" | 471 | # ########################################################################### |
500 | 62 | AP_GREP="$(which grep)" | 472 | |
501 | 63 | which ggrep >/dev/null 2>&1 && AP_GREP="$(which ggrep)" | 473 | |
502 | 64 | 474 | set -u | |
503 | 65 | # ######################################################################## | 475 | |
504 | 66 | # Globals, helper functions | 476 | _seq() { |
505 | 67 | # ######################################################################## | 477 | local i="$1" |
506 | 68 | 478 | awk "BEGIN { for(i=1; i<=$i; i++) print i; }" | |
507 | 69 | # The awk code for fuzzy rounding. (It's used in a few places, so makes sense | 479 | } |
508 | 70 | # not to duplicate). It fuzzy-rounds the variable named fuzzy_var. It goes in | 480 | |
509 | 71 | # steps of 5, 10, 25, then repeats by a factor of 10 larger (50, 100, 250), and | 481 | _pidof() { |
510 | 72 | # so on, until it finds a number that's large enough. The pattern is slightly | 482 | local cmd="$1" |
511 | 73 | # broken between the initial 1 and 50, because rounding to the nearest 2.5 | 483 | if ! pidof "$cmd" 2>/dev/null; then |
512 | 74 | # doesn't seem right to me. | 484 | ps -eo pid,ucomm | awk -v comm="$cmd" '$2 == comm { print $1 }' |
513 | 485 | fi | ||
514 | 486 | } | ||
515 | 487 | |||
516 | 488 | _lsof() { | ||
517 | 489 | local pid="$1" | ||
518 | 490 | if ! lsof -p $pid 2>/dev/null; then | ||
519 | 491 | /bin/ls -l /proc/$pid/fd 2>/dev/null | ||
520 | 492 | fi | ||
521 | 493 | } | ||
522 | 494 | |||
523 | 495 | |||
524 | 496 | |||
525 | 497 | _which() { | ||
526 | 498 | if [ -x /usr/bin/which ]; then | ||
527 | 499 | /usr/bin/which "$1" 2>/dev/null | awk '{print $1}' | ||
528 | 500 | elif which which 1>/dev/null 2>&1; then | ||
529 | 501 | which "$1" 2>/dev/null | awk '{print $1}' | ||
530 | 502 | else | ||
531 | 503 | echo "$1" | ||
532 | 504 | fi | ||
533 | 505 | } | ||
534 | 506 | |||
535 | 507 | # ########################################################################### | ||
536 | 508 | # End alt_cmds package | ||
537 | 509 | # ########################################################################### | ||
538 | 510 | |||
539 | 511 | # ########################################################################### | ||
540 | 512 | # report_formatting package | ||
541 | 513 | # This package is a copy without comments from the original. The original | ||
542 | 514 | # with comments and its test file can be found in the Bazaar repository at, | ||
543 | 515 | # lib/bash/report_formatting.sh | ||
544 | 516 | # t/lib/bash/report_formatting.sh | ||
545 | 517 | # See https://launchpad.net/percona-toolkit for more information. | ||
546 | 518 | # ########################################################################### | ||
547 | 519 | |||
548 | 520 | |||
549 | 521 | set -u | ||
550 | 522 | |||
551 | 523 | POSIXLY_CORRECT=1 | ||
552 | 524 | export POSIXLY_CORRECT | ||
553 | 525 | |||
554 | 75 | fuzzy_formula=' | 526 | fuzzy_formula=' |
555 | 76 | rounded = 0; | 527 | rounded = 0; |
556 | 77 | if (fuzzy_var <= 10 ) { | 528 | if (fuzzy_var <= 10 ) { |
557 | @@ -94,108 +545,461 @@ | |||
558 | 94 | factor = factor * 10; | 545 | factor = factor * 10; |
559 | 95 | }' | 546 | }' |
560 | 96 | 547 | ||
588 | 97 | # The temp files are for storing working results so we don't call commands many | 548 | fuzz () { |
589 | 98 | # times (gives inconsistent results, maybe adds load on things I don't want to | 549 | awk -v fuzzy_var="$1" "BEGIN { ${fuzzy_formula} print fuzzy_var;}" |
590 | 99 | # such as RAID controllers). They must not exist -- if they did, someone would | 550 | } |
591 | 100 | # symlink them to /etc/passwd and then run this program as root. Call this | 551 | |
592 | 101 | # function with "rm" or "touch" as an argument. | 552 | fuzzy_pct () { |
593 | 102 | temp_files() { | 553 | local pct="$(awk -v one="$1" -v two="$2" 'BEGIN{ if (two > 0) { printf "%d", one/two*100; } else {print 0} }')"; |
594 | 103 | for file in $TMPDIR/percona-toolkit{,-mysql-variables,-mysql-status,-innodb-status} \ | 554 | echo "$(fuzz "${pct}")%" |
595 | 104 | $TMPDIR/percona-toolkit{2,-mysql-databases,-mysql-processlist,-noncounters} \ | 555 | } |
596 | 105 | $TMPDIR/percona-toolkit-mysql{dump,-slave}; | 556 | |
570 | 106 | do | ||
571 | 107 | case "$1" in | ||
572 | 108 | touch) | ||
573 | 109 | if ! touch "${file}"; then | ||
574 | 110 | echo "I can't make my temp file ${file}"; | ||
575 | 111 | exit 1; | ||
576 | 112 | fi | ||
577 | 113 | ;; | ||
578 | 114 | rm) | ||
579 | 115 | rm -f "${file}" | ||
580 | 116 | ;; | ||
581 | 117 | esac | ||
582 | 118 | done | ||
583 | 119 | } | ||
584 | 120 | |||
585 | 121 | # Print a space-padded string into $line. Then translate spaces to hashes, and | ||
586 | 122 | # underscores to spaces. End result is a line of hashes with words at the | ||
587 | 123 | # start. | ||
597 | 124 | section () { | 557 | section () { |
609 | 125 | line="$(printf '#_%-60s' "$1_")" | 558 | local str="$1" |
610 | 126 | line="${line// /#}" | 559 | awk -v var="${str} _" 'BEGIN { |
611 | 127 | printf "%s\n" "${line//_/ }" | 560 | line = sprintf("# %-60s", var); |
612 | 128 | } | 561 | i = index(line, "_"); |
613 | 129 | 562 | x = substr(line, i); | |
614 | 130 | # Print a "name | value" line. | 563 | gsub(/[_ \t]/, "#", x); |
615 | 131 | name_val() { | 564 | printf("%s%s\n", substr(line, 1, i-1), x); |
616 | 132 | printf "%20s | %s\n" "$1" "$2" | 565 | }' |
617 | 133 | } | 566 | } |
618 | 134 | 567 | ||
619 | 135 | # Converts a value to units of power of 2. Optional precision is $2. | 568 | NAME_VAL_LEN=12 |
620 | 569 | name_val () { | ||
621 | 570 | printf "%+*s | %s\n" "${NAME_VAL_LEN}" "$1" "$2" | ||
622 | 571 | } | ||
623 | 572 | |||
624 | 136 | shorten() { | 573 | shorten() { |
639 | 137 | unit=k | 574 | local num="$1" |
640 | 138 | size=1024 | 575 | local prec="${2:-2}" |
641 | 139 | if [ $1 -ge 1099511627776 ] ; then | 576 | local div="${3:-1024}" |
642 | 140 | size=1099511627776 | 577 | |
643 | 141 | unit=T | 578 | echo "$num" | awk -v prec="$prec" -v div="$div" ' |
644 | 142 | elif [ $1 -ge 1073741824 ] ; then | 579 | { |
645 | 143 | size=1073741824 | 580 | size = 4; |
646 | 144 | unit=G | 581 | val = $1; |
647 | 145 | elif [ $1 -ge 1048576 ] ; then | 582 | |
648 | 146 | size=1048576 | 583 | unit = val >= 1099511627776 ? "T" : val >= 1073741824 ? "G" : val >= 1048576 ? "M" : val >= 1024 ? "k" : ""; |
649 | 147 | unit=M | 584 | |
650 | 148 | fi | 585 | while ( int(val) && !(val % 1024) ) { |
651 | 149 | result=$(echo "$1 $size ${2:-0}" | $AP_AWK '{printf "%." $3 "f", $1 / $2}') | 586 | val /= 1024; |
652 | 150 | echo "${result}${unit}" | 587 | } |
653 | 588 | |||
654 | 589 | while ( val > 1000 ) { | ||
655 | 590 | val /= div; | ||
656 | 591 | } | ||
657 | 592 | |||
658 | 593 | printf "%.*f%s", prec, val, unit; | ||
659 | 594 | } | ||
660 | 595 | ' | ||
661 | 151 | } | 596 | } |
662 | 152 | 597 | ||
663 | 153 | # Collapse a file into an aggregated list; file must be created with 'sort | | ||
664 | 154 | # uniq -c'. This function is copy-pasted from 'summary' so see there for full | ||
665 | 155 | # docs and tests. | ||
666 | 156 | # ############################################################################## | ||
667 | 157 | group_concat () { | 598 | group_concat () { |
672 | 158 | sed -e '{H; $!d}' -e 'x' -e 's/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/, //' ${1} | 599 | sed -e '{H; $!d;}' -e 'x' -e 's/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/, //' "${1}" |
673 | 159 | } | 600 | } |
674 | 160 | 601 | ||
675 | 161 | # Accepts a number of seconds, and outputs a d+h:m:s formatted string | 602 | # ########################################################################### |
676 | 603 | # End report_formatting package | ||
677 | 604 | # ########################################################################### | ||
678 | 605 | |||
679 | 606 | # ########################################################################### | ||
680 | 607 | # summary_common package | ||
681 | 608 | # This package is a copy without comments from the original. The original | ||
682 | 609 | # with comments and its test file can be found in the Bazaar repository at, | ||
683 | 610 | # lib/bash/summary_common.sh | ||
684 | 611 | # t/lib/bash/summary_common.sh | ||
685 | 612 | # See https://launchpad.net/percona-toolkit for more information. | ||
686 | 613 | # ########################################################################### | ||
687 | 614 | |||
688 | 615 | |||
689 | 616 | set -u | ||
690 | 617 | |||
691 | 618 | CMD_FILE="$( _which file 2>/dev/null )" | ||
692 | 619 | CMD_NM="$( _which nm 2>/dev/null )" | ||
693 | 620 | CMD_OBJDUMP="$( _which objdump 2>/dev/null )" | ||
694 | 621 | |||
695 | 622 | get_nice_of_pid () { | ||
696 | 623 | local pid="$1" | ||
697 | 624 | local niceness="$(ps -p $pid -o nice | awk '$1 !~ /[^0-9]/ {print $1; exit}')" | ||
698 | 625 | |||
699 | 626 | if [ -n "${niceness}" ]; then | ||
700 | 627 | echo $niceness | ||
701 | 628 | else | ||
702 | 629 | local tmpfile="$TMPDIR/nice_through_c.tmp.c" | ||
703 | 630 | _d "Getting the niceness from ps failed, somehow. We are about to try this:" | ||
704 | 631 | cat <<EOC > "$tmpfile" | ||
705 | 632 | |||
706 | 633 | int main(void) { | ||
707 | 634 | int priority = getpriority(PRIO_PROCESS, $pid); | ||
708 | 635 | if ( priority == -1 && errno == ESRCH ) { | ||
709 | 636 | return 1; | ||
710 | 637 | } | ||
711 | 638 | else { | ||
712 | 639 | printf("%d\\n", priority); | ||
713 | 640 | return 0; | ||
714 | 641 | } | ||
715 | 642 | } | ||
716 | 643 | |||
717 | 644 | EOC | ||
718 | 645 | local c_comp=$(_which gcc) | ||
719 | 646 | if [ -z "${c_comp}" ]; then | ||
720 | 647 | c_comp=$(_which cc) | ||
721 | 648 | fi | ||
722 | 649 | _d "$tmpfile: $( cat "$tmpfile" )" | ||
723 | 650 | _d "$c_comp -xc \"$tmpfile\" -o \"$tmpfile\" && eval \"$tmpfile\"" | ||
724 | 651 | $c_comp -xc "$tmpfile" -o "$tmpfile" 2>/dev/null && eval "$tmpfile" 2>/dev/null | ||
725 | 652 | if [ $? -ne 0 ]; then | ||
726 | 653 | echo "?" | ||
727 | 654 | _d "Failed to get a niceness value for $pid" | ||
728 | 655 | fi | ||
729 | 656 | fi | ||
730 | 657 | } | ||
731 | 658 | |||
732 | 659 | get_oom_of_pid () { | ||
733 | 660 | local pid="$1" | ||
734 | 661 | local oom_adj="" | ||
735 | 662 | |||
736 | 663 | if [ -n "${pid}" -a -e /proc/cpuinfo ]; then | ||
737 | 664 | if [ -s "/proc/$pid/oom_score_adj" ]; then | ||
738 | 665 | oom_adj=$(cat "/proc/$pid/oom_score_adj" 2>/dev/null) | ||
739 | 666 | _d "For $pid, the oom value is $oom_adj, retreived from oom_score_adj" | ||
740 | 667 | else | ||
741 | 668 | oom_adj=$(cat "/proc/$pid/oom_adj" 2>/dev/null) | ||
742 | 669 | _d "For $pid, the oom value is $oom_adj, retreived from oom_adj" | ||
743 | 670 | fi | ||
744 | 671 | fi | ||
745 | 672 | |||
746 | 673 | if [ -n "${oom_adj}" ]; then | ||
747 | 674 | echo "${oom_adj}" | ||
748 | 675 | else | ||
749 | 676 | echo "?" | ||
750 | 677 | _d "Can't find the oom value for $pid" | ||
751 | 678 | fi | ||
752 | 679 | } | ||
753 | 680 | |||
754 | 681 | has_symbols () { | ||
755 | 682 | local executable="$(_which "$1")" | ||
756 | 683 | local has_symbols="" | ||
757 | 684 | |||
758 | 685 | if [ "${CMD_FILE}" ] \ | ||
759 | 686 | && [ "$($CMD_FILE "${executable}" | grep 'not stripped' )" ]; then | ||
760 | 687 | has_symbols=1 | ||
761 | 688 | elif [ "${CMD_NM}" ] \ | ||
762 | 689 | || [ "${CMD_OBJDMP}" ]; then | ||
763 | 690 | if [ "${CMD_NM}" ] \ | ||
764 | 691 | && [ !"$("${CMD_NM}" -- "${executable}" 2>&1 | grep 'File format not recognized' )" ]; then | ||
765 | 692 | if [ -z "$( $CMD_NM -- "${executable}" 2>&1 | grep ': no symbols' )" ]; then | ||
766 | 693 | has_symbols=1 | ||
767 | 694 | fi | ||
768 | 695 | elif [ -z "$("${CMD_OBJDUMP}" -t -- "${executable}" | grep '^no symbols$' )" ]; then | ||
769 | 696 | has_symbols=1 | ||
770 | 697 | fi | ||
771 | 698 | fi | ||
772 | 699 | |||
773 | 700 | if [ "${has_symbols}" ]; then | ||
774 | 701 | echo "Yes" | ||
775 | 702 | else | ||
776 | 703 | echo "No" | ||
777 | 704 | fi | ||
778 | 705 | } | ||
779 | 706 | |||
780 | 707 | setup_data_dir () { | ||
781 | 708 | local existing_dir="$1" | ||
782 | 709 | local data_dir="" | ||
783 | 710 | if [ -z "$existing_dir" ]; then | ||
784 | 711 | mkdir "$TMPDIR/data" || die "Cannot mkdir $TMPDIR/data" | ||
785 | 712 | data_dir="$TMPDIR/data" | ||
786 | 713 | else | ||
787 | 714 | if [ ! -d "$existing_dir" ]; then | ||
788 | 715 | mkdir "$existing_dir" || die "Cannot mkdir $existing_dir" | ||
789 | 716 | elif [ "$( ls -A "$existing_dir" )" ]; then | ||
790 | 717 | die "--save-samples directory isn't empty, halting." | ||
791 | 718 | fi | ||
792 | 719 | touch "$existing_dir/test" || die "Cannot write to $existing_dir" | ||
793 | 720 | rm "$existing_dir/test" || die "Cannot rm $existing_dir/test" | ||
794 | 721 | data_dir="$existing_dir" | ||
795 | 722 | fi | ||
796 | 723 | echo "$data_dir" | ||
797 | 724 | } | ||
798 | 725 | |||
799 | 726 | get_var () { | ||
800 | 727 | local varname="$1" | ||
801 | 728 | local file="$2" | ||
802 | 729 | awk -v pattern="${varname}" '$1 == pattern { if (length($2)) { len = length($1); print substr($0, len+index(substr($0, len+1), $2)) } }' "${file}" | ||
803 | 730 | } | ||
804 | 731 | |||
805 | 732 | # ########################################################################### | ||
806 | 733 | # End summary_common package | ||
807 | 734 | # ########################################################################### | ||
808 | 735 | |||
809 | 736 | # ########################################################################### | ||
810 | 737 | # collect_mysql_info package | ||
811 | 738 | # This package is a copy without comments from the original. The original | ||
812 | 739 | # with comments and its test file can be found in the Bazaar repository at, | ||
813 | 740 | # lib/bash/collect_mysql_info.sh | ||
814 | 741 | # t/lib/bash/collect_mysql_info.sh | ||
815 | 742 | # See https://launchpad.net/percona-toolkit for more information. | ||
816 | 743 | # ########################################################################### | ||
817 | 744 | |||
818 | 745 | |||
819 | 746 | |||
820 | 747 | CMD_MYSQL="${CMD_MYSQL:-""}" | ||
821 | 748 | CMD_MYSQLDUMP="${CMD_MYSQLDUMP:-""}" | ||
822 | 749 | |||
823 | 750 | collect_mysqld_instances () { | ||
824 | 751 | local variables_file="$1" | ||
825 | 752 | |||
826 | 753 | local pids="$(_pidof mysqld)" | ||
827 | 754 | |||
828 | 755 | if [ -n "$pids" ]; then | ||
829 | 756 | |||
830 | 757 | for pid in $pids; do | ||
831 | 758 | local nice="$( get_nice_of_pid $pid )" | ||
832 | 759 | local oom="$( get_oom_of_pid $pid )" | ||
833 | 760 | echo "internal::nice_of_$pid $nice" >> "$variables_file" | ||
834 | 761 | echo "internal::oom_of_$pid $oom" >> "$variables_file" | ||
835 | 762 | done | ||
836 | 763 | |||
837 | 764 | pids="$(echo $pids | sed -e 's/ /,/g')" | ||
838 | 765 | ps ww -p "$pids" 2>/dev/null | ||
839 | 766 | else | ||
840 | 767 | echo "mysqld doesn't appear to be running" | ||
841 | 768 | fi | ||
842 | 769 | |||
843 | 770 | } | ||
844 | 771 | |||
845 | 772 | find_my_cnf_file() { | ||
846 | 773 | local file="$1" | ||
847 | 774 | local port="${2:-""}" | ||
848 | 775 | |||
849 | 776 | local cnf_file="" | ||
850 | 777 | if test -n "$port" && grep -- "/mysqld.*--port=$port" "${file}" >/dev/null 2>&1 ; then | ||
851 | 778 | cnf_file="$(grep -- "/mysqld.*--port=$port" "${file}" \ | ||
852 | 779 | | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \ | ||
853 | 780 | | head -n1)" | ||
854 | 781 | else | ||
855 | 782 | cnf_file="$(grep '/mysqld' "${file}" \ | ||
856 | 783 | | awk 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \ | ||
857 | 784 | | head -n1)" | ||
858 | 785 | fi | ||
859 | 786 | |||
860 | 787 | if [ ! -n "${cnf_file}" ]; then | ||
861 | 788 | cnf_file="/etc/my.cnf"; | ||
862 | 789 | if [ ! -e "${cnf_file}" ]; then | ||
863 | 790 | cnf_file="/etc/mysql/my.cnf"; | ||
864 | 791 | fi | ||
865 | 792 | if [ ! -e "${cnf_file}" ]; then | ||
866 | 793 | cnf_file="/var/db/mysql/my.cnf"; | ||
867 | 794 | fi | ||
868 | 795 | fi | ||
869 | 796 | |||
870 | 797 | echo "$cnf_file" | ||
871 | 798 | } | ||
872 | 799 | |||
873 | 800 | collect_mysql_variables () { | ||
874 | 801 | $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW /*!40100 GLOBAL*/ VARIABLES' | ||
875 | 802 | } | ||
876 | 803 | |||
877 | 804 | collect_mysql_status () { | ||
878 | 805 | $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW /*!50000 GLOBAL*/ STATUS' | ||
879 | 806 | } | ||
880 | 807 | |||
881 | 808 | collect_mysql_databases () { | ||
882 | 809 | $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW DATABASES' 2>/dev/null | ||
883 | 810 | } | ||
884 | 811 | |||
885 | 812 | collect_mysql_plugins () { | ||
886 | 813 | $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW PLUGINS' 2>/dev/null | ||
887 | 814 | } | ||
888 | 815 | |||
889 | 816 | collect_mysql_slave_status () { | ||
890 | 817 | $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW SLAVE STATUS' 2>/dev/null | ||
891 | 818 | } | ||
892 | 819 | |||
893 | 820 | collect_mysql_innodb_status () { | ||
894 | 821 | $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW /*!50000 ENGINE*/ INNODB STATUS' 2>/dev/null | ||
895 | 822 | } | ||
896 | 823 | |||
897 | 824 | collect_mysql_processlist () { | ||
898 | 825 | $CMD_MYSQL $EXT_ARGV -ssE -e 'SHOW FULL PROCESSLIST' 2>/dev/null | ||
899 | 826 | } | ||
900 | 827 | |||
901 | 828 | collect_mysql_users () { | ||
902 | 829 | $CMD_MYSQL $EXT_ARGV -ss -e 'SELECT COUNT(*), SUM(user=""), SUM(password=""), SUM(password NOT LIKE "*%") FROM mysql.user' 2>/dev/null | ||
903 | 830 | } | ||
904 | 831 | |||
905 | 832 | collect_master_logs_status () { | ||
906 | 833 | local master_logs_file="$1" | ||
907 | 834 | local master_status_file="$2" | ||
908 | 835 | $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER LOGS' > "$master_logs_file" 2>/dev/null | ||
909 | 836 | $CMD_MYSQL $EXT_ARGV -ss -e 'SHOW MASTER STATUS' > "$master_status_file" 2>/dev/null | ||
910 | 837 | } | ||
911 | 838 | |||
912 | 839 | collect_mysql_deferred_status () { | ||
913 | 840 | local status_file="$1" | ||
914 | 841 | collect_mysql_status > "$TMPDIR/defer_gatherer" | ||
915 | 842 | join "$status_file" "$TMPDIR/defer_gatherer" | ||
916 | 843 | } | ||
917 | 844 | |||
918 | 845 | collect_internal_vars () { | ||
919 | 846 | local mysqld_executables="${1:-""}" | ||
920 | 847 | |||
921 | 848 | local FNV_64="" | ||
922 | 849 | if $CMD_MYSQL $EXT_ARGV -e 'SELECT FNV_64("a")' >/dev/null 2>&1; then | ||
923 | 850 | FNV_64="Enabled"; | ||
924 | 851 | else | ||
925 | 852 | FNV_64="Unknown"; | ||
926 | 853 | fi | ||
927 | 854 | |||
928 | 855 | local now="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT NOW()')" | ||
929 | 856 | local user="$($CMD_MYSQL $EXT_ARGV -ss -e 'SELECT CURRENT_USER()')" | ||
930 | 857 | local trigger_count=$($CMD_MYSQL $EXT_ARGV -ss -e "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS" 2>/dev/null) | ||
931 | 858 | |||
932 | 859 | echo "pt-summary-internal-mysql_executable $CMD_MYSQL" | ||
933 | 860 | echo "pt-summary-internal-now $now" | ||
934 | 861 | echo "pt-summary-internal-user $user" | ||
935 | 862 | echo "pt-summary-internal-FNV_64 $FNV_64" | ||
936 | 863 | echo "pt-summary-internal-trigger_count $trigger_count" | ||
937 | 864 | |||
938 | 865 | if [ -e "$mysqld_executables" ]; then | ||
939 | 866 | local i=1 | ||
940 | 867 | while read executable; do | ||
941 | 868 | echo "pt-summary-internal-mysqld_executable_${i} $(has_symbols "$executable")" | ||
942 | 869 | i=$(($i + 1)) | ||
943 | 870 | done < "$mysqld_executables" | ||
944 | 871 | fi | ||
945 | 872 | } | ||
946 | 873 | |||
947 | 874 | get_mysqldump_for () { | ||
948 | 875 | local args="$1" | ||
949 | 876 | local dbtodump="${2:-"--all-databases"}" | ||
950 | 877 | |||
951 | 878 | $CMD_MYSQLDUMP $EXT_ARGV --no-data --skip-comments \ | ||
952 | 879 | --skip-add-locks --skip-add-drop-table --compact \ | ||
953 | 880 | --skip-lock-all-tables --skip-lock-tables --skip-set-charset \ | ||
954 | 881 | ${args} --databases $( local IFS=,; echo ${dbtodump}) | ||
955 | 882 | } | ||
956 | 883 | |||
957 | 884 | get_mysqldump_args () { | ||
958 | 885 | local file="$1" | ||
959 | 886 | local trg_arg="" | ||
960 | 887 | |||
961 | 888 | if $CMD_MYSQLDUMP --help --verbose 2>&1 | grep triggers >/dev/null; then | ||
962 | 889 | trg_arg="--routines" | ||
963 | 890 | fi | ||
964 | 891 | |||
965 | 892 | if [ "${trg_arg}" ]; then | ||
966 | 893 | local triggers="--skip-triggers" | ||
967 | 894 | local trg=$(get_var "pt-summary-internal-trigger_count" "$file" ) | ||
968 | 895 | if [ -n "${trg}" ] && [ "${trg}" -gt 0 ]; then | ||
969 | 896 | triggers="--triggers" | ||
970 | 897 | fi | ||
971 | 898 | trg_arg="${trg_arg} ${triggers}"; | ||
972 | 899 | fi | ||
973 | 900 | echo "${trg_arg}" | ||
974 | 901 | } | ||
975 | 902 | |||
976 | 903 | collect_mysqld_executables () { | ||
977 | 904 | local mysqld_instances="$1" | ||
978 | 905 | |||
979 | 906 | for pid in $( grep '/mysqld' "$mysqld_instances" | awk '/^ .*[0-9]/{print $1}' ); do | ||
980 | 907 | ps -o cmd -p $pid | sed -e 's/^\(.*mysqld\) .*/\1/' | grep -v '^CMD$' | ||
981 | 908 | done | sort -u | ||
982 | 909 | } | ||
983 | 910 | |||
984 | 911 | collect_mysql_info () { | ||
985 | 912 | local dir="$1" | ||
986 | 913 | |||
987 | 914 | collect_mysql_variables > "$dir/mysql-variables" | ||
988 | 915 | collect_mysql_status > "$dir/mysql-status" | ||
989 | 916 | collect_mysql_databases > "$dir/mysql-databases" | ||
990 | 917 | collect_mysql_plugins > "$dir/mysql-plugins" | ||
991 | 918 | collect_mysql_slave_status > "$dir/mysql-slave" | ||
992 | 919 | collect_mysql_innodb_status > "$dir/innodb-status" | ||
993 | 920 | collect_mysql_processlist > "$dir/mysql-processlist" | ||
994 | 921 | collect_mysql_users > "$dir/mysql-users" | ||
995 | 922 | |||
996 | 923 | collect_mysqld_instances "$dir/mysql-variables" > "$dir/mysqld-instances" | ||
997 | 924 | collect_mysqld_executables "$dir/mysqld-instances" > "$dir/mysqld-executables" | ||
998 | 925 | |||
999 | 926 | local binlog="$(get_var log_bin "$dir/mysql-variables")" | ||
1000 | 927 | if [ "${binlog}" ]; then | ||
1001 | 928 | collect_master_logs_status "$dir/mysql-master-logs" "$dir/mysql-master-status" | ||
1002 | 929 | fi | ||
1003 | 930 | |||
1004 | 931 | local uptime="$(get_var Uptime "$dir/mysql-status")" | ||
1005 | 932 | local current_time="$($CMD_MYSQL $EXT_ARGV -ss -e \ | ||
1006 | 933 | "SELECT LEFT(NOW() - INTERVAL ${uptime} SECOND, 16)")" | ||
1007 | 934 | |||
1008 | 935 | local port="$(get_var port "$dir/mysql-variables")" | ||
1009 | 936 | local cnf_file="$(find_my_cnf_file "$dir/mysqld-instances" ${port})" | ||
1010 | 937 | |||
1011 | 938 | cat "$cnf_file" > "$dir/mysql-config-file" | ||
1012 | 939 | |||
1013 | 940 | local pid_file="$(get_var "pid_file" "$dir/mysql-variables")" | ||
1014 | 941 | local pid_file_exists="" | ||
1015 | 942 | [ -e "${pid_file}" ] && pid_file_exists=1 | ||
1016 | 943 | echo "pt-summary-internal-pid_file_exists $pid_file_exists" >> "$dir/mysql-variables" | ||
1017 | 944 | |||
1018 | 945 | echo "pt-summary-internal-current_time $current_time" >> "$dir/mysql-variables" | ||
1019 | 946 | echo "pt-summary-internal-Config_File_path $cnf_file" >> "$dir/mysql-variables" | ||
1020 | 947 | collect_internal_vars "$dir/mysqld-executables" >> "$dir/mysql-variables" | ||
1021 | 948 | |||
1022 | 949 | if [ -n "${OPT_DATABASES}" ]; then | ||
1023 | 950 | local trg_arg="$( get_mysqldump_args "$dir/mysql-variables" )" | ||
1024 | 951 | get_mysqldump_for "${trg_arg}" "${OPT_DATABASES}" > "$dir/mysqldump" | ||
1025 | 952 | fi | ||
1026 | 953 | |||
1027 | 954 | ( | ||
1028 | 955 | sleep $OPT_SLEEP | ||
1029 | 956 | collect_mysql_deferred_status "$dir/mysql-status" > "$dir/mysql-status-defer" | ||
1030 | 957 | ) & | ||
1031 | 958 | _d "Forked child is $!" | ||
1032 | 959 | } | ||
1033 | 960 | |||
1034 | 961 | # ########################################################################### | ||
1035 | 962 | # End collect_mysql_info package | ||
1036 | 963 | # ########################################################################### | ||
1037 | 964 | |||
1038 | 965 | # ########################################################################### | ||
1039 | 966 | # report_mysql_info package | ||
1040 | 967 | # This package is a copy without comments from the original. The original | ||
1041 | 968 | # with comments and its test file can be found in the Bazaar repository at, | ||
1042 | 969 | # lib/bash/report_mysql_info.sh | ||
1043 | 970 | # t/lib/bash/report_mysql_info.sh | ||
1044 | 971 | # See https://launchpad.net/percona-toolkit for more information. | ||
1045 | 972 | # ########################################################################### | ||
1046 | 973 | |||
1047 | 974 | |||
1048 | 975 | set -u | ||
1049 | 976 | POSIXLY_CORRECT=1 | ||
1050 | 977 | |||
1051 | 162 | secs_to_time () { | 978 | secs_to_time () { |
1054 | 163 | echo "$1" | $AP_AWK '{ | 979 | awk -v sec="$1" 'BEGIN { |
1055 | 164 | printf( "%d+%02d:%02d:%02d", $1 / 86400, ($1 % 86400) / 3600, ($1 % 3600) / 60, $1 % 60); | 980 | printf( "%d+%02d:%02d:%02d", sec / 86400, (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60); |
1056 | 165 | }' | 981 | }' |
1057 | 166 | } | 982 | } |
1058 | 167 | 983 | ||
1059 | 168 | # gets a value from $TMPDIR/percona-toolkit-mysql-variables. Returns zero if it doesn't | ||
1060 | 169 | # exist. | ||
1061 | 170 | get_var () { | ||
1062 | 171 | v="$($AP_AWK "\$1 ~ /^$1$/ { print \$2 }" $TMPDIR/percona-toolkit-mysql-variables)" | ||
1063 | 172 | echo "${v:-0}" | ||
1064 | 173 | } | ||
1065 | 174 | |||
1066 | 175 | # Returns true if a variable exists | ||
1067 | 176 | var_exists () { | ||
1068 | 177 | $AP_GREP "$1" $TMPDIR/percona-toolkit-mysql-variables >/dev/null 2>&1; | ||
1069 | 178 | } | ||
1070 | 179 | |||
1071 | 180 | # Returns "Enabled", "Disabled", or "Not Supported" depending on whether the | ||
1072 | 181 | # variable exists and is ON or enabled. You can pass 2nd and 3rd variables to | ||
1073 | 182 | # control whether the variable should be 'gt' (numeric greater than) or 'eq' | ||
1074 | 183 | # (string equal) to some value. | ||
1075 | 184 | feat_on() { | 984 | feat_on() { |
1078 | 185 | if var_exists $1 ; then | 985 | local file="$1" |
1079 | 186 | var="$($AP_AWK "\$1 ~ /^$1$/ { print \$2 }" $TMPDIR/percona-toolkit-mysql-variables)" | 986 | local varname="$2" |
1080 | 987 | [ -e "$file" ] || return | ||
1081 | 988 | |||
1082 | 989 | if [ "$( get_var "$varname" "${file}" )" ]; then | ||
1083 | 990 | local var="$(awk "\$1 ~ /^$2$/ { print \$2 }" $file)" | ||
1084 | 187 | if [ "${var}" = "ON" ]; then | 991 | if [ "${var}" = "ON" ]; then |
1085 | 188 | echo "Enabled" | 992 | echo "Enabled" |
1086 | 189 | elif [ "${var}" = "OFF" -o "${var}" = "0" -o -z "${var}" ]; then | 993 | elif [ "${var}" = "OFF" -o "${var}" = "0" -o -z "${var}" ]; then |
1087 | 190 | echo "Disabled" | 994 | echo "Disabled" |
1090 | 191 | elif [ "$2" = "ne" ]; then | 995 | elif [ "$3" = "ne" ]; then |
1091 | 192 | if [ "${var}" != "$3" ]; then | 996 | if [ "${var}" != "$4" ]; then |
1092 | 193 | echo "Enabled" | 997 | echo "Enabled" |
1093 | 194 | else | 998 | else |
1094 | 195 | echo "Disabled" | 999 | echo "Disabled" |
1095 | 196 | fi | 1000 | fi |
1098 | 197 | elif [ "$2" = "gt" ]; then | 1001 | elif [ "$3" = "gt" ]; then |
1099 | 198 | if [ "${var}" -gt "$3" ]; then | 1002 | if [ "${var}" -gt "$4" ]; then |
1100 | 199 | echo "Enabled" | 1003 | echo "Enabled" |
1101 | 200 | else | 1004 | else |
1102 | 201 | echo "Disabled" | 1005 | echo "Disabled" |
1103 | @@ -210,128 +1014,124 @@ | |||
1104 | 210 | fi | 1014 | fi |
1105 | 211 | } | 1015 | } |
1106 | 212 | 1016 | ||
1136 | 213 | # gets a value from $TMPDIR/percona-toolkit-mysql-status. Returns zero if it doesn't | 1017 | get_table_cache () { |
1137 | 214 | # exist. | 1018 | local file="$1" |
1138 | 215 | get_stat () { | 1019 | |
1139 | 216 | v="$($AP_AWK "\$1 ~ /^$1$/ { print \$2 }" $TMPDIR/percona-toolkit-mysql-status)" | 1020 | [ -e "$file" ] || return |
1140 | 217 | echo "${v:-0}" | 1021 | |
1141 | 218 | } | 1022 | local table_cache="" |
1142 | 219 | 1023 | if [ "$( get_var table_open_cache "${file}" )" ]; then | |
1143 | 220 | # Does fuzzy rounding: rounds to nearest interval, but the interval gets larger | 1024 | table_cache="$(get_var table_open_cache "${file}")" |
1144 | 221 | # as the number gets larger. This is to make things easier to diff. | 1025 | else |
1145 | 222 | fuzz () { | 1026 | table_cache="$(get_var table_cache "${file}")" |
1146 | 223 | echo $1 | $AP_AWK "{fuzzy_var=\$1; ${fuzzy_formula} print fuzzy_var;}" | 1027 | fi |
1147 | 224 | } | 1028 | echo ${table_cache:-0} |
1148 | 225 | 1029 | } | |
1149 | 226 | # Fuzzy computes the percent that $1 is of $2 | 1030 | |
1150 | 227 | fuzzy_pct () { | 1031 | get_plugin_status () { |
1151 | 228 | pct=$(echo $1 $2 | $AP_AWK '{ if ($2 > 0) { printf "%d", $1/$2*100; } else {print 0} }'); | 1032 | local file="$1" |
1152 | 229 | echo "$(fuzz ${pct})%" | 1033 | local plugin="$2" |
1153 | 230 | } | 1034 | |
1154 | 231 | 1035 | local status="$(grep -w "$plugin" "$file" | awk '{ print $2 }')" | |
1155 | 232 | # ############################################################################## | 1036 | |
1156 | 233 | # Functions for parsing specific files and getting desired info from them. | 1037 | echo ${status:-"Not found"} |
1157 | 234 | # These are called from within main() and are separated so they can be tested | 1038 | } |
1158 | 235 | # easily. The calling convention is that the data they need to run is prepared | 1039 | |
1159 | 236 | # first by putting it into $TMPDIR/percona-toolkit. Then code that's testing | 1040 | |
1160 | 237 | # just needs to put sample data into $TMPDIR/percona-toolkit and call it. | 1041 | _NO_FALSE_NEGATIVES="" |
1132 | 238 | # ############################################################################## | ||
1133 | 239 | |||
1134 | 240 | # Parses the output of 'ps -e -o args | $AP_GREP mysqld' or 'ps auxww...' | ||
1135 | 241 | # which should be in $TMPDIR/percona-toolkit. | ||
1161 | 242 | parse_mysqld_instances () { | 1042 | parse_mysqld_instances () { |
1163 | 243 | local file=$1 | 1043 | local file="$1" |
1164 | 1044 | local variables_file="$2" | ||
1165 | 1045 | |||
1166 | 244 | local socket=${socket:-""} | 1046 | local socket=${socket:-""} |
1167 | 245 | local port=${port:-""} | 1047 | local port=${port:-""} |
1172 | 246 | local datadir=${datadir:-""} | 1048 | local datadir="${datadir:-""}" |
1173 | 247 | echo " Port Data Directory Socket" | 1049 | |
1174 | 248 | echo " ===== ========================== ======" | 1050 | [ -e "$file" ] || return |
1175 | 249 | $AP_GREP '/mysqld ' $file | while read line; do | 1051 | |
1176 | 1052 | echo " Port Data Directory Nice OOM Socket" | ||
1177 | 1053 | echo " ===== ========================== ==== === ======" | ||
1178 | 1054 | |||
1179 | 1055 | grep '/mysqld ' "$file" | while read line; do | ||
1180 | 1056 | local pid=$(echo "$line" | awk '{print $1;}') | ||
1181 | 250 | for word in ${line}; do | 1057 | for word in ${line}; do |
1185 | 251 | # Some grep doesn't have -o, so I have to pull out the words I want by | 1058 | if echo "${word}" | grep -- "--socket=" > /dev/null; then |
1183 | 252 | # looking at each word | ||
1184 | 253 | if echo "${word}" | $AP_GREP -- "--socket=" > /dev/null; then | ||
1186 | 254 | socket="$(echo "${word}" | cut -d= -f2)" | 1059 | socket="$(echo "${word}" | cut -d= -f2)" |
1187 | 255 | fi | 1060 | fi |
1189 | 256 | if echo "${word}" | $AP_GREP -- "--port=" > /dev/null; then | 1061 | if echo "${word}" | grep -- "--port=" > /dev/null; then |
1190 | 257 | port="$(echo "${word}" | cut -d= -f2)" | 1062 | port="$(echo "${word}" | cut -d= -f2)" |
1191 | 258 | fi | 1063 | fi |
1193 | 259 | if echo "${word}" | $AP_GREP -- "--datadir=" > /dev/null; then | 1064 | if echo "${word}" | grep -- "--datadir=" > /dev/null; then |
1194 | 260 | datadir="$(echo "${word}" | cut -d= -f2)" | 1065 | datadir="$(echo "${word}" | cut -d= -f2)" |
1195 | 261 | fi | 1066 | fi |
1196 | 262 | done | 1067 | done |
1198 | 263 | printf " %5s %-26s %s\n" "${port}" "${datadir}" "${socket}" | 1068 | local nice="$(get_var "internal::nice_of_$pid" "$variables_file")" |
1199 | 1069 | local oom="$(get_var "internal::oom_of_$pid" "$variables_file")" | ||
1200 | 1070 | if [ -n "${_NO_FALSE_NEGATIVES}" ]; then | ||
1201 | 1071 | nice="?" | ||
1202 | 1072 | oom="?" | ||
1203 | 1073 | fi | ||
1204 | 1074 | printf " %5s %-26s %-4s %-3s %s\n" "${port}" "${datadir}" "${nice:-"?"}" "${oom:-"?"}" "${socket}" | ||
1205 | 264 | done | 1075 | done |
1206 | 265 | } | 1076 | } |
1207 | 266 | 1077 | ||
1208 | 267 | # Tries to find the my.cnf file by examining 'ps' output, which should be in | ||
1209 | 268 | # $TMPDIR/percona-toolkit. You have to specify the port for the instance you are | ||
1210 | 269 | # interested in, in case there are multiple instances. | ||
1211 | 270 | find_my_cnf_file() { | ||
1212 | 271 | local file=$1 | ||
1213 | 272 | local port=${2:-""} | ||
1214 | 273 | if test -n "$port" && $AP_GREP -- "/mysqld.*--port=$port" $file >/dev/null 2>&1 ; then | ||
1215 | 274 | $AP_GREP -- "/mysqld.*--port=$port" $file \ | ||
1216 | 275 | | $AP_AWK 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \ | ||
1217 | 276 | | head -n1 | ||
1218 | 277 | else | ||
1219 | 278 | $AP_GREP '/mysqld' $file \ | ||
1220 | 279 | | $AP_AWK 'BEGIN{RS=" "; FS="=";} $1 ~ /--defaults-file/ { print $2; }' \ | ||
1221 | 280 | | head -n1 | ||
1222 | 281 | fi | ||
1223 | 282 | } | ||
1224 | 283 | |||
1225 | 284 | # Gets the MySQL system time. Uses input from $TMPDIR/percona-toolkit-mysql-variables. | ||
1226 | 285 | get_mysql_timezone () { | 1078 | get_mysql_timezone () { |
1228 | 286 | tz="$(get_var time_zone)" | 1079 | local file="$1" |
1229 | 1080 | |||
1230 | 1081 | [ -e "$file" ] || return | ||
1231 | 1082 | |||
1232 | 1083 | local tz="$(get_var time_zone "${file}")" | ||
1233 | 287 | if [ "${tz}" = "SYSTEM" ]; then | 1084 | if [ "${tz}" = "SYSTEM" ]; then |
1235 | 288 | tz="$(get_var system_time_zone)" | 1085 | tz="$(get_var system_time_zone "${file}")" |
1236 | 289 | fi | 1086 | fi |
1237 | 290 | echo "${tz}" | 1087 | echo "${tz}" |
1238 | 291 | } | 1088 | } |
1239 | 292 | 1089 | ||
1240 | 293 | # Gets the MySQL system version. Uses input from $TMPDIR/percona-toolkit-mysql-variables. | ||
1241 | 294 | get_mysql_version () { | 1090 | get_mysql_version () { |
1244 | 295 | name_val Version "$(get_var version) $(get_var version_comment)" | 1091 | local file="$1" |
1245 | 296 | name_val "Built On" "$(get_var version_compile_os) $(get_var version_compile_machine)" | 1092 | |
1246 | 1093 | name_val Version "$(get_var version "${file}") $(get_var version_comment "${file}")" | ||
1247 | 1094 | name_val "Built On" "$(get_var version_compile_os "${file}") $(get_var version_compile_machine "${file}")" | ||
1248 | 297 | } | 1095 | } |
1249 | 298 | 1096 | ||
1250 | 299 | # Gets the system start and uptime in human readable format. Last restart date | ||
1251 | 300 | # should be in $TMPDIR/percona-toolkit. | ||
1252 | 301 | get_mysql_uptime () { | 1097 | get_mysql_uptime () { |
1256 | 302 | local file=$1 | 1098 | local uptime="$1" |
1257 | 303 | restart="$(cat $file)" | 1099 | local restart="$2" |
1255 | 304 | uptime="$(get_stat Uptime)" | ||
1258 | 305 | uptime="$(secs_to_time ${uptime})" | 1100 | uptime="$(secs_to_time ${uptime})" |
1259 | 306 | echo "${restart} (up ${uptime})" | 1101 | echo "${restart} (up ${uptime})" |
1260 | 307 | } | 1102 | } |
1261 | 308 | 1103 | ||
1262 | 309 | # Summarizes the output of SHOW MASTER LOGS, which is in $TMPDIR/percona-toolkit | ||
1263 | 310 | summarize_binlogs () { | 1104 | summarize_binlogs () { |
1268 | 311 | local file=$1 | 1105 | local file="$1" |
1269 | 312 | name_val "Binlogs" $(wc -l $file) | 1106 | |
1270 | 313 | name_val "Zero-Sized" $($AP_GREP -c '\<0$' $file) | 1107 | [ -e "$file" ] || return |
1271 | 314 | size=$($AP_AWK '{t += $2} END{printf "%0.f\n", t}' $file) | 1108 | |
1272 | 1109 | local size="$(awk '{t += $2} END{printf "%0.f\n", t}' "$file")" | ||
1273 | 1110 | name_val "Binlogs" $(wc -l "$file") | ||
1274 | 1111 | name_val "Zero-Sized" $(grep -c '\<0$' "$file") | ||
1275 | 315 | name_val "Total Size" $(shorten ${size} 1) | 1112 | name_val "Total Size" $(shorten ${size} 1) |
1276 | 316 | } | 1113 | } |
1277 | 317 | 1114 | ||
1279 | 318 | # Print out binlog_do_db and binlog_ignore_db | 1115 | format_users () { |
1280 | 1116 | local file="$1" | ||
1281 | 1117 | [ -e "$file" ] || return | ||
1282 | 1118 | awk '{printf "%d users, %d anon, %d w/o pw, %d old pw\n", $1, $2, $3, $4}' "${file}" | ||
1283 | 1119 | } | ||
1284 | 1120 | |||
1285 | 319 | format_binlog_filters () { | 1121 | format_binlog_filters () { |
1289 | 320 | local file=$1 | 1122 | local file="$1" |
1290 | 321 | name_val "binlog_do_db" $(cut -f3 $file) | 1123 | [ -e "$file" ] || return |
1291 | 322 | name_val "binlog_ignore_db" $(cut -f4 $file) | 1124 | name_val "binlog_do_db" "$(cut -f3 "$file")" |
1292 | 1125 | name_val "binlog_ignore_db" "$(cut -f4 "$file")" | ||
1293 | 323 | } | 1126 | } |
1294 | 324 | 1127 | ||
1295 | 325 | # Takes as input a file that has two samples of SHOW STATUS, columnized next to | ||
1296 | 326 | # each other. These should be in $TMPDIR/percona-toolkit. Outputs fuzzy-ed numbers: | ||
1297 | 327 | # absolute, all-time per second, and per-second over the interval between the | ||
1298 | 328 | # samples. Omits any rows that are all zeroes. | ||
1299 | 329 | format_status_variables () { | 1128 | format_status_variables () { |
1305 | 330 | local file=$1 | 1129 | local file="$1" |
1306 | 331 | # First, figure out the intervals. | 1130 | [ -e "$file" ] || return |
1307 | 332 | utime1=$($AP_AWK '/Uptime /{print $2}' $file); | 1131 | |
1308 | 333 | utime2=$($AP_AWK '/Uptime /{print $3}' $file); | 1132 | utime1="$(awk '/Uptime /{print $2}' "$file")"; |
1309 | 334 | ${AP_AWK} " | 1133 | utime2="$(awk '/Uptime /{print $3}' "$file")"; |
1310 | 1134 | awk " | ||
1311 | 335 | BEGIN { | 1135 | BEGIN { |
1312 | 336 | utime1 = ${utime1}; | 1136 | utime1 = ${utime1}; |
1313 | 337 | utime2 = ${utime2}; | 1137 | utime2 = ${utime2}; |
1314 | @@ -367,28 +1167,22 @@ | |||
1315 | 367 | printf(format, \$1, perday, persec, nowsec); | 1167 | printf(format, \$1, perday, persec, nowsec); |
1316 | 368 | } | 1168 | } |
1317 | 369 | } | 1169 | } |
1319 | 370 | }" $file | 1170 | }" "$file" |
1320 | 371 | } | 1171 | } |
1321 | 372 | 1172 | ||
1322 | 373 | # Slices the processlist a bunch of different ways. The processlist should be | ||
1323 | 374 | # created with the \G flag so it's vertical. | ||
1324 | 375 | # The parsing is a bit awkward because different | ||
1325 | 376 | # versions of awk have limitations like "too many fields on line xyz". So we | ||
1326 | 377 | # use 'cut' to shorten the lines. We count all things into temporary variables | ||
1327 | 378 | # for each process in the processlist, and when we hit the Info: line which | ||
1328 | 379 | # ought to be the last line in the process, we decide what to do with the temp | ||
1329 | 380 | # variables. If we're summarizing Command, we count everything; otherwise, only | ||
1330 | 381 | # non-Sleep processes get counted towards the sum and max of Time. | ||
1331 | 382 | summarize_processlist () { | 1173 | summarize_processlist () { |
1333 | 383 | local file=$1 | 1174 | local file="$1" |
1334 | 1175 | |||
1335 | 1176 | [ -e "$file" ] || return | ||
1336 | 1177 | |||
1337 | 384 | for param in Command User Host db State; do | 1178 | for param in Command User Host db State; do |
1338 | 385 | echo | 1179 | echo |
1339 | 386 | printf ' %-30s %8s %7s %9s %9s\n' \ | 1180 | printf ' %-30s %8s %7s %9s %9s\n' \ |
1340 | 387 | "${param}" "COUNT(*)" Working "SUM(Time)" "MAX(Time)" | 1181 | "${param}" "COUNT(*)" Working "SUM(Time)" "MAX(Time)" |
1341 | 388 | echo " ------------------------------" \ | 1182 | echo " ------------------------------" \ |
1342 | 389 | "-------- ------- --------- ---------" | 1183 | "-------- ------- --------- ---------" |
1345 | 390 | cut -c1-80 $file \ | 1184 | cut -c1-80 "$file" \ |
1346 | 391 | | $AP_AWK " | 1185 | | awk " |
1347 | 392 | \$1 == \"${param}:\" { | 1186 | \$1 == \"${param}:\" { |
1348 | 393 | p = substr(\$0, index(\$0, \":\") + 2); | 1187 | p = substr(\$0, index(\$0, \":\") + 2); |
1349 | 394 | if ( index(p, \":\") > 0 ) { | 1188 | if ( index(p, \":\") > 0 ) { |
1350 | @@ -428,22 +1222,21 @@ | |||
1351 | 428 | echo | 1222 | echo |
1352 | 429 | } | 1223 | } |
1353 | 430 | 1224 | ||
1354 | 431 | # Pretty-prints the my.cnf file, which should be in $TMPDIR/percona-toolkit. It's super | ||
1355 | 432 | # annoying, but some *modern* versions of awk don't support POSIX character | ||
1356 | 433 | # sets in regular expressions, like [[:space:]] (looking at you, Debian). So | ||
1357 | 434 | # the below patterns contain [<space><tab>] and must remain that way. | ||
1358 | 435 | pretty_print_cnf_file () { | 1225 | pretty_print_cnf_file () { |
1361 | 436 | local file=$1 | 1226 | local file="$1" |
1362 | 437 | $AP_AWK ' | 1227 | |
1363 | 1228 | [ -e "$file" ] || return | ||
1364 | 1229 | |||
1365 | 1230 | awk ' | ||
1366 | 438 | BEGIN { | 1231 | BEGIN { |
1367 | 439 | FS="=" | 1232 | FS="=" |
1368 | 440 | } | 1233 | } |
1375 | 441 | /^ *[a-zA-Z[]/ { | 1234 | /^[ \t]*[a-zA-Z[]/ { |
1376 | 442 | if ($2) { | 1235 | if (length($2)) { |
1377 | 443 | gsub(/^[ ]*/, "", $1); | 1236 | gsub(/^[ \t]*/, "", $1); |
1378 | 444 | gsub(/^[ ]*/, "", $2); | 1237 | gsub(/^[ \t]*/, "", $2); |
1379 | 445 | gsub(/[ ]*$/, "", $1); | 1238 | gsub(/[ \t]*$/, "", $1); |
1380 | 446 | gsub(/[ ]*$/, "", $2); | 1239 | gsub(/[ \t]*$/, "", $2); |
1381 | 447 | printf("%-35s = %s\n", $1, $2); | 1240 | printf("%-35s = %s\n", $1, $2); |
1382 | 448 | } | 1241 | } |
1383 | 449 | else if ( $0 ~ /\[/ ) { | 1242 | else if ( $0 ~ /\[/ ) { |
1384 | @@ -453,11 +1246,12 @@ | |||
1385 | 453 | else { | 1246 | else { |
1386 | 454 | print $1; | 1247 | print $1; |
1387 | 455 | } | 1248 | } |
1389 | 456 | }' $file | 1249 | }' "$file" |
1390 | 457 | } | 1250 | } |
1391 | 458 | 1251 | ||
1392 | 459 | find_checkpoint_age() { | 1252 | find_checkpoint_age() { |
1394 | 460 | $AP_AWK ' | 1253 | local file="$1" |
1395 | 1254 | awk ' | ||
1396 | 461 | /Log sequence number/{ | 1255 | /Log sequence number/{ |
1397 | 462 | if ( $5 ) { | 1256 | if ( $5 ) { |
1398 | 463 | lsn = $5 + ($4 * 4294967296); | 1257 | lsn = $5 + ($4 * 4294967296); |
1399 | @@ -474,11 +1268,15 @@ | |||
1400 | 474 | print lsn - $4; | 1268 | print lsn - $4; |
1401 | 475 | } | 1269 | } |
1402 | 476 | } | 1270 | } |
1404 | 477 | ' "$@" | 1271 | ' "$file" |
1405 | 478 | } | 1272 | } |
1406 | 479 | 1273 | ||
1407 | 480 | find_pending_io_reads() { | 1274 | find_pending_io_reads() { |
1409 | 481 | $AP_AWK ' | 1275 | local file="$1" |
1410 | 1276 | |||
1411 | 1277 | [ -e "$file" ] || return | ||
1412 | 1278 | |||
1413 | 1279 | awk ' | ||
1414 | 482 | /Pending normal aio reads/ { | 1280 | /Pending normal aio reads/ { |
1415 | 483 | normal_aio_reads = substr($5, 1, index($5, ",")); | 1281 | normal_aio_reads = substr($5, 1, index($5, ",")); |
1416 | 484 | } | 1282 | } |
1417 | @@ -495,11 +1293,15 @@ | |||
1418 | 495 | printf "%d buf pool reads, %d normal AIO", reads, normal_aio_reads; | 1293 | printf "%d buf pool reads, %d normal AIO", reads, normal_aio_reads; |
1419 | 496 | printf ", %d ibuf AIO, %d preads", ibuf_aio_reads, preads; | 1294 | printf ", %d ibuf AIO, %d preads", ibuf_aio_reads, preads; |
1420 | 497 | } | 1295 | } |
1422 | 498 | ' "${1}" | 1296 | ' "${file}" |
1423 | 499 | } | 1297 | } |
1424 | 500 | 1298 | ||
1425 | 501 | find_pending_io_writes() { | 1299 | find_pending_io_writes() { |
1427 | 502 | $AP_AWK ' | 1300 | local file="$1" |
1428 | 1301 | |||
1429 | 1302 | [ -e "$file" ] || return | ||
1430 | 1303 | |||
1431 | 1304 | awk ' | ||
1432 | 503 | /aio writes/ { | 1305 | /aio writes/ { |
1433 | 504 | aio_writes = substr($NF, 1, index($NF, ",")); | 1306 | aio_writes = substr($NF, 1, index($NF, ",")); |
1434 | 505 | } | 1307 | } |
1435 | @@ -522,11 +1324,15 @@ | |||
1436 | 522 | END { | 1324 | END { |
1437 | 523 | printf "%d buf pool (%d LRU, %d flush list, %d page); %d AIO, %d sync, %d log IO (%d log, %d chkp); %d pwrites", lru + flush_list + single_page, lru, flush_list, single_page, aio_writes, sync_ios, log_ios, log_writes, chkp_writes, pwrites; | 1325 | printf "%d buf pool (%d LRU, %d flush list, %d page); %d AIO, %d sync, %d log IO (%d log, %d chkp); %d pwrites", lru + flush_list + single_page, lru, flush_list, single_page, aio_writes, sync_ios, log_ios, log_writes, chkp_writes, pwrites; |
1438 | 524 | } | 1326 | } |
1440 | 525 | ' "${1}" | 1327 | ' "${file}" |
1441 | 526 | } | 1328 | } |
1442 | 527 | 1329 | ||
1443 | 528 | find_pending_io_flushes() { | 1330 | find_pending_io_flushes() { |
1445 | 529 | $AP_AWK ' | 1331 | local file="$1" |
1446 | 1332 | |||
1447 | 1333 | [ -e "$file" ] || return | ||
1448 | 1334 | |||
1449 | 1335 | awk ' | ||
1450 | 530 | /Pending flushes/ { | 1336 | /Pending flushes/ { |
1451 | 531 | log_flushes = substr($5, 1, index($5, ";")); | 1337 | log_flushes = substr($5, 1, index($5, ";")); |
1452 | 532 | buf_pool = $NF; | 1338 | buf_pool = $NF; |
1453 | @@ -534,13 +1340,17 @@ | |||
1454 | 534 | END { | 1340 | END { |
1455 | 535 | printf "%d buf pool, %d log", buf_pool, log_flushes; | 1341 | printf "%d buf pool, %d log", buf_pool, log_flushes; |
1456 | 536 | } | 1342 | } |
1458 | 537 | ' "${1}" | 1343 | ' "${file}" |
1459 | 538 | } | 1344 | } |
1460 | 539 | 1345 | ||
1461 | 540 | summarize_undo_log_entries() { | 1346 | summarize_undo_log_entries() { |
1465 | 541 | $AP_GREP 'undo log entries' "$1" \ | 1347 | local file="$1" |
1466 | 542 | | $AP_SED -e 's/^.*undo log entries \([0-9]*\)/\1/' \ | 1348 | |
1467 | 543 | | $AP_AWK ' | 1349 | [ -e "$file" ] || return |
1468 | 1350 | |||
1469 | 1351 | grep 'undo log entries' "${file}" \ | ||
1470 | 1352 | | sed -e 's/^.*undo log entries \([0-9]*\)/\1/' \ | ||
1471 | 1353 | | awk ' | ||
1472 | 544 | { | 1354 | { |
1473 | 545 | count++; | 1355 | count++; |
1474 | 546 | sum += $1; | 1356 | sum += $1; |
1475 | @@ -554,7 +1364,11 @@ | |||
1476 | 554 | } | 1364 | } |
1477 | 555 | 1365 | ||
1478 | 556 | find_max_trx_time() { | 1366 | find_max_trx_time() { |
1480 | 557 | $AP_AWK ' | 1367 | local file="$1" |
1481 | 1368 | |||
1482 | 1369 | [ -e "$file" ] || return | ||
1483 | 1370 | |||
1484 | 1371 | awk ' | ||
1485 | 558 | BEGIN { | 1372 | BEGIN { |
1486 | 559 | max = 0; | 1373 | max = 0; |
1487 | 560 | } | 1374 | } |
1488 | @@ -570,59 +1384,69 @@ | |||
1489 | 570 | } | 1384 | } |
1490 | 571 | END { | 1385 | END { |
1491 | 572 | print max; | 1386 | print max; |
1496 | 573 | }' "$@" | 1387 | }' "${file}" |
1497 | 574 | } | 1388 | } |
1498 | 575 | 1389 | ||
1499 | 576 | # Summarizes various things about InnoDB status that are not easy to see by eye. | 1390 | find_transation_states () { |
1500 | 1391 | local file="$1" | ||
1501 | 1392 | local tmpfile="$TMPDIR/find_transation_states.tmp" | ||
1502 | 1393 | |||
1503 | 1394 | [ -e "$file" ] || return | ||
1504 | 1395 | |||
1505 | 1396 | awk -F, '/^---TRANSACTION/{print $2}' "${file}" \ | ||
1506 | 1397 | | sed -e 's/ [0-9]* sec.*//' \ | ||
1507 | 1398 | | sort \ | ||
1508 | 1399 | | uniq -c > "${tmpfile}" | ||
1509 | 1400 | group_concat "${tmpfile}" | ||
1510 | 1401 | } | ||
1511 | 1402 | |||
1512 | 577 | format_innodb_status () { | 1403 | format_innodb_status () { |
1513 | 578 | local file=$1 | 1404 | local file=$1 |
1515 | 579 | name_val "Checkpoint Age" $(shorten $(find_checkpoint_age "${file}")) | 1405 | |
1516 | 1406 | [ -e "$file" ] || return | ||
1517 | 1407 | |||
1518 | 1408 | name_val "Checkpoint Age" "$(shorten $(find_checkpoint_age "${file}") 0)" | ||
1519 | 580 | name_val "InnoDB Queue" "$(awk '/queries inside/{print}' "${file}")" | 1409 | name_val "InnoDB Queue" "$(awk '/queries inside/{print}' "${file}")" |
1520 | 581 | name_val "Oldest Transaction" "$(find_max_trx_time "${file}") Seconds"; | 1410 | name_val "Oldest Transaction" "$(find_max_trx_time "${file}") Seconds"; |
1523 | 582 | name_val "History List Len" $(awk '/History list length/{print $4}' "${file}") | 1411 | name_val "History List Len" "$(awk '/History list length/{print $4}' "${file}")" |
1524 | 583 | name_val "Read Views" $(awk '/read views open inside/{print $1}' "${file}") | 1412 | name_val "Read Views" "$(awk '/read views open inside/{print $1}' "${file}")" |
1525 | 584 | name_val "Undo Log Entries" "$(summarize_undo_log_entries "${file}")" | 1413 | name_val "Undo Log Entries" "$(summarize_undo_log_entries "${file}")" |
1526 | 585 | name_val "Pending I/O Reads" "$(find_pending_io_reads "${file}")" | 1414 | name_val "Pending I/O Reads" "$(find_pending_io_reads "${file}")" |
1527 | 586 | name_val "Pending I/O Writes" "$(find_pending_io_writes "${file}")" | 1415 | name_val "Pending I/O Writes" "$(find_pending_io_writes "${file}")" |
1528 | 587 | name_val "Pending I/O Flushes" "$(find_pending_io_flushes "${file}")" | 1416 | name_val "Pending I/O Flushes" "$(find_pending_io_flushes "${file}")" |
1533 | 588 | $AP_AWK -F, '/^---TRANSACTION/{print $2}' "${file}" \ | 1417 | name_val "Transaction States" "$(find_transation_states "${file}" )" |
1534 | 589 | | $AP_SED -e 's/ [0-9]* sec.*//' | sort | uniq -c > $TMPDIR/percona-toolkit2 | 1418 | if grep 'TABLE LOCK table' "${file}" >/dev/null ; then |
1531 | 590 | name_val "Transaction States" "$(group_concat $TMPDIR/percona-toolkit2)" | ||
1532 | 591 | if $AP_GREP 'TABLE LOCK table' "${file}" >/dev/null ; then | ||
1535 | 592 | echo "Tables Locked" | 1419 | echo "Tables Locked" |
1537 | 593 | $AP_AWK '/^TABLE LOCK table/{print $4}' "${file}" \ | 1420 | awk '/^TABLE LOCK table/{print $4}' "${file}" \ |
1538 | 594 | | sort | uniq -c | sort -rn | 1421 | | sort | uniq -c | sort -rn |
1539 | 595 | fi | 1422 | fi |
1541 | 596 | if $AP_GREP 'has waited at' "${file}" > /dev/null ; then | 1423 | if grep 'has waited at' "${file}" > /dev/null ; then |
1542 | 597 | echo "Semaphore Waits" | 1424 | echo "Semaphore Waits" |
1544 | 598 | $AP_GREP 'has waited at' "${file}" | cut -d' ' -f6-8 \ | 1425 | grep 'has waited at' "${file}" | cut -d' ' -f6-8 \ |
1545 | 599 | | sort | uniq -c | sort -rn | 1426 | | sort | uniq -c | sort -rn |
1546 | 600 | fi | 1427 | fi |
1548 | 601 | if $AP_GREP 'reserved it in mode' "${file}" > /dev/null; then | 1428 | if grep 'reserved it in mode' "${file}" > /dev/null; then |
1549 | 602 | echo "Semaphore Holders" | 1429 | echo "Semaphore Holders" |
1551 | 603 | $AP_AWK '/has reserved it in mode/{ | 1430 | awk '/has reserved it in mode/{ |
1552 | 604 | print substr($0, 1 + index($0, "("), index($0, ")") - index($0, "(") - 1); | 1431 | print substr($0, 1 + index($0, "("), index($0, ")") - index($0, "(") - 1); |
1553 | 605 | }' "${file}" | sort | uniq -c | sort -rn | 1432 | }' "${file}" | sort | uniq -c | sort -rn |
1554 | 606 | fi | 1433 | fi |
1556 | 607 | if $AP_GREP -e 'Mutex at' -e 'lock on' "${file}" >/dev/null 2>&1; then | 1434 | if grep -e 'Mutex at' -e 'lock on' "${file}" >/dev/null 2>&1; then |
1557 | 608 | echo "Mutexes/Locks Waited For" | 1435 | echo "Mutexes/Locks Waited For" |
1559 | 609 | $AP_GREP -e 'Mutex at' -e 'lock on' "${file}" | $AP_SED -e 's/^[XS]-//' -e 's/,.*$//' \ | 1436 | grep -e 'Mutex at' -e 'lock on' "${file}" | sed -e 's/^[XS]-//' -e 's/,.*$//' \ |
1560 | 610 | | sort | uniq -c | sort -rn | 1437 | | sort | uniq -c | sort -rn |
1561 | 611 | fi | 1438 | fi |
1562 | 612 | } | 1439 | } |
1563 | 613 | 1440 | ||
1564 | 614 | # Summarizes per-database statistics for a bunch of different things: count of | ||
1565 | 615 | # tables, views, etc. $1 is the file name. $2 is the database name; if none, | ||
1566 | 616 | # then there should be multiple databases. | ||
1567 | 617 | format_overall_db_stats () { | 1441 | format_overall_db_stats () { |
1569 | 618 | local file=$1 | 1442 | local file="$1" |
1570 | 1443 | local tmpfile="$TMPDIR/format_overall_db_stats.tmp" | ||
1571 | 1444 | |||
1572 | 1445 | [ -e "$file" ] || return | ||
1573 | 1446 | |||
1574 | 619 | echo | 1447 | echo |
1579 | 620 | # We keep counts of everything in an associative array keyed by db name, and | 1448 | awk ' |
1576 | 621 | # what it is. The num_dbs counter is to ensure sort order is consistent when | ||
1577 | 622 | # we run the awk commands following this one. | ||
1578 | 623 | $AP_AWK ' | ||
1580 | 624 | BEGIN { | 1449 | BEGIN { |
1581 | 625 | # In case there is no USE statement in the file. | ||
1582 | 626 | db = "{chosen}"; | 1450 | db = "{chosen}"; |
1583 | 627 | num_dbs = 0; | 1451 | num_dbs = 0; |
1584 | 628 | } | 1452 | } |
1585 | @@ -634,7 +1458,6 @@ | |||
1586 | 634 | } | 1458 | } |
1587 | 635 | } | 1459 | } |
1588 | 636 | /^CREATE TABLE/ { | 1460 | /^CREATE TABLE/ { |
1589 | 637 | # Handle single-DB dumps, where there is no USE statement. | ||
1590 | 638 | if (num_dbs == 0) { | 1461 | if (num_dbs == 0) { |
1591 | 639 | num_dbs = 1; | 1462 | num_dbs = 1; |
1592 | 640 | db_seen[db] = 1; | 1463 | db_seen[db] = 1; |
1593 | @@ -674,15 +1497,13 @@ | |||
1594 | 674 | printf fmt, db, counts[db ",tables"], counts[db ",views"], counts[db ",sps"], counts[db ",trg"], counts[db ",func"], counts[db ",fk"], counts[db ",partn"]; | 1497 | printf fmt, db, counts[db ",tables"], counts[db ",views"], counts[db ",sps"], counts[db ",trg"], counts[db ",func"], counts[db ",fk"], counts[db ",partn"]; |
1595 | 675 | } | 1498 | } |
1596 | 676 | } | 1499 | } |
1600 | 677 | ' $file > $TMPDIR/percona-toolkit | 1500 | ' "$file" > "$tmpfile" |
1601 | 678 | head -n2 $TMPDIR/percona-toolkit | 1501 | head -n2 "$tmpfile" |
1602 | 679 | tail -n +3 $TMPDIR/percona-toolkit | sort | 1502 | tail -n +3 "$tmpfile" | sort |
1603 | 680 | 1503 | ||
1604 | 681 | echo | 1504 | echo |
1607 | 682 | # Now do the summary of engines per DB | 1505 | awk ' |
1606 | 683 | $AP_AWK ' | ||
1608 | 684 | BEGIN { | 1506 | BEGIN { |
1609 | 685 | # In case there is no USE statement in the file. | ||
1610 | 686 | db = "{chosen}"; | 1507 | db = "{chosen}"; |
1611 | 687 | num_dbs = 0; | 1508 | num_dbs = 0; |
1612 | 688 | num_engines = 0; | 1509 | num_engines = 0; |
1613 | @@ -695,7 +1516,6 @@ | |||
1614 | 695 | } | 1516 | } |
1615 | 696 | } | 1517 | } |
1616 | 697 | /^\) ENGINE=/ { | 1518 | /^\) ENGINE=/ { |
1617 | 698 | # Handle single-DB dumps, where there is no USE statement. | ||
1618 | 699 | if (num_dbs == 0) { | 1519 | if (num_dbs == 0) { |
1619 | 700 | num_dbs = 1; | 1520 | num_dbs = 1; |
1620 | 701 | db_seen[db] = 1; | 1521 | db_seen[db] = 1; |
1621 | @@ -734,16 +1554,13 @@ | |||
1622 | 734 | print ""; | 1554 | print ""; |
1623 | 735 | } | 1555 | } |
1624 | 736 | } | 1556 | } |
1628 | 737 | ' $file > $TMPDIR/percona-toolkit | 1557 | ' "$file" > "$tmpfile" |
1629 | 738 | head -n1 $TMPDIR/percona-toolkit | 1558 | head -n1 "$tmpfile" |
1630 | 739 | tail -n +2 $TMPDIR/percona-toolkit | sort | 1559 | tail -n +2 "$tmpfile" | sort |
1631 | 740 | 1560 | ||
1632 | 741 | echo | 1561 | echo |
1636 | 742 | # Now do the summary of index types per DB. Careful -- index is a reserved | 1562 | awk ' |
1634 | 743 | # word in awk. | ||
1635 | 744 | $AP_AWK ' | ||
1637 | 745 | BEGIN { | 1563 | BEGIN { |
1638 | 746 | # In case there is no USE statement in the file. | ||
1639 | 747 | db = "{chosen}"; | 1564 | db = "{chosen}"; |
1640 | 748 | num_dbs = 0; | 1565 | num_dbs = 0; |
1641 | 749 | num_idxes = 0; | 1566 | num_idxes = 0; |
1642 | @@ -756,7 +1573,6 @@ | |||
1643 | 756 | } | 1573 | } |
1644 | 757 | } | 1574 | } |
1645 | 758 | /KEY/ { | 1575 | /KEY/ { |
1646 | 759 | # Handle single-DB dumps, where there is no USE statement. | ||
1647 | 760 | if (num_dbs == 0) { | 1576 | if (num_dbs == 0) { |
1648 | 761 | num_dbs = 1; | 1577 | num_dbs = 1; |
1649 | 762 | db_seen[db] = 1; | 1578 | db_seen[db] = 1; |
1650 | @@ -807,15 +1623,13 @@ | |||
1651 | 807 | print ""; | 1623 | print ""; |
1652 | 808 | } | 1624 | } |
1653 | 809 | } | 1625 | } |
1657 | 810 | ' $file > $TMPDIR/percona-toolkit | 1626 | ' "$file" > "$tmpfile" |
1658 | 811 | head -n1 $TMPDIR/percona-toolkit | 1627 | head -n1 "$tmpfile" |
1659 | 812 | tail -n +2 $TMPDIR/percona-toolkit | sort | 1628 | tail -n +2 "$tmpfile" | sort |
1660 | 813 | 1629 | ||
1661 | 814 | echo | 1630 | echo |
1664 | 815 | # Now do the summary of datatypes per DB | 1631 | awk ' |
1663 | 816 | $AP_AWK ' | ||
1665 | 817 | BEGIN { | 1632 | BEGIN { |
1666 | 818 | # In case there is no USE statement in the file. | ||
1667 | 819 | db = "{chosen}"; | 1633 | db = "{chosen}"; |
1668 | 820 | num_dbs = 0; | 1634 | num_dbs = 0; |
1669 | 821 | num_types = 0; | 1635 | num_types = 0; |
1670 | @@ -828,7 +1642,6 @@ | |||
1671 | 828 | } | 1642 | } |
1672 | 829 | } | 1643 | } |
1673 | 830 | /^ `/ { | 1644 | /^ `/ { |
1674 | 831 | # Handle single-DB dumps, where there is no USE statement. | ||
1675 | 832 | if (num_dbs == 0) { | 1645 | if (num_dbs == 0) { |
1676 | 833 | num_dbs = 1; | 1646 | num_dbs = 1; |
1677 | 834 | db_seen[db] = 1; | 1647 | db_seen[db] = 1; |
1678 | @@ -898,106 +1711,195 @@ | |||
1679 | 898 | print ""; | 1711 | print ""; |
1680 | 899 | } | 1712 | } |
1681 | 900 | } | 1713 | } |
1686 | 901 | ' $file > $TMPDIR/percona-toolkit | 1714 | ' "$file" > "$tmpfile" |
1687 | 902 | hdr=$($AP_GREP -n Database $TMPDIR/percona-toolkit | cut -d: -f1); | 1715 | local hdr=$(grep -n Database "$tmpfile" | cut -d: -f1); |
1688 | 903 | head -n${hdr} $TMPDIR/percona-toolkit | 1716 | head -n${hdr} "$tmpfile" |
1689 | 904 | tail -n +$((${hdr} + 1)) $TMPDIR/percona-toolkit | sort | 1717 | tail -n +$((${hdr} + 1)) "$tmpfile" | sort |
1690 | 905 | echo | 1718 | echo |
1691 | 906 | } | 1719 | } |
1692 | 907 | 1720 | ||
1786 | 908 | # ############################################################################## | 1721 | section_percona_server_features () { |
1787 | 909 | # The main() function is called at the end of the script. This makes it | 1722 | local file="$1" |
1788 | 910 | # testable. Major bits of parsing are separated into functions for testability. | 1723 | |
1789 | 911 | # ############################################################################## | 1724 | [ -e "$file" ] || return |
1790 | 912 | main() { | 1725 | |
1791 | 913 | 1726 | name_val "Table & Index Stats" \ | |
1792 | 914 | # Begin by setting the $PATH to include some common locations that are not | 1727 | "$(feat_on "$file" userstat_running)" |
1793 | 915 | # always in the $PATH, including the "sbin" locations. On SunOS systems, | 1728 | name_val "Multiple I/O Threads" \ |
1794 | 916 | # prefix the path with the location of more sophisticated utilities. | 1729 | "$(feat_on "$file" innodb_read_io_threads gt 1)" |
1795 | 917 | export PATH="${PATH}:/usr/local/bin:/usr/bin:/bin:/usr/libexec" | 1730 | name_val "Corruption Resilient" \ |
1796 | 918 | export PATH="${PATH}:/usr/mysql/bin/:/usr/local/sbin:/usr/sbin:/sbin" | 1731 | "$(feat_on "$file" innodb_pass_corrupt_table)" |
1797 | 919 | export PATH="/usr/gnu/bin/:/usr/xpg4/bin/:${PATH}" | 1732 | name_val "Durable Replication" \ |
1798 | 920 | 1733 | "$(feat_on "$file" innodb_overwrite_relay_log_info)" | |
1799 | 921 | # Set up temporary files. | 1734 | name_val "Import InnoDB Tables" \ |
1800 | 922 | mk_tmpdir | 1735 | "$(feat_on "$file" innodb_expand_import)" |
1801 | 923 | temp_files "rm" | 1736 | name_val "Fast Server Restarts" \ |
1802 | 924 | temp_files "touch" | 1737 | "$(feat_on "$file" innodb_auto_lru_dump)" |
1803 | 925 | 1738 | name_val "Enhanced Logging" \ | |
1804 | 926 | # ######################################################################## | 1739 | "$(feat_on "$file" log_slow_verbosity ne microtime)" |
1805 | 927 | # Header for the whole thing, table of discovered instances | 1740 | name_val "Replica Perf Logging" \ |
1806 | 928 | # ######################################################################## | 1741 | "$(feat_on "$file" log_slow_slave_statements)" |
1807 | 929 | section Percona_Toolkit_MySQL_Summary_Report | 1742 | name_val "Response Time Hist." \ |
1808 | 930 | name_val "System time" "`date -u +'%F %T UTC'` (local TZ: `date +'%Z %z'`)" | 1743 | "$(feat_on "$file" enable_query_response_time_stats)" |
1809 | 931 | section Instances | 1744 | name_val "Smooth Flushing" \ |
1810 | 932 | ps auxww 2>/dev/null | $AP_GREP mysqld > $TMPDIR/percona-toolkit | 1745 | "$(feat_on "$file" innodb_adaptive_checkpoint ne none)" |
1811 | 933 | parse_mysqld_instances $TMPDIR/percona-toolkit | 1746 | name_val "HandlerSocket NoSQL" \ |
1812 | 934 | 1747 | "$(feat_on "$file" handlersocket_port)" | |
1813 | 935 | # ######################################################################## | 1748 | name_val "Fast Hash UDFs" \ |
1814 | 936 | # Fetch some basic info so we can start | 1749 | "$(get_var "pt-summary-internal-FNV_64" "$file")" |
1815 | 937 | # ######################################################################## | 1750 | } |
1816 | 938 | mysql "$@" -ss -e 'SELECT CURRENT_USER()' > $TMPDIR/percona-toolkit | 1751 | |
1817 | 939 | if [ "$?" != "0" ]; then | 1752 | section_myisam () { |
1818 | 940 | echo "Cannot connect to mysql, please specify command-line options." | 1753 | local variables_file="$1" |
1819 | 941 | temp_files "rm" | 1754 | local status_file="$2" |
1820 | 942 | rm_tmpdir | 1755 | |
1821 | 943 | exit 1 | 1756 | [ -e "$variables_file" -a -e "$status_file" ] || return |
1822 | 944 | fi | 1757 | |
1823 | 945 | user="$(cat $TMPDIR/percona-toolkit)"; | 1758 | local buf_size="$(get_var key_buffer_size "$variables_file")" |
1824 | 946 | mysql "$@" -ss -e 'SHOW /*!40100 GLOBAL*/ VARIABLES' > $TMPDIR/percona-toolkit-mysql-variables | 1759 | local blk_size="$(get_var key_cache_block_size "$variables_file")" |
1825 | 947 | mysql "$@" -ss -e 'SHOW /*!50000 GLOBAL*/ STATUS' > $TMPDIR/percona-toolkit-mysql-status | 1760 | local blk_unus="$(get_var Key_blocks_unused "$status_file")" |
1826 | 948 | mysql "$@" -ss -e 'SHOW DATABASES' > $TMPDIR/percona-toolkit-mysql-databases 2>/dev/null | 1761 | local blk_unfl="$(get_var Key_blocks_not_flushed "$variables_file")" |
1827 | 949 | mysql "$@" -ssE -e 'SHOW SLAVE STATUS' > $TMPDIR/percona-toolkit-mysql-slave 2>/dev/null | 1762 | local unus=$((${blk_unus:-0} * ${blk_size:-0})) |
1828 | 950 | mysql "$@" -ssE -e 'SHOW /*!50000 ENGINE*/ INNODB STATUS' > $TMPDIR/percona-toolkit-innodb-status 2>/dev/null | 1763 | local unfl=$((${blk_unfl:-0} * ${blk_size:-0})) |
1829 | 951 | mysql "$@" -ssE -e 'SHOW FULL PROCESSLIST' > $TMPDIR/percona-toolkit-mysql-processlist 2>/dev/null | 1764 | local used=$((${buf_size:-0} - ${unus})) |
1830 | 952 | now="$(mysql "$@" -ss -e 'SELECT NOW()')" | 1765 | |
1831 | 953 | port="$(get_var port)" | 1766 | name_val "Key Cache" "$(shorten ${buf_size} 1)" |
1832 | 954 | 1767 | name_val "Pct Used" "$(fuzzy_pct ${used} ${buf_size})" | |
1833 | 955 | # ######################################################################## | 1768 | name_val "Unflushed" "$(fuzzy_pct ${unfl} ${buf_size})" |
1834 | 956 | # General date, hostname, etc | 1769 | } |
1835 | 957 | # ######################################################################## | 1770 | |
1836 | 958 | section "Report_On_Port_${port}" | 1771 | section_innodb () { |
1837 | 959 | name_val User "${user}" | 1772 | local variables_file="$1" |
1838 | 960 | name_val Time "${now} ($(get_mysql_timezone))" | 1773 | local status_file="$2" |
1839 | 961 | name_val Hostname "$(get_var hostname)" | 1774 | |
1840 | 962 | get_mysql_version | 1775 | [ -e "$variables_file" -a -e "$status_file" ] || return |
1841 | 963 | 1776 | ||
1842 | 964 | uptime="$(get_stat Uptime)" | 1777 | local version=$(get_var innodb_version "$variables_file") |
1843 | 965 | mysql "$@" -ss -e "SELECT LEFT(NOW() - INTERVAL ${uptime} SECOND, 16)" \ | 1778 | name_val Version ${version:-default} |
1844 | 966 | > $TMPDIR/percona-toolkit | 1779 | |
1845 | 967 | name_val Started "$(get_mysql_uptime $TMPDIR/percona-toolkit)" | 1780 | local bp_size="$(get_var innodb_buffer_pool_size "$variables_file")" |
1846 | 968 | 1781 | name_val "Buffer Pool Size" "$(shorten "${bp_size:-0}" 1)" | |
1847 | 969 | name_val Databases "$($AP_GREP -c . $TMPDIR/percona-toolkit-mysql-databases)" | 1782 | |
1848 | 970 | name_val Datadir "$(get_var datadir)" | 1783 | local bp_pags="$(get_var Innodb_buffer_pool_pages_total "$status_file")" |
1849 | 971 | procs="$(get_stat Threads_connected)" | 1784 | local bp_free="$(get_var Innodb_buffer_pool_pages_free "$status_file")" |
1850 | 972 | procr="$(get_stat Threads_running)" | 1785 | local bp_dirt="$(get_var Innodb_buffer_pool_pages_dirty "$status_file")" |
1851 | 973 | name_val Processes "$(fuzz ${procs}) connected, $(fuzz ${procr}) running" | 1786 | local bp_fill=$((${bp_pags} - ${bp_free})) |
1852 | 974 | if [ -s $TMPDIR/percona-toolkit-mysql-slave ]; then slave=""; else slave="not "; fi | 1787 | name_val "Buffer Pool Fill" "$(fuzzy_pct ${bp_fill} ${bp_pags})" |
1853 | 975 | slavecount=$($AP_GREP -c 'Binlog Dump' $TMPDIR/percona-toolkit-mysql-processlist) | 1788 | name_val "Buffer Pool Dirty" "$(fuzzy_pct ${bp_dirt} ${bp_pags})" |
1854 | 976 | name_val Replication "Is ${slave}a slave, has ${slavecount} slaves connected" | 1789 | |
1855 | 977 | 1790 | name_val "File Per Table" $(get_var innodb_file_per_table "$variables_file") | |
1856 | 978 | # TODO move this into a section with other files: error log, slow log and | 1791 | name_val "Page Size" $(shorten $(get_var Innodb_page_size "$status_file") 0) |
1857 | 979 | # show the sizes | 1792 | |
1858 | 980 | pid_file="$(get_var pid_file)" | 1793 | local log_size="$(get_var innodb_log_file_size "$variables_file")" |
1859 | 981 | [ -e "${pid_file}" ] && PID_EXISTS="(exists)" | 1794 | local log_file="$(get_var innodb_log_files_in_group "$variables_file")" |
1860 | 982 | name_val Pidfile "${pid_file} ${PID_EXISTS:-(does not exist)}" | 1795 | local log_total=$(awk "BEGIN {printf \"%.2f\n\", ${log_size}*${log_file}}" ) |
1861 | 983 | 1796 | name_val "Log File Size" \ | |
1862 | 984 | # ######################################################################## | 1797 | "${log_file} * $(shorten ${log_size} 1 1000) = $(shorten ${log_total} 1 1000)" |
1863 | 985 | # Processlist, sliced several different ways | 1798 | name_val "Log Buffer Size" \ |
1864 | 986 | # ######################################################################## | 1799 | "$(shorten $(get_var innodb_log_buffer_size "$variables_file") 0)" |
1865 | 987 | section Processlist | 1800 | name_val "Flush Method" \ |
1866 | 988 | summarize_processlist $TMPDIR/percona-toolkit-mysql-processlist | 1801 | "$(get_var innodb_flush_method "$variables_file")" |
1867 | 989 | 1802 | name_val "Flush Log At Commit" \ | |
1868 | 990 | # ######################################################################## | 1803 | "$(get_var innodb_flush_log_at_trx_commit "$variables_file")" |
1869 | 991 | # Queries and query plans | 1804 | name_val "XA Support" \ |
1870 | 992 | # ######################################################################## | 1805 | "$(get_var innodb_support_xa "$variables_file")" |
1871 | 993 | section "Status_Counters_(Wait_10_Seconds)" | 1806 | name_val "Checksums" \ |
1872 | 994 | sleep 10 | 1807 | "$(get_var innodb_checksums "$variables_file")" |
1873 | 995 | # TODO: gather this data in the same format as normal: stats, TS line | 1808 | name_val "Doublewrite" \ |
1874 | 996 | mysql "$@" -ss -e 'SHOW /*!50000 GLOBAL*/ STATUS' \ | 1809 | "$(get_var innodb_doublewrite "$variables_file")" |
1875 | 997 | | join $TMPDIR/percona-toolkit-mysql-status - > $TMPDIR/percona-toolkit | 1810 | name_val "R/W I/O Threads" \ |
1876 | 998 | # Make a file with a list of things we want to omit because they aren't | 1811 | "$(get_var innodb_read_io_threads "$variables_file") $(get_var innodb_write_io_threads "$variables_file")" |
1877 | 999 | # counters, they are gauges (in RRDTool terminology). Gauges are shown | 1812 | name_val "I/O Capacity" \ |
1878 | 1000 | # elsewhere in the output. | 1813 | "$(get_var innodb_io_capacity "$variables_file")" |
1879 | 1814 | name_val "Thread Concurrency" \ | ||
1880 | 1815 | "$(get_var innodb_thread_concurrency "$variables_file")" | ||
1881 | 1816 | name_val "Concurrency Tickets" \ | ||
1882 | 1817 | "$(get_var innodb_concurrency_tickets "$variables_file")" | ||
1883 | 1818 | name_val "Commit Concurrency" \ | ||
1884 | 1819 | "$(get_var innodb_commit_concurrency "$variables_file")" | ||
1885 | 1820 | name_val "Txn Isolation Level" \ | ||
1886 | 1821 | "$(get_var tx_isolation "$variables_file")" | ||
1887 | 1822 | name_val "Adaptive Flushing" \ | ||
1888 | 1823 | "$(get_var innodb_adaptive_flushing "$variables_file")" | ||
1889 | 1824 | name_val "Adaptive Checkpoint" \ | ||
1890 | 1825 | "$(get_var innodb_adaptive_checkpoint "$variables_file")" | ||
1891 | 1826 | } | ||
1892 | 1827 | |||
1893 | 1828 | |||
1894 | 1829 | section_noteworthy_variables () { | ||
1895 | 1830 | local file="$1" | ||
1896 | 1831 | |||
1897 | 1832 | [ -e "$file" ] || return | ||
1898 | 1833 | |||
1899 | 1834 | name_val "Auto-Inc Incr/Offset" "$(get_var auto_increment_increment "$file")/$(get_var auto_increment_offset "$file")" | ||
1900 | 1835 | for v in \ | ||
1901 | 1836 | default_storage_engine flush_time init_connect init_file sql_mode; | ||
1902 | 1837 | do | ||
1903 | 1838 | name_val "${v}" "$(get_var ${v} "$file")" | ||
1904 | 1839 | done | ||
1905 | 1840 | for v in \ | ||
1906 | 1841 | join_buffer_size sort_buffer_size read_buffer_size read_rnd_buffer_size \ | ||
1907 | 1842 | bulk_insert_buffer max_heap_table_size tmp_table_size \ | ||
1908 | 1843 | max_allowed_packet thread_stack; | ||
1909 | 1844 | do | ||
1910 | 1845 | name_val "${v}" "$(shorten $(get_var ${v} "$file") 0)" | ||
1911 | 1846 | done | ||
1912 | 1847 | for v in log log_error log_warnings log_slow_queries \ | ||
1913 | 1848 | log_queries_not_using_indexes log_slave_updates; | ||
1914 | 1849 | do | ||
1915 | 1850 | name_val "${v}" "$(get_var ${v} "$file")" | ||
1916 | 1851 | done | ||
1917 | 1852 | } | ||
1918 | 1853 | |||
1919 | 1854 | _semi_sync_stats_for () { | ||
1920 | 1855 | local target="$1" | ||
1921 | 1856 | local file="$2" | ||
1922 | 1857 | |||
1923 | 1858 | [ -e "$file" ] || return | ||
1924 | 1859 | |||
1925 | 1860 | local semisync_status="$(get_var "Rpl_semi_sync_${target}_status" "${file}" )" | ||
1926 | 1861 | local semisync_trace="$(get_var "rpl_semi_sync_${target}_trace_level" "${file}")" | ||
1927 | 1862 | |||
1928 | 1863 | local trace_extra="" | ||
1929 | 1864 | if [ -n "${semisync_trace}" ]; then | ||
1930 | 1865 | if [ $semisync_trace -eq 1 ]; then | ||
1931 | 1866 | trace_extra="general (for example, time function failures) " | ||
1932 | 1867 | elif [ $semisync_trace -eq 16 ]; then | ||
1933 | 1868 | trace_extra="detail (more verbose information) " | ||
1934 | 1869 | elif [ $semisync_trace -eq 32 ]; then | ||
1935 | 1870 | trace_extra="net wait (more information about network waits)" | ||
1936 | 1871 | elif [ $semisync_trace -eq 64 ]; then | ||
1937 | 1872 | trace_extra="function (information about function entry and exit)" | ||
1938 | 1873 | else | ||
1939 | 1874 | trace_extra="Unknown setting" | ||
1940 | 1875 | fi | ||
1941 | 1876 | fi | ||
1942 | 1877 | |||
1943 | 1878 | name_val "${target} semisync status" "${semisync_status}" | ||
1944 | 1879 | name_val "${target} trace level" "${semisync_trace}, ${trace_extra}" | ||
1945 | 1880 | |||
1946 | 1881 | if [ "${target}" = "master" ]; then | ||
1947 | 1882 | name_val "${target} timeout in milliseconds" \ | ||
1948 | 1883 | "$(get_var "rpl_semi_sync_${target}_timeout" "${file}")" | ||
1949 | 1884 | name_val "${target} waits for slaves" \ | ||
1950 | 1885 | "$(get_var "rpl_semi_sync_${target}_wait_no_slave" "${file}")" | ||
1951 | 1886 | |||
1952 | 1887 | _d "Prepend Rpl_semi_sync_master_ to the following" | ||
1953 | 1888 | for v in \ | ||
1954 | 1889 | clients net_avg_wait_time net_wait_time net_waits \ | ||
1955 | 1890 | no_times no_tx timefunc_failures tx_avg_wait_time \ | ||
1956 | 1891 | tx_wait_time tx_waits wait_pos_backtraverse \ | ||
1957 | 1892 | wait_sessions yes_tx; | ||
1958 | 1893 | do | ||
1959 | 1894 | name_val "${target} ${v}" \ | ||
1960 | 1895 | "$( get_var "Rpl_semi_sync_master_${v}" "${file}" )" | ||
1961 | 1896 | done | ||
1962 | 1897 | fi | ||
1963 | 1898 | } | ||
1964 | 1899 | |||
1965 | 1900 | noncounters_pattern () { | ||
1966 | 1901 | local noncounters_pattern="" | ||
1967 | 1902 | |||
1968 | 1001 | for var in Compression Delayed_insert_threads Innodb_buffer_pool_pages_data \ | 1903 | for var in Compression Delayed_insert_threads Innodb_buffer_pool_pages_data \ |
1969 | 1002 | Innodb_buffer_pool_pages_dirty Innodb_buffer_pool_pages_free \ | 1904 | Innodb_buffer_pool_pages_dirty Innodb_buffer_pool_pages_free \ |
1970 | 1003 | Innodb_buffer_pool_pages_latched Innodb_buffer_pool_pages_misc \ | 1905 | Innodb_buffer_pool_pages_latched Innodb_buffer_pool_pages_misc \ |
1971 | @@ -1018,314 +1920,410 @@ | |||
1972 | 1018 | Threads_cached Threads_connected Threads_running \ | 1920 | Threads_cached Threads_connected Threads_running \ |
1973 | 1019 | Uptime_since_flush_status; | 1921 | Uptime_since_flush_status; |
1974 | 1020 | do | 1922 | do |
1985 | 1021 | echo "${var}" >> $TMPDIR/percona-toolkit-noncounters | 1923 | if [ -z "${noncounters_pattern}" ]; then |
1986 | 1022 | done | 1924 | noncounters_pattern="${var}" |
1987 | 1023 | format_status_variables $TMPDIR/percona-toolkit | $AP_GREP -v -f $TMPDIR/percona-toolkit-noncounters | 1925 | else |
1988 | 1024 | 1926 | noncounters_pattern="${noncounters_pattern}\|${var}" | |
1989 | 1025 | # ######################################################################## | 1927 | fi |
1990 | 1026 | # Table cache | 1928 | done |
1991 | 1027 | # ######################################################################## | 1929 | echo $noncounters_pattern |
1992 | 1028 | section Table_cache | 1930 | } |
1993 | 1029 | if var_exists table_open_cache; then | 1931 | |
1994 | 1030 | table_cache=$(get_var table_open_cache) | 1932 | section_mysqld () { |
1995 | 1933 | local executables_file="$1" | ||
1996 | 1934 | local variables_file="$2" | ||
1997 | 1935 | |||
1998 | 1936 | [ -e "$executables_file" -a -e "$variables_file" ] || return | ||
1999 | 1937 | |||
2000 | 1938 | section "MySQL Executable" | ||
2001 | 1939 | local i=1; | ||
2002 | 1940 | while read executable; do | ||
2003 | 1941 | name_val "Path to executable" "$executable" | ||
2004 | 1942 | name_val "Has symbols" "$( get_var "pt-summary-internal-mysqld_executable_${i}" "$variables_file" )" | ||
2005 | 1943 | i=$(($i + 1)) | ||
2006 | 1944 | done < "$executables_file" | ||
2007 | 1945 | } | ||
2008 | 1946 | |||
2009 | 1947 | section_mysql_files () { | ||
2010 | 1948 | local variables_file="$1" | ||
2011 | 1949 | |||
2012 | 1950 | section "MySQL Files" | ||
2013 | 1951 | for file_name in pid_file slow_query_log_file general_log_file log_error; do | ||
2014 | 1952 | local file="$(get_var "${file_name}" "$variables_file")" | ||
2015 | 1953 | local name_out="$(echo "$file_name" | sed 'y/[a-z]/[A-Z]/')" | ||
2016 | 1954 | if [ -e "${file}" ]; then | ||
2017 | 1955 | name_val "$name_out" "$file" | ||
2018 | 1956 | name_val "${name_out} Size" "$(du "$file" | awk '{print $1}')" | ||
2019 | 1957 | else | ||
2020 | 1958 | name_val "$name_out" "(does not exist)" | ||
2021 | 1959 | fi | ||
2022 | 1960 | done | ||
2023 | 1961 | } | ||
2024 | 1962 | |||
2025 | 1963 | report_mysql_summary () { | ||
2026 | 1964 | local dir="$1" | ||
2027 | 1965 | |||
2028 | 1966 | local NAME_VAL_LEN=25 | ||
2029 | 1967 | |||
2030 | 1968 | |||
2031 | 1969 | section "Percona Toolkit MySQL Summary Report" | ||
2032 | 1970 | name_val "System time" "`date -u +'%F %T UTC'` (local TZ: `date +'%Z %z'`)" | ||
2033 | 1971 | section "Instances" | ||
2034 | 1972 | parse_mysqld_instances "$dir/mysqld-instances" "$dir/mysql-variables" | ||
2035 | 1973 | |||
2036 | 1974 | section_mysqld "$dir/mysqld-executables" "$dir/mysql-variables" | ||
2037 | 1975 | |||
2038 | 1976 | local user="$(get_var "pt-summary-internal-user" "$dir/mysql-variables")" | ||
2039 | 1977 | local port="$(get_var port "$dir/mysql-variables")" | ||
2040 | 1978 | local now="$(get_var "pt-summary-internal-now" "$dir/mysql-variables")" | ||
2041 | 1979 | section "Report On Port ${port}" | ||
2042 | 1980 | name_val User "${user}" | ||
2043 | 1981 | name_val Time "${now} ($(get_mysql_timezone "$dir/mysql-variables"))" | ||
2044 | 1982 | name_val Hostname "$(get_var hostname "$dir/mysql-variables")" | ||
2045 | 1983 | get_mysql_version "$dir/mysql-variables" | ||
2046 | 1984 | |||
2047 | 1985 | local uptime="$(get_var Uptime "$dir/mysql-status")" | ||
2048 | 1986 | local current_time="$(get_var "pt-summary-internal-current_time" "$dir/mysql-variables")" | ||
2049 | 1987 | name_val Started "$(get_mysql_uptime "${uptime}" "${current_time}")" | ||
2050 | 1988 | |||
2051 | 1989 | local num_dbs="$(grep -c . "$dir/mysql-databases")" | ||
2052 | 1990 | name_val Databases "${num_dbs}" | ||
2053 | 1991 | name_val Datadir "$(get_var datadir "$dir/mysql-variables")" | ||
2054 | 1992 | |||
2055 | 1993 | local fuzz_procs=$(fuzz $(get_var Threads_connected "$dir/mysql-status")) | ||
2056 | 1994 | local fuzz_procr=$(fuzz $(get_var Threads_running "$dir/mysql-status")) | ||
2057 | 1995 | name_val Processes "${fuzz_procs} connected, ${fuzz_procr} running" | ||
2058 | 1996 | |||
2059 | 1997 | local slave="" | ||
2060 | 1998 | if [ -s "$dir/mysql-slave" ]; then slave=""; else slave="not "; fi | ||
2061 | 1999 | local slavecount=$(grep -c 'Binlog Dump' "$dir/mysql-processlist") | ||
2062 | 2000 | name_val Replication "Is ${slave}a slave, has ${slavecount} slaves connected" | ||
2063 | 2001 | |||
2064 | 2002 | |||
2065 | 2003 | local pid_file="$(get_var "pid_file" "$dir/mysql-variables")" | ||
2066 | 2004 | local PID_EXISTS="" | ||
2067 | 2005 | if [ "$( get_var "pt-summary-internal-pid_file_exists" "$dir/mysql-variables" )" ]; then | ||
2068 | 2006 | PID_EXISTS="(exists)" | ||
2069 | 1031 | else | 2007 | else |
2071 | 1032 | table_cache=$(get_var table_cache) | 2008 | PID_EXISTS="(does not exist)" |
2072 | 1033 | fi | 2009 | fi |
2102 | 1034 | name_val Size "${table_cache}" | 2010 | name_val Pidfile "${pid_file} ${PID_EXISTS}" |
2103 | 1035 | open_tables=$(get_stat Open_tables) | 2011 | |
2104 | 1036 | name_val Usage "$(fuzzy_pct ${open_tables} ${table_cache})" | 2012 | section "Processlist" |
2105 | 1037 | 2013 | summarize_processlist "$dir/mysql-processlist" | |
2106 | 1038 | # ######################################################################## | 2014 | |
2107 | 1039 | # Percona Server features | 2015 | section "Status Counters (Wait ${OPT_SLEEP} Seconds)" |
2108 | 1040 | # ######################################################################## | 2016 | wait |
2109 | 1041 | section Key_Percona_Server_features | 2017 | local noncounters_pattern="$(noncounters_pattern)" |
2110 | 1042 | name_val "Table & Index Stats" "$(feat_on userstat_running)" | 2018 | format_status_variables "$dir/mysql-status-defer" | grep -v "${noncounters_pattern}" |
2111 | 1043 | name_val "Multiple I/O Threads" "$(feat_on innodb_read_io_threads gt 1)" | 2019 | |
2112 | 1044 | name_val "Corruption Resilient" "$(feat_on innodb_pass_corrupt_table)" | 2020 | section "Table cache" |
2113 | 1045 | name_val "Durable Replication" "$(feat_on innodb_overwrite_relay_log_info)" | 2021 | local open_tables=$(get_var "Open_tables" "$dir/mysql-status") |
2114 | 1046 | name_val "Import InnoDB Tables" "$(feat_on innodb_expand_import)" | 2022 | local table_cache=$(get_table_cache "$dir/mysql-variables") |
2115 | 1047 | name_val "Fast Server Restarts" "$(feat_on innodb_auto_lru_dump)" | 2023 | name_val Size $table_cache |
2116 | 1048 | name_val "Enhanced Logging" "$(feat_on log_slow_verbosity ne microtime)" | 2024 | name_val Usage "$(fuzzy_pct ${open_tables} ${table_cache})" |
2117 | 1049 | name_val "Replica Perf Logging" "$(feat_on log_slow_slave_statements)" | 2025 | |
2118 | 1050 | name_val "Response Time Hist." "$(feat_on enable_query_response_time_stats)" | 2026 | section "Key Percona Server features" |
2119 | 1051 | name_val "Smooth Flushing" "$(feat_on innodb_adaptive_checkpoint ne none)" | 2027 | section_percona_server_features "$dir/mysql-variables" |
2120 | 1052 | name_val "HandlerSocket NoSQL" "$(feat_on handlersocket_port)" | 2028 | |
2121 | 1053 | mysql "$@" -e 'SELECT FNV_64("a")' >/dev/null 2>&1 && FNV_64="Enabled"; | 2029 | section "Plugins" |
2122 | 1054 | name_val "Fast Maatkit Hashes" "${FNV_64:-Unknown}" | 2030 | name_val "InnoDB compression" "$(get_plugin_status "$dir/mysql-plugins" "INNODB_CMP")" |
2123 | 1055 | 2031 | ||
2124 | 1056 | # ######################################################################## | 2032 | if [ "$(get_var have_query_cache "$dir/mysql-variables")" ]; then |
2125 | 1057 | # Query cache | 2033 | section "Query cache" |
2126 | 1058 | # ######################################################################## | 2034 | local query_cache_size=$(get_var query_cache_size "$dir/mysql-variables") |
2127 | 1059 | query_cache_size=$(get_var query_cache_size); | 2035 | local used=$(( ${query_cache_size} - $(get_var Qcache_free_memory "$dir/mysql-status") )) |
2128 | 1060 | if [ "$(get_var have_query_cache)" ]; then | 2036 | local hrat=$(fuzzy_pct $(get_var Qcache_hits "$dir/mysql-status") $(get_var Qcache_inserts "$dir/mysql-status")) |
2129 | 1061 | section Query_cache | 2037 | name_val query_cache_type $(get_var query_cache_type "$dir/mysql-variables") |
2101 | 1062 | name_val query_cache_type $(get_var query_cache_type) | ||
2130 | 1063 | name_val Size "$(shorten ${query_cache_size} 1)" | 2038 | name_val Size "$(shorten ${query_cache_size} 1)" |
2131 | 1064 | used=$(( ${query_cache_size} - $(get_stat Qcache_free_memory) )) | ||
2132 | 1065 | name_val Usage "$(fuzzy_pct ${used} ${query_cache_size})" | 2039 | name_val Usage "$(fuzzy_pct ${used} ${query_cache_size})" |
2133 | 1066 | hrat=$(fuzzy_pct $(get_stat Qcache_hits) $(get_stat Qcache_inserts)) | ||
2134 | 1067 | name_val HitToInsertRatio "${hrat}" | 2040 | name_val HitToInsertRatio "${hrat}" |
2135 | 1068 | fi | 2041 | fi |
2136 | 1069 | 2042 | ||
2144 | 1070 | # ######################################################################## | 2043 | local semisync_enabled_master="$(get_var "rpl_semi_sync_master_enabled" "$dir/mysql-variables")" |
2145 | 1071 | # Schema, databases, data type, other analysis. | 2044 | if [ -n "${semisync_enabled_master}" ]; then |
2146 | 1072 | # ######################################################################## | 2045 | section "Semisynchronous Replication" |
2147 | 1073 | section Schema | 2046 | if [ "$semisync_enabled_master" = "OFF" -o "$semisync_enabled_master" = "0" -o -z "$semisync_enabled_master" ]; then |
2148 | 1074 | # Assume "no" if stdin or stdout is not a terminal, so this can be run and | 2047 | name_val "Master" "Disabled" |
2149 | 1075 | # put into a file, or piped into a pager, or something else like that. | 2048 | else |
2150 | 1076 | if [ -t 0 -a -t 1 ]; then | 2049 | _semi_sync_stats_for "master" "$dir/mysql-variables" |
2151 | 2050 | fi | ||
2152 | 2051 | local semisync_enabled_slave="$(get_var rpl_semi_sync_slave_enabled "$dir/mysql-variables")" | ||
2153 | 2052 | if [ "$semisync_enabled_slave" = "OFF" -o "$semisync_enabled_slave" = "0" -o -z "$semisync_enabled_slave" ]; then | ||
2154 | 2053 | name_val "Slave" "Disabled" | ||
2155 | 2054 | else | ||
2156 | 2055 | _semi_sync_stats_for "slave" "$dir/mysql-variables" | ||
2157 | 2056 | fi | ||
2158 | 2057 | fi | ||
2159 | 2058 | |||
2160 | 2059 | section "Schema" | ||
2161 | 2060 | local reply="n" | ||
2162 | 2061 | if [ "${OPT_DATABASES}" ] || [ "${OPT_READ_SAMPLES}" ] \ | ||
2163 | 2062 | || [ -e "$dir/mysqldump" -a -s "$dir/mysqldump" ]; then | ||
2164 | 2063 | reply="y" | ||
2165 | 2064 | elif [ -t 0 -a -t 1 ]; then | ||
2166 | 1077 | echo -n "Would you like to mysqldump -d the schema and analyze it? y/n " | 2065 | echo -n "Would you like to mysqldump -d the schema and analyze it? y/n " |
2167 | 1078 | read reply | 2066 | read reply |
2168 | 1079 | reply=${reply:-n} | 2067 | reply=${reply:-n} |
2169 | 1080 | fi | 2068 | fi |
2202 | 1081 | if echo "${reply:-n}" | $AP_GREP -i '^y' > /dev/null ; then | 2069 | if echo "${reply:-n}" | grep -i '^y' > /dev/null ; then |
2203 | 1082 | # If mysqldump supports triggers, then add options for routines. | 2070 | if [ -z "${OPT_DATABASES}" ] && [ -z "$OPT_READ_SAMPLES" ] \ |
2204 | 1083 | if mysqldump --help --verbose 2>&1 | $AP_GREP triggers >/dev/null; then | 2071 | && [ ! -e "$dir/mysqldump" ]; then |
2205 | 1084 | trg_arg="--routines" | 2072 | echo "There are ${num_dbs} databases. Would you like to dump all, or just one?" |
2206 | 1085 | fi | 2073 | echo -n "Type the name of the database, or press Enter to dump all of them. " |
2207 | 1086 | if [ "${trg_arg}" ]; then | 2074 | local dbtodump="" |
2208 | 1087 | # Find out if there are any triggers. If there are none, we will skip | 2075 | read dbtodump |
2209 | 1088 | # that option to mysqldump, because when mysqldump checks for them, it | 2076 | local trg_arg="$( get_mysqldump_args "$dir/mysql-variables" )" |
2210 | 1089 | # can take a long time, one table at a time. | 2077 | get_mysqldump_for "${trg_arg}" "${dbtodump}" > "$dir/mysqldump" |
2211 | 1090 | triggers="--skip-triggers" | 2078 | fi |
2212 | 1091 | trg=$(mysql "$@" -ss -e "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TRIGGERS" 2>/dev/null); | 2079 | |
2213 | 1092 | if [ "${res}" ]; then | 2080 | if [ -e "$dir/mysqldump" -a -s "$dir/mysqldump" ] \ |
2214 | 1093 | if [ "${res}" -gt 0 ]; then | 2081 | && grep 'CREATE TABLE' "$dir/mysqldump" >/dev/null 2>&1; then |
2215 | 1094 | triggers="--triggers" | 2082 | format_overall_db_stats "$dir/mysqldump" |
2216 | 1095 | fi | 2083 | elif [ ! -e "$dir/mysqldump" -a "$OPT_READ_SAMPLES" ]; then |
2217 | 1096 | fi | 2084 | echo "Skipping schema analysis as the directory passed in" \ |
2218 | 1097 | trg_arg="${trg_arg} ${triggers}"; | 2085 | "doesn't have a dump file" |
2187 | 1098 | fi | ||
2188 | 1099 | # Find out which databases to dump | ||
2189 | 1100 | num_dbs="$($AP_GREP -c . $TMPDIR/percona-toolkit-mysql-databases)" | ||
2190 | 1101 | echo "There are ${num_dbs} databases. Would you like to dump all, or just one?" | ||
2191 | 1102 | echo -n "Type the name of the database, or press Enter to dump all of them. " | ||
2192 | 1103 | read dbtodump | ||
2193 | 1104 | mysqldump "$@" --no-data --skip-comments \ | ||
2194 | 1105 | --skip-add-locks --skip-add-drop-table --compact \ | ||
2195 | 1106 | --skip-lock-all-tables --skip-lock-tables --skip-set-charset \ | ||
2196 | 1107 | ${trg_arg} ${dbtodump:---all-databases} > $TMPDIR/percona-toolkit-mysqldump | ||
2197 | 1108 | # Test the result by checking the file, not by the exit status, because we | ||
2198 | 1109 | # might get partway through and then die, and the info is worth analyzing | ||
2199 | 1110 | # anyway. | ||
2200 | 1111 | if $AP_GREP 'CREATE TABLE' $TMPDIR/percona-toolkit-mysqldump >/dev/null 2>&1; then | ||
2201 | 1112 | format_overall_db_stats $TMPDIR/percona-toolkit-mysqldump | ||
2219 | 1113 | else | 2086 | else |
2220 | 1114 | echo "Skipping schema analysis due to apparent error in dump file" | 2087 | echo "Skipping schema analysis due to apparent error in dump file" |
2221 | 1115 | rm -f $TMPDIR/percona-toolkit-mysqldump | ||
2222 | 1116 | fi | 2088 | fi |
2223 | 1117 | else | 2089 | else |
2224 | 1118 | echo "Skipping schema analysis" | 2090 | echo "Skipping schema analysis" |
2225 | 1119 | fi | 2091 | fi |
2226 | 1120 | 2092 | ||
2279 | 1121 | # ######################################################################## | 2093 | section "Noteworthy Technologies" |
2280 | 1122 | # Noteworthy Technologies | 2094 | if [ -s "$dir/mysqldump" ]; then |
2281 | 1123 | # ######################################################################## | 2095 | if grep FULLTEXT "$dir/mysqldump" > /dev/null; then |
2282 | 1124 | section Noteworthy_Technologies | 2096 | name_val "Full Text Indexing" "Yes" |
2283 | 1125 | if [ -e $TMPDIR/percona-toolkit-mysqldump ]; then | 2097 | else |
2284 | 1126 | if $AP_GREP FULLTEXT $TMPDIR/percona-toolkit-mysqldump > /dev/null; then | 2098 | name_val "Full Text Indexing" "No" |
2285 | 1127 | name_val "Full Text Indexing" Yes | 2099 | fi |
2286 | 1128 | else | 2100 | if grep 'GEOMETRY\|POINT\|LINESTRING\|POLYGON' "$dir/mysqldump" > /dev/null; then |
2287 | 1129 | name_val "Full Text Indexing" No | 2101 | name_val "Geospatial Types" "Yes" |
2288 | 1130 | fi | 2102 | else |
2289 | 1131 | if $AP_GREP 'GEOMETRY\|POINT\|LINESTRING\|POLYGON' $TMPDIR/percona-toolkit-mysqldump > /dev/null; then | 2103 | name_val "Geospatial Types" "No" |
2290 | 1132 | name_val "Geospatial Types" Yes | 2104 | fi |
2291 | 1133 | else | 2105 | if grep 'FOREIGN KEY' "$dir/mysqldump" > /dev/null; then |
2292 | 1134 | name_val "Geospatial Types" No | 2106 | name_val "Foreign Keys" "Yes" |
2293 | 1135 | fi | 2107 | else |
2294 | 1136 | if $AP_GREP 'FOREIGN KEY' $TMPDIR/percona-toolkit-mysqldump > /dev/null; then | 2108 | name_val "Foreign Keys" "No" |
2295 | 1137 | name_val "Foreign Keys" Yes | 2109 | fi |
2296 | 1138 | else | 2110 | if grep 'PARTITION BY' "$dir/mysqldump" > /dev/null; then |
2297 | 1139 | name_val "Foreign Keys" No | 2111 | name_val "Partitioning" "Yes" |
2298 | 1140 | fi | 2112 | else |
2299 | 1141 | if $AP_GREP 'PARTITION BY' $TMPDIR/percona-toolkit-mysqldump > /dev/null; then | 2113 | name_val "Partitioning" "No" |
2300 | 1142 | name_val "Partitioning" Yes | 2114 | fi |
2301 | 1143 | else | 2115 | if grep -e 'ENGINE=InnoDB.*ROW_FORMAT' \ |
2302 | 1144 | name_val "Partitioning" No | 2116 | -e 'ENGINE=InnoDB.*KEY_BLOCK_SIZE' "$dir/mysqldump" > /dev/null; then |
2303 | 1145 | fi | 2117 | name_val "InnoDB Compression" "Yes" |
2304 | 1146 | fi | 2118 | else |
2305 | 1147 | if [ "$(get_stat Ssl_accepts)" -gt 0 ]; then | 2119 | name_val "InnoDB Compression" "No" |
2306 | 1148 | name_val "SSL" Yes | 2120 | fi |
2307 | 1149 | else | 2121 | fi |
2308 | 1150 | name_val "SSL" No | 2122 | local ssl="$(get_var Ssl_accepts "$dir/mysql-status")" |
2309 | 1151 | fi | 2123 | if [ -n "$ssl" -a "${ssl:-0}" -gt 0 ]; then |
2310 | 1152 | if [ "$(get_stat Com_lock_tables)" -gt 0 ]; then | 2124 | name_val "SSL" "Yes" |
2311 | 1153 | name_val "Explicit LOCK TABLES" Yes | 2125 | else |
2312 | 1154 | else | 2126 | name_val "SSL" "No" |
2313 | 1155 | name_val "Explicit LOCK TABLES" No | 2127 | fi |
2314 | 1156 | fi | 2128 | local lock_tables="$(get_var Com_lock_tables "$dir/mysql-status")" |
2315 | 1157 | if [ "$(get_stat Delayed_writes)" -gt 0 ]; then | 2129 | if [ -n "$lock_tables" -a "${lock_tables:-0}" -gt 0 ]; then |
2316 | 1158 | name_val "Delayed Insert" Yes | 2130 | name_val "Explicit LOCK TABLES" "Yes" |
2317 | 1159 | else | 2131 | else |
2318 | 1160 | name_val "Delayed Insert" No | 2132 | name_val "Explicit LOCK TABLES" "No" |
2319 | 1161 | fi | 2133 | fi |
2320 | 1162 | if [ "$(get_stat Com_xa_start)" -gt 0 ]; then | 2134 | local delayed_insert="$(get_var Delayed_writes "$dir/mysql-status")" |
2321 | 1163 | name_val "XA Transactions" Yes | 2135 | if [ -n "$delayed_insert" -a "${delayed_insert:-0}" -gt 0 ]; then |
2322 | 1164 | else | 2136 | name_val "Delayed Insert" "Yes" |
2323 | 1165 | name_val "XA Transactions" No | 2137 | else |
2324 | 1166 | fi | 2138 | name_val "Delayed Insert" "No" |
2325 | 1167 | if [ "$(get_stat Ndb_cluster_node_id)" -gt 0 ]; then | 2139 | fi |
2326 | 1168 | name_val "NDB Cluster" Yes | 2140 | local xat="$(get_var Com_xa_start "$dir/mysql-status")" |
2327 | 1169 | else | 2141 | if [ -n "$xat" -a "${xat:-0}" -gt 0 ]; then |
2328 | 1170 | name_val "NDB Cluster" No | 2142 | name_val "XA Transactions" "Yes" |
2329 | 1171 | fi | 2143 | else |
2330 | 1172 | prep=$(( $(get_stat Com_stmt_prepare) + $(get_stat Com_prepare_sql) )) | 2144 | name_val "XA Transactions" "No" |
2331 | 2145 | fi | ||
2332 | 2146 | local ndb_cluster="$(get_var "Ndb_cluster_node_id" "$dir/mysql-status")" | ||
2333 | 2147 | if [ -n "$ndb_cluster" -a "${ndb_cluster:-0}" -gt 0 ]; then | ||
2334 | 2148 | name_val "NDB Cluster" "Yes" | ||
2335 | 2149 | else | ||
2336 | 2150 | name_val "NDB Cluster" "No" | ||
2337 | 2151 | fi | ||
2338 | 2152 | local prep=$(( $(get_var "Com_stmt_prepare" "$dir/mysql-status") + $(get_var "Com_prepare_sql" "$dir/mysql-status") )) | ||
2339 | 1173 | if [ "${prep}" -gt 0 ]; then | 2153 | if [ "${prep}" -gt 0 ]; then |
2341 | 1174 | name_val "Prepared Statements" Yes | 2154 | name_val "Prepared Statements" "Yes" |
2342 | 1175 | else | 2155 | else |
2344 | 1176 | name_val "Prepared Statements" No | 2156 | name_val "Prepared Statements" "No" |
2345 | 2157 | fi | ||
2346 | 2158 | local prep_count="$(get_var Prepared_stmt_count "$dir/mysql-status")" | ||
2347 | 2159 | if [ "${prep_count}" ]; then | ||
2348 | 2160 | name_val "Prepared statement count" "${prep_count}" | ||
2349 | 1177 | fi | 2161 | fi |
2350 | 1178 | 2162 | ||
2356 | 1179 | # ######################################################################## | 2163 | section "InnoDB" |
2357 | 1180 | # InnoDB | 2164 | local have_innodb="$(get_var "have_innodb" "$dir/mysql-variables")" |
2353 | 1181 | # ######################################################################## | ||
2354 | 1182 | section InnoDB | ||
2355 | 1183 | have_innodb=$(get_var have_innodb) | ||
2358 | 1184 | if [ "${have_innodb}" = "YES" ]; then | 2165 | if [ "${have_innodb}" = "YES" ]; then |
2397 | 1185 | 2166 | section_innodb "$dir/mysql-variables" "$dir/mysql-status" | |
2398 | 1186 | version=$(get_var innodb_version) | 2167 | |
2399 | 1187 | name_val Version ${version:-default} | 2168 | if [ -s "$dir/innodb-status" ]; then |
2400 | 1188 | 2169 | format_innodb_status "$dir/innodb-status" | |
2363 | 1189 | bp_size="$(get_var innodb_buffer_pool_size)" | ||
2364 | 1190 | name_val "Buffer Pool Size" "$(shorten ${bp_size} 1)" | ||
2365 | 1191 | |||
2366 | 1192 | bp_pags="$(get_stat Innodb_buffer_pool_pages_total)" | ||
2367 | 1193 | bp_free="$(get_stat Innodb_buffer_pool_pages_free)" | ||
2368 | 1194 | bp_dirt="$(get_stat Innodb_buffer_pool_pages_dirty)" | ||
2369 | 1195 | bp_fill=$((${bp_pags} - ${bp_free})) | ||
2370 | 1196 | name_val "Buffer Pool Fill" "$(fuzzy_pct ${bp_fill} ${bp_pags})" | ||
2371 | 1197 | name_val "Buffer Pool Dirty" "$(fuzzy_pct ${bp_dirt} ${bp_pags})" | ||
2372 | 1198 | |||
2373 | 1199 | name_val "File Per Table" $(get_var innodb_file_per_table) | ||
2374 | 1200 | name_val "Page Size" $(shorten $(get_stat Innodb_page_size)) | ||
2375 | 1201 | |||
2376 | 1202 | lg_size="$(get_var innodb_log_file_size)" | ||
2377 | 1203 | lg_fils="$(get_var innodb_log_files_in_group)" | ||
2378 | 1204 | lg_totl="$((${lg_size} * ${lg_fils}))" | ||
2379 | 1205 | name_val "Log File Size" "${lg_fils} * $(shorten ${lg_size}) = $(shorten ${lg_totl} 1)" | ||
2380 | 1206 | name_val "Log Buffer Size" $(shorten $(get_var innodb_log_buffer_size)) | ||
2381 | 1207 | name_val "Flush Method" $(get_var innodb_flush_method) | ||
2382 | 1208 | name_val "Flush Log At Commit" $(get_var innodb_flush_log_at_trx_commit) | ||
2383 | 1209 | name_val "XA Support" $(get_var innodb_support_xa) | ||
2384 | 1210 | name_val "Checksums" $(get_var innodb_checksums) | ||
2385 | 1211 | name_val "Doublewrite" $(get_var innodb_doublewrite) | ||
2386 | 1212 | name_val "R/W I/O Threads" "$(get_var innodb_read_io_threads) $(get_var innodb_write_io_threads)" | ||
2387 | 1213 | name_val "I/O Capacity" $(get_var innodb_io_capacity) | ||
2388 | 1214 | name_val "Thread Concurrency" $(get_var innodb_thread_concurrency) | ||
2389 | 1215 | name_val "Concurrency Tickets" $(get_var innodb_concurrency_tickets) | ||
2390 | 1216 | name_val "Commit Concurrency" $(get_var innodb_commit_concurrency) | ||
2391 | 1217 | name_val "Txn Isolation Level" $(get_var tx_isolation) | ||
2392 | 1218 | name_val "Adaptive Flushing" $(get_var innodb_adaptive_flushing) | ||
2393 | 1219 | name_val "Adaptive Checkpoint" $(get_var innodb_adaptive_checkpoint) | ||
2394 | 1220 | |||
2395 | 1221 | if [ -s $TMPDIR/percona-toolkit-innodb-status ]; then | ||
2396 | 1222 | format_innodb_status $TMPDIR/percona-toolkit-innodb-status | ||
2401 | 1223 | fi | 2170 | fi |
2402 | 1224 | fi | 2171 | fi |
2403 | 1225 | 2172 | ||
2438 | 1226 | # ######################################################################## | 2173 | section "MyISAM" |
2439 | 1227 | # MyISAM | 2174 | section_myisam "$dir/mysql-variables" "$dir/mysql-status" |
2440 | 1228 | # ######################################################################## | 2175 | |
2441 | 1229 | section MyISAM | 2176 | section "Security" |
2442 | 1230 | buf_size=$(get_var key_buffer_size) | 2177 | local users="$( format_users "$dir/mysql-users" )" |
2443 | 1231 | blk_size=$(get_var key_cache_block_size) | 2178 | name_val "Users" "${users}" |
2444 | 1232 | blk_unus=$(get_stat Key_blocks_unused) | 2179 | name_val "Old Passwords" "$(get_var old_passwords "$dir/mysql-variables")" |
2445 | 1233 | blk_unfl=$(get_stat Key_blocks_not_flushed) | 2180 | |
2446 | 1234 | unus=$((${blk_unus} * ${blk_size})) | 2181 | section "Binary Logging" |
2447 | 1235 | unfl=$((${blk_unfl} * ${blk_size})) | 2182 | |
2448 | 1236 | used=$((${buf_size} - ${unus})) | 2183 | if [ -s "$dir/mysql-master-logs" ] \ |
2449 | 1237 | name_val "Key Cache" "$(shorten ${buf_size} 1)" | 2184 | || [ -s "$dir/mysql-master-status" ]; then |
2450 | 1238 | name_val "Pct Used" "$(fuzzy_pct ${used} ${buf_size})" | 2185 | summarize_binlogs "$dir/mysql-master-logs" |
2451 | 1239 | name_val "Unflushed" "$(fuzzy_pct ${unfl} ${buf_size})" | 2186 | local format="$(get_var binlog_format "$dir/mysql-variables")" |
2418 | 1240 | |||
2419 | 1241 | # ######################################################################## | ||
2420 | 1242 | # Users & Security | ||
2421 | 1243 | # ######################################################################## | ||
2422 | 1244 | section Security | ||
2423 | 1245 | users="$(mysql "$@" -ss \ | ||
2424 | 1246 | -e 'SELECT COUNT(*), SUM(user=""), SUM(password=""), SUM(password NOT LIKE "*%") FROM mysql.user' 2>/dev/null \ | ||
2425 | 1247 | | $AP_AWK '{printf "%d users, %d anon, %d w/o pw, %d old pw\n", $1, $2, $3, $4}')" | ||
2426 | 1248 | name_val Users "${users}" | ||
2427 | 1249 | name_val "Old Passwords" $(get_var old_passwords) | ||
2428 | 1250 | |||
2429 | 1251 | # ######################################################################## | ||
2430 | 1252 | # Binary Logging | ||
2431 | 1253 | # ######################################################################## | ||
2432 | 1254 | section Binary_Logging | ||
2433 | 1255 | binlog=$(get_var log_bin) | ||
2434 | 1256 | if [ "${binlog}" ]; then | ||
2435 | 1257 | mysql "$@" -ss -e 'SHOW MASTER LOGS' > $TMPDIR/percona-toolkit 2>/dev/null | ||
2436 | 1258 | summarize_binlogs $TMPDIR/percona-toolkit | ||
2437 | 1259 | format="$(get_var binlog_format)" | ||
2452 | 1260 | name_val binlog_format "${format:-STATEMENT}" | 2187 | name_val binlog_format "${format:-STATEMENT}" |
2503 | 1261 | name_val expire_logs_days $(get_var expire_logs_days) | 2188 | name_val expire_logs_days "$(get_var expire_logs_days "$dir/mysql-variables")" |
2504 | 1262 | name_val sync_binlog $(get_var sync_binlog) | 2189 | name_val sync_binlog "$(get_var sync_binlog "$dir/mysql-variables")" |
2505 | 1263 | name_val server_id $(get_var server_id) | 2190 | name_val server_id "$(get_var server_id "$dir/mysql-variables")" |
2506 | 1264 | mysql "$@" -ss -e 'SHOW MASTER STATUS' > $TMPDIR/percona-toolkit 2>/dev/null | 2191 | format_binlog_filters "$dir/mysql-master-status" |
2507 | 1265 | format_binlog_filters $TMPDIR/percona-toolkit | 2192 | fi |
2508 | 1266 | fi | 2193 | |
2509 | 1267 | 2194 | ||
2510 | 1268 | # Replication: seconds behind, running, filters, skip_slave_start, skip_errors, | 2195 | section "Noteworthy Variables" |
2511 | 1269 | # read_only, temp tables open, slave_net_timeout, slave_exec_mode | 2196 | section_noteworthy_variables "$dir/mysql-variables" |
2512 | 1270 | 2197 | ||
2513 | 1271 | # ######################################################################## | 2198 | section "Configuration File" |
2514 | 1272 | # Interesting things that you just ought to know about. | 2199 | local cnf_file="$(get_var "pt-summary-internal-Config_File_path" "$dir/mysql-variables")" |
2515 | 1273 | # ######################################################################## | 2200 | if [ -n "${cnf_file}" ]; then |
2466 | 1274 | section Noteworthy_Variables | ||
2467 | 1275 | name_val "Auto-Inc Incr/Offset" "$(get_var auto_increment_increment)/$(get_var auto_increment_offset)" | ||
2468 | 1276 | for v in \ | ||
2469 | 1277 | default_storage_engine flush_time init_connect init_file sql_mode; | ||
2470 | 1278 | do | ||
2471 | 1279 | name_val ${v} $(get_var ${v}) | ||
2472 | 1280 | done | ||
2473 | 1281 | for v in \ | ||
2474 | 1282 | join_buffer_size sort_buffer_size read_buffer_size read_rnd_buffer_size \ | ||
2475 | 1283 | bulk_insert_buffer max_heap_table_size tmp_table_size \ | ||
2476 | 1284 | max_allowed_packet thread_stack; | ||
2477 | 1285 | do | ||
2478 | 1286 | name_val ${v} $(shorten $(get_var ${v})) | ||
2479 | 1287 | done | ||
2480 | 1288 | for v in log log_error log_warnings log_slow_queries \ | ||
2481 | 1289 | log_queries_not_using_indexes log_slave_updates; | ||
2482 | 1290 | do | ||
2483 | 1291 | name_val ${v} $(get_var ${v}) | ||
2484 | 1292 | done | ||
2485 | 1293 | |||
2486 | 1294 | # ######################################################################## | ||
2487 | 1295 | # If there is a my.cnf in a standard location, see if we can pretty-print it. | ||
2488 | 1296 | # ######################################################################## | ||
2489 | 1297 | section Configuration_File | ||
2490 | 1298 | ps auxww 2>/dev/null | $AP_GREP mysqld > $TMPDIR/percona-toolkit | ||
2491 | 1299 | cnf_file=$(find_my_cnf_file $TMPDIR/percona-toolkit ${port}); | ||
2492 | 1300 | if [ ! -e "${cnf_file}" ]; then | ||
2493 | 1301 | name_val "Config File" "Cannot autodetect, trying common locations" | ||
2494 | 1302 | cnf_file="/etc/my.cnf"; | ||
2495 | 1303 | fi | ||
2496 | 1304 | if [ ! -e "${cnf_file}" ]; then | ||
2497 | 1305 | cnf_file="/etc/mysql/my.cnf"; | ||
2498 | 1306 | fi | ||
2499 | 1307 | if [ ! -e "${cnf_file}" ]; then | ||
2500 | 1308 | cnf_file="/var/db/mysql/my.cnf"; | ||
2501 | 1309 | fi | ||
2502 | 1310 | if [ -e "${cnf_file}" ]; then | ||
2516 | 1311 | name_val "Config File" "${cnf_file}" | 2201 | name_val "Config File" "${cnf_file}" |
2519 | 1312 | cat "${cnf_file}" > $TMPDIR/percona-toolkit | 2202 | pretty_print_cnf_file "$dir/mysql-config-file" |
2518 | 1313 | pretty_print_cnf_file $TMPDIR/percona-toolkit | ||
2520 | 1314 | else | 2203 | else |
2521 | 1315 | name_val "Config File" "Cannot autodetect or find, giving up" | 2204 | name_val "Config File" "Cannot autodetect or find, giving up" |
2522 | 1316 | fi | 2205 | fi |
2523 | 1317 | 2206 | ||
2535 | 1318 | temp_files "rm" | 2207 | section "The End" |
2536 | 1319 | 2208 | } | |
2537 | 1320 | # Make sure that we signal the end of the tool's output. | 2209 | |
2538 | 1321 | section The_End | 2210 | # ########################################################################### |
2539 | 1322 | 2211 | # End report_mysql_info package | |
2540 | 1323 | rm_tmpdir | 2212 | # ########################################################################### |
2541 | 1324 | } | 2213 | |
2542 | 1325 | 2214 | # ######################################################################## | |
2543 | 1326 | # Execute the program if it was not included from another file. This makes it | 2215 | # Some global setup is necessary for cross-platform compatibility, even |
2544 | 1327 | # possible to include without executing, and thus test. | 2216 | # when sourcing this script for testing purposes. |
2545 | 1328 | if [ "$(basename "$0")" = "pt-mysql-summary" ]; then main "$@"; fi | 2217 | # ######################################################################## |
2546 | 2218 | |||
2547 | 2219 | TOOL="pt-mysql-summary" | ||
2548 | 2220 | |||
2549 | 2221 | CMD_MYSQL="$(_which mysql)" | ||
2550 | 2222 | CMD_MYSQLDUMP="$( _which mysqldump )" | ||
2551 | 2223 | |||
2552 | 2224 | check_mysql () { | ||
2553 | 2225 | # Check that mysql and mysqldump are in PATH. If not, we're | ||
2554 | 2226 | # already dead in the water, so don't bother with cmd line opts, | ||
2555 | 2227 | # just error and exit. | ||
2556 | 2228 | [ -n "$(mysql --help 2>/dev/null)" ] \ | ||
2557 | 2229 | || die "Cannot execute mysql. Check that it is in PATH." | ||
2558 | 2230 | [ -n "$(mysqldump --help 2>/dev/null)" ] \ | ||
2559 | 2231 | || die "Cannot execute mysqldump. Check that it is in PATH." | ||
2560 | 2232 | |||
2561 | 2233 | # Now that we have the cmd line opts, check that we can actually | ||
2562 | 2234 | # connect to MySQL. | ||
2563 | 2235 | [ -n "$(mysql $EXT_ARGV -e 'SELECT 1')" ] \ | ||
2564 | 2236 | || die "Cannot connect to MySQL. Check that MySQL is running and that the options after -- are correct." | ||
2565 | 2237 | |||
2566 | 2238 | } | ||
2567 | 2239 | |||
2568 | 2240 | sigtrap() { | ||
2569 | 2241 | warn "Caught signal, forcing exit" | ||
2570 | 2242 | rm_tmpdir | ||
2571 | 2243 | exit $EXIT_STATUS | ||
2572 | 2244 | } | ||
2573 | 2245 | |||
2574 | 2246 | # ############################################################################## | ||
2575 | 2247 | # The main() function is called at the end of the script. This makes it | ||
2576 | 2248 | # testable. Major bits of parsing are separated into functions for testability. | ||
2577 | 2249 | # ############################################################################## | ||
2578 | 2250 | main() { | ||
2579 | 2251 | # Prepending SIG to these doesn't work with NetBSD's sh | ||
2580 | 2252 | trap sigtrap HUP INT TERM | ||
2581 | 2253 | |||
2582 | 2254 | local RAN_WITH="--sleep=$OPT_SLEEP --databases=$OPT_DATABASES --save-samples=$OPT_SAVE_SAMPLES" | ||
2583 | 2255 | |||
2584 | 2256 | _d "Starting $0 $RAN_WITH" | ||
2585 | 2257 | |||
2586 | 2258 | # Begin by setting the $PATH to include some common locations that are not | ||
2587 | 2259 | # always in the $PATH, including the "sbin" locations. On SunOS systems, | ||
2588 | 2260 | # prefix the path with the location of more sophisticated utilities. | ||
2589 | 2261 | export PATH="${PATH}:/usr/local/bin:/usr/bin:/bin:/usr/libexec" | ||
2590 | 2262 | export PATH="${PATH}:/usr/mysql/bin/:/usr/local/sbin:/usr/sbin:/sbin" | ||
2591 | 2263 | export PATH="/usr/gnu/bin/:/usr/xpg4/bin/:${PATH}" | ||
2592 | 2264 | |||
2593 | 2265 | _d "Going to use: mysql=${CMD_MYSQL} mysqldump=${CMD_MYSQLDUMP}" | ||
2594 | 2266 | |||
2595 | 2267 | # Create the tmpdir for everything to run in | ||
2596 | 2268 | mk_tmpdir | ||
2597 | 2269 | |||
2598 | 2270 | # Set DATA_DIR where we'll save collected data files. | ||
2599 | 2271 | local data_dir="$(setup_data_dir "${OPT_SAVE_SAMPLES:-""}")" | ||
2600 | 2272 | if [ -z "$data_dir" ]; then | ||
2601 | 2273 | exit $? | ||
2602 | 2274 | fi | ||
2603 | 2275 | |||
2604 | 2276 | if [ -n "$OPT_READ_SAMPLES" -a -d "$OPT_READ_SAMPLES" ]; then | ||
2605 | 2277 | # --read-samples was set and is a directory, so the samples | ||
2606 | 2278 | # will already be there. | ||
2607 | 2279 | data_dir="$OPT_READ_SAMPLES" | ||
2608 | 2280 | else | ||
2609 | 2281 | # ##################################################################### | ||
2610 | 2282 | # Fetch most info, leave a child in the background gathering the rest | ||
2611 | 2283 | # ##################################################################### | ||
2612 | 2284 | collect_mysql_info "${data_dir}" 2>"${data_dir}/collect.err" | ||
2613 | 2285 | fi | ||
2614 | 2286 | |||
2615 | 2287 | # ######################################################################## | ||
2616 | 2288 | # Format and pretty-print the data | ||
2617 | 2289 | # ######################################################################## | ||
2618 | 2290 | report_mysql_summary "${data_dir}" | ||
2619 | 2291 | |||
2620 | 2292 | rm_tmpdir | ||
2621 | 2293 | |||
2622 | 2294 | } | ||
2623 | 2295 | |||
2624 | 2296 | # Execute the program if it was not included from another file. | ||
2625 | 2297 | # This makes it possible to include without executing, and thus test. | ||
2626 | 2298 | if [ "${0##*/}" = "$TOOL" ] \ | ||
2627 | 2299 | || [ "${0##*/}" = "bash" -a "$_" = "$0" ]; then | ||
2628 | 2300 | |||
2629 | 2301 | # Set up temporary dir. | ||
2630 | 2302 | mk_tmpdir | ||
2631 | 2303 | # Parse command line options. | ||
2632 | 2304 | parse_options "$0" "$@" | ||
2633 | 2305 | |||
2634 | 2306 | # Verify that --sleep, if present, is positive | ||
2635 | 2307 | if [ -n "$OPT_SLEEP" ] && [ "$OPT_SLEEP" -lt 0 ]; then | ||
2636 | 2308 | option_error "Invalid --sleep value: $sleep" | ||
2637 | 2309 | fi | ||
2638 | 2310 | |||
2639 | 2311 | usage_or_errors "$0" | ||
2640 | 2312 | po_status=$? | ||
2641 | 2313 | rm_tmpdir | ||
2642 | 2314 | |||
2643 | 2315 | if [ $po_status -ne 0 ]; then | ||
2644 | 2316 | [ $OPT_ERRS -gt 0 ] && exit 1 | ||
2645 | 2317 | exit 0 | ||
2646 | 2318 | fi | ||
2647 | 2319 | |||
2648 | 2320 | # Check if mysql and mysqldump are there, otherwise bail out early. | ||
2649 | 2321 | # But don't if they passed in --read-samples, since we don't need | ||
2650 | 2322 | # a connection then. | ||
2651 | 2323 | [ "$OPT_READ_SAMPLES" ] || check_mysql | ||
2652 | 2324 | |||
2653 | 2325 | main "$@" | ||
2654 | 2326 | fi | ||
2655 | 1329 | 2327 | ||
2656 | 1330 | # ############################################################################ | 2328 | # ############################################################################ |
2657 | 1331 | # Documentation | 2329 | # Documentation |
2658 | @@ -1335,11 +2333,11 @@ | |||
2659 | 1335 | 2333 | ||
2660 | 1336 | =head1 NAME | 2334 | =head1 NAME |
2661 | 1337 | 2335 | ||
2663 | 1338 | pt-mysql-summary - Summarize MySQL information in a nice way. | 2336 | pt-mysql-summary - Summarize MySQL information nicely. |
2664 | 1339 | 2337 | ||
2665 | 1340 | =head1 SYNOPSIS | 2338 | =head1 SYNOPSIS |
2666 | 1341 | 2339 | ||
2668 | 1342 | Usage: pt-mysql-summary [MYSQL-OPTIONS] | 2340 | Usage: pt-mysql-summary [OPTIONS] [-- MYSQL OPTIONS] |
2669 | 1343 | 2341 | ||
2670 | 1344 | pt-mysql-summary conveniently summarizes the status and configuration of a | 2342 | pt-mysql-summary conveniently summarizes the status and configuration of a |
2671 | 1345 | MySQL database server so that you can learn about it at a glance. It is not | 2343 | MySQL database server so that you can learn about it at a glance. It is not |
2672 | @@ -1356,8 +2354,7 @@ | |||
2673 | 1356 | 2354 | ||
2674 | 1357 | pt-mysql-summary is a read-only tool. It should be very low-risk. | 2355 | pt-mysql-summary is a read-only tool. It should be very low-risk. |
2675 | 1358 | 2356 | ||
2678 | 1359 | At the time of this release, we know of no bugs that could cause serious harm | 2357 | At the time of this release, we know of no bugs that could harm users. |
2677 | 1360 | to users. | ||
2679 | 1361 | 2358 | ||
2680 | 1362 | The authoritative source for updated information is always the online issue | 2359 | The authoritative source for updated information is always the online issue |
2681 | 1363 | tracking system. Issues that affect this tool will be marked as such. You can | 2360 | tracking system. Issues that affect this tool will be marked as such. You can |
2682 | @@ -1373,34 +2370,435 @@ | |||
2683 | 1373 | into files in a temporary directory, and then formats them neatly with awk | 2370 | into files in a temporary directory, and then formats them neatly with awk |
2684 | 1374 | and other scripting languages. | 2371 | and other scripting languages. |
2685 | 1375 | 2372 | ||
2688 | 1376 | To use, simply execute it. Optionally add the same command-line options | 2373 | To use, simply execute it. Optionally add a double dash and then the same |
2689 | 1377 | you would use to connect to MySQL, like C<pt-mysql-summary --user=foo>. | 2374 | command-line options you would use to connect to MySQL, such as the following: |
2690 | 2375 | |||
2691 | 2376 | pt-mysql-summary -- --user=root | ||
2692 | 1378 | 2377 | ||
2693 | 1379 | The tool interacts minimally with the server upon which it runs. It assumes | 2378 | The tool interacts minimally with the server upon which it runs. It assumes |
2694 | 1380 | that you'll run it on the same server you're inspecting, and therefore it | 2379 | that you'll run it on the same server you're inspecting, and therefore it |
2702 | 1381 | assumes that it will be able to find the my.cnf configuration file, for | 2380 | assumes that it will be able to find the my.cnf configuration file, for example. |
2703 | 1382 | example. However, it should degrade gracefully if this is not the case. | 2381 | However, it should degrade gracefully if this is not the case. Note, however, |
2704 | 1383 | Note, however, that its output does not indicate which information comes from | 2382 | that its output does not indicate which information comes from the MySQL |
2705 | 1384 | the MySQL database and which comes from the host operating system, so it is | 2383 | database and which comes from the host operating system, so it is possible for |
2706 | 1385 | possible for confusing output to be generated if you run the tool on one | 2384 | confusing output to be generated if you run the tool on one server and connect |
2707 | 1386 | server and direct it to connect to a MySQL database server running on another | 2385 | to a MySQL database server running on another server. |
2701 | 1387 | server. | ||
2708 | 1388 | 2386 | ||
2710 | 1389 | =head1 Fuzzy-Rounding | 2387 | =head1 OUTPUT |
2711 | 1390 | 2388 | ||
2712 | 1391 | Many of the outputs from this tool are deliberately rounded to show their | 2389 | Many of the outputs from this tool are deliberately rounded to show their |
2713 | 1392 | magnitude but not the exact detail. This is called fuzzy-rounding. The idea | 2390 | magnitude but not the exact detail. This is called fuzzy-rounding. The idea |
2715 | 1393 | is that it doesn't matter whether a server is running 918 queries per second | 2391 | is that it does not matter whether a server is running 918 queries per second |
2716 | 1394 | or 921 queries per second; such a small variation is insignificant, and only | 2392 | or 921 queries per second; such a small variation is insignificant, and only |
2717 | 1395 | makes the output hard to compare to other servers. Fuzzy-rounding rounds in | 2393 | makes the output hard to compare to other servers. Fuzzy-rounding rounds in |
2718 | 1396 | larger increments as the input grows. It begins by rounding to the nearest 5, | 2394 | larger increments as the input grows. It begins by rounding to the nearest 5, |
2719 | 1397 | then the nearest 10, nearest 25, and then repeats by a factor of 10 larger | 2395 | then the nearest 10, nearest 25, and then repeats by a factor of 10 larger |
2720 | 1398 | (50, 100, 250), and so on, as the input grows. | 2396 | (50, 100, 250), and so on, as the input grows. |
2721 | 1399 | 2397 | ||
2722 | 2398 | The following is a sample of the report that the tool produces: | ||
2723 | 2399 | |||
2724 | 2400 | # Percona Toolkit MySQL Summary Report ####################### | ||
2725 | 2401 | System time | 2012-03-30 18:46:05 UTC | ||
2726 | 2402 | (local TZ: EDT -0400) | ||
2727 | 2403 | # Instances ################################################## | ||
2728 | 2404 | Port Data Directory Nice OOM Socket | ||
2729 | 2405 | ===== ========================== ==== === ====== | ||
2730 | 2406 | 12345 /tmp/12345/data 0 0 /tmp/12345.sock | ||
2731 | 2407 | 12346 /tmp/12346/data 0 0 /tmp/12346.sock | ||
2732 | 2408 | 12347 /tmp/12347/data 0 0 /tmp/12347.sock | ||
2733 | 2409 | |||
2734 | 2410 | The first two sections show which server the report was generated on and which | ||
2735 | 2411 | MySQL instances are running on the server. This is detected from the output of | ||
2736 | 2412 | C<ps> and does not always detect all instances and parameters, but often works | ||
2737 | 2413 | well. From this point forward, the report will be focused on a single MySQL | ||
2738 | 2414 | instance, although several instances may appear in the above paragraph. | ||
2739 | 2415 | |||
2740 | 2416 | # Report On Port 12345 ####################################### | ||
2741 | 2417 | User | msandbox@% | ||
2742 | 2418 | Time | 2012-03-30 14:46:05 (EDT) | ||
2743 | 2419 | Hostname | localhost.localdomain | ||
2744 | 2420 | Version | 5.5.20-log MySQL Community Server (GPL) | ||
2745 | 2421 | Built On | linux2.6 i686 | ||
2746 | 2422 | Started | 2012-03-28 23:33 (up 1+15:12:09) | ||
2747 | 2423 | Databases | 4 | ||
2748 | 2424 | Datadir | /tmp/12345/data/ | ||
2749 | 2425 | Processes | 2 connected, 2 running | ||
2750 | 2426 | Replication | Is not a slave, has 1 slaves connected | ||
2751 | 2427 | Pidfile | /tmp/12345/data/12345.pid (exists) | ||
2752 | 2428 | |||
2753 | 2429 | This section is a quick summary of the MySQL instance: version, uptime, and | ||
2754 | 2430 | other very basic parameters. The Time output is generated from the MySQL server, | ||
2755 | 2431 | unlike the system date and time printed earlier, so you can see whether the | ||
2756 | 2432 | database and operating system times match. | ||
2757 | 2433 | |||
2758 | 2434 | # Processlist ################################################ | ||
2759 | 2435 | |||
2760 | 2436 | Command COUNT(*) Working SUM(Time) MAX(Time) | ||
2761 | 2437 | ------------------------------ -------- ------- --------- --------- | ||
2762 | 2438 | Binlog Dump 1 1 150000 150000 | ||
2763 | 2439 | Query 1 1 0 0 | ||
2764 | 2440 | |||
2765 | 2441 | User COUNT(*) Working SUM(Time) MAX(Time) | ||
2766 | 2442 | ------------------------------ -------- ------- --------- --------- | ||
2767 | 2443 | msandbox 2 2 150000 150000 | ||
2768 | 2444 | |||
2769 | 2445 | Host COUNT(*) Working SUM(Time) MAX(Time) | ||
2770 | 2446 | ------------------------------ -------- ------- --------- --------- | ||
2771 | 2447 | localhost 2 2 150000 150000 | ||
2772 | 2448 | |||
2773 | 2449 | db COUNT(*) Working SUM(Time) MAX(Time) | ||
2774 | 2450 | ------------------------------ -------- ------- --------- --------- | ||
2775 | 2451 | NULL 2 2 150000 150000 | ||
2776 | 2452 | |||
2777 | 2453 | State COUNT(*) Working SUM(Time) MAX(Time) | ||
2778 | 2454 | ------------------------------ -------- ------- --------- --------- | ||
2779 | 2455 | Master has sent all binlog to 1 1 150000 150000 | ||
2780 | 2456 | NULL 1 1 0 0 | ||
2781 | 2457 | |||
2782 | 2458 | This section is a summary of the output from SHOW PROCESSLIST. Each sub-section | ||
2783 | 2459 | is aggregated by a different item, which is shown as the first column heading. | ||
2784 | 2460 | When summarized by Command, every row in SHOW PROCESSLIST is included, but | ||
2785 | 2461 | otherwise, rows whose Command is Sleep are excluded from the SUM and MAX | ||
2786 | 2462 | columns, so they do not skew the numbers too much. In the example shown, the | ||
2787 | 2463 | server is idle except for this tool itself, and one connected replica, which | ||
2788 | 2464 | is executing Binlog Dump. | ||
2789 | 2465 | |||
2790 | 2466 | The columns are the number of rows included, the number that are not in Sleep | ||
2791 | 2467 | status, the sum of the Time column, and the maximum Time column. The numbers are | ||
2792 | 2468 | fuzzy-rounded. | ||
2793 | 2469 | |||
2794 | 2470 | # Status Counters (Wait 10 Seconds) ########################## | ||
2795 | 2471 | Variable Per day Per second 10 secs | ||
2796 | 2472 | Binlog_cache_disk_use 4 | ||
2797 | 2473 | Binlog_cache_use 80 | ||
2798 | 2474 | Bytes_received 15000000 175 200 | ||
2799 | 2475 | Bytes_sent 15000000 175 2000 | ||
2800 | 2476 | Com_admin_commands 1 | ||
2801 | 2477 | ...................(many lines omitted)............................ | ||
2802 | 2478 | Threads_created 40 1 | ||
2803 | 2479 | Uptime 90000 1 1 | ||
2804 | 2480 | |||
2805 | 2481 | This section shows selected counters from two snapshots of SHOW GLOBAL STATUS, | ||
2806 | 2482 | gathered approximately 10 seconds apart and fuzzy-rounded. It includes only | ||
2807 | 2483 | items that are incrementing counters; it does not include absolute numbers such | ||
2808 | 2484 | as the Threads_running status variable, which represents a current value, rather | ||
2809 | 2485 | than an accumulated number over time. | ||
2810 | 2486 | |||
2811 | 2487 | The first column is the variable name, and the second column is the counter from | ||
2812 | 2488 | the first snapshot divided by 86400 (the number of seconds in a day), so you can | ||
2813 | 2489 | see the magnitude of the counter's change per day. 86400 fuzzy-rounds to 90000, | ||
2814 | 2490 | so the Uptime counter should always be about 90000. | ||
2815 | 2491 | |||
2816 | 2492 | The third column is the value from the first snapshot, divided by Uptime and | ||
2817 | 2493 | then fuzzy-rounded, so it represents approximately how quickly the counter is | ||
2818 | 2494 | growing per-second over the uptime of the server. | ||
2819 | 2495 | |||
2820 | 2496 | The third column is the incremental difference from the first and second | ||
2821 | 2497 | snapshot, divided by the difference in uptime and then fuzzy-rounded. Therefore, | ||
2822 | 2498 | it shows how quickly the counter is growing per second at the time the report | ||
2823 | 2499 | was generated. | ||
2824 | 2500 | |||
2825 | 2501 | # Table cache ################################################ | ||
2826 | 2502 | Size | 400 | ||
2827 | 2503 | Usage | 15% | ||
2828 | 2504 | |||
2829 | 2505 | This section shows the size of the table cache, followed by the percentage of | ||
2830 | 2506 | the table cache in use. The usage is fuzzy-rounded. | ||
2831 | 2507 | |||
2832 | 2508 | # Key Percona Server features ################################ | ||
2833 | 2509 | Table & Index Stats | Not Supported | ||
2834 | 2510 | Multiple I/O Threads | Enabled | ||
2835 | 2511 | Corruption Resilient | Not Supported | ||
2836 | 2512 | Durable Replication | Not Supported | ||
2837 | 2513 | Import InnoDB Tables | Not Supported | ||
2838 | 2514 | Fast Server Restarts | Not Supported | ||
2839 | 2515 | Enhanced Logging | Not Supported | ||
2840 | 2516 | Replica Perf Logging | Not Supported | ||
2841 | 2517 | Response Time Hist. | Not Supported | ||
2842 | 2518 | Smooth Flushing | Not Supported | ||
2843 | 2519 | HandlerSocket NoSQL | Not Supported | ||
2844 | 2520 | Fast Hash UDFs | Unknown | ||
2845 | 2521 | |||
2846 | 2522 | This section shows features that are available in Percona Server and whether | ||
2847 | 2523 | they are enabled or not. In the example shown, the server is standard MySQL, not | ||
2848 | 2524 | Percona Server, so the features are generally not supported. | ||
2849 | 2525 | |||
2850 | 2526 | # Plugins #################################################### | ||
2851 | 2527 | InnoDB compression | ACTIVE | ||
2852 | 2528 | |||
2853 | 2529 | This feature shows specific plugins and whether they are enabled. | ||
2854 | 2530 | |||
2855 | 2531 | # Query cache ################################################ | ||
2856 | 2532 | query_cache_type | ON | ||
2857 | 2533 | Size | 0.0 | ||
2858 | 2534 | Usage | 0% | ||
2859 | 2535 | HitToInsertRatio | 0% | ||
2860 | 2536 | |||
2861 | 2537 | This section shows whether the query cache is enabled and its size, followed by | ||
2862 | 2538 | the percentage of the cache in use and the hit-to-insert ratio. The latter two | ||
2863 | 2539 | are fuzzy-rounded. | ||
2864 | 2540 | |||
2865 | 2541 | # Schema ##################################################### | ||
2866 | 2542 | Would you like to mysqldump -d the schema and analyze it? y/n y | ||
2867 | 2543 | There are 4 databases. Would you like to dump all, or just one? | ||
2868 | 2544 | Type the name of the database, or press Enter to dump all of them. | ||
2869 | 2545 | |||
2870 | 2546 | Database Tables Views SPs Trigs Funcs FKs Partn | ||
2871 | 2547 | mysql 24 | ||
2872 | 2548 | performance_schema 17 | ||
2873 | 2549 | sakila 16 7 3 6 3 22 | ||
2874 | 2550 | |||
2875 | 2551 | Database MyISAM CSV PERFORMANCE_SCHEMA InnoDB | ||
2876 | 2552 | mysql 22 2 | ||
2877 | 2553 | performance_schema 17 | ||
2878 | 2554 | sakila 8 15 | ||
2879 | 2555 | |||
2880 | 2556 | Database BTREE FULLTEXT | ||
2881 | 2557 | mysql 31 | ||
2882 | 2558 | performance_schema | ||
2883 | 2559 | sakila 63 1 | ||
2884 | 2560 | |||
2885 | 2561 | c t s e l d i t m v s | ||
2886 | 2562 | h i e n o a n i e a m | ||
2887 | 2563 | a m t u n t t n d r a | ||
2888 | 2564 | r e m g e y i c l | ||
2889 | 2565 | s b t i u h l | ||
2890 | 2566 | t l i n m a i | ||
2891 | 2567 | a o m t t r n | ||
2892 | 2568 | m b e e t | ||
2893 | 2569 | p x | ||
2894 | 2570 | t | ||
2895 | 2571 | Database === === === === === === === === === === === | ||
2896 | 2572 | mysql 61 10 6 78 5 4 26 3 4 5 3 | ||
2897 | 2573 | performance_schema 5 16 33 | ||
2898 | 2574 | sakila 1 15 1 3 4 3 19 42 26 | ||
2899 | 2575 | |||
2900 | 2576 | If you select to dump the schema and analyze it, the tool will print the above | ||
2901 | 2577 | section. This summarizes the number and type of objects in the database. It is | ||
2902 | 2578 | generated by running C<mysqldump --no-data>, not by querying the | ||
2903 | 2579 | INFORMATION_SCHEMA, which can freeze a busy server. You can use the | ||
2904 | 2580 | L<"--databases"> option to specify which databases to examine. If you do not, | ||
2905 | 2581 | and you run the tool interactively, it will prompt you as shown. | ||
2906 | 2582 | |||
2907 | 2583 | You can choose not to dump the schema, to dump all of the databases, or to dump | ||
2908 | 2584 | only a single named one, by specifying the appropriate options. In the example | ||
2909 | 2585 | above, we are dumping all databases. | ||
2910 | 2586 | |||
2911 | 2587 | The first sub-report in the section is the count of objects by type in each | ||
2912 | 2588 | database: tables, views, and so on. The second one shows how many tables use | ||
2913 | 2589 | various storage engines in each database. The third sub-report shows the number | ||
2914 | 2590 | of each type of indexes in each database. | ||
2915 | 2591 | |||
2916 | 2592 | The last section shows the number of columns of various data types in each | ||
2917 | 2593 | database. For compact display, the column headers are formatted vertically, so | ||
2918 | 2594 | you need to read downwards from the top. In this example, the first column is | ||
2919 | 2595 | C<char> and the second column is C<timestamp>. This example is truncated so it | ||
2920 | 2596 | does not wrap on a terminal. | ||
2921 | 2597 | |||
2922 | 2598 | All of the numbers in this portion of the output are exact, not fuzzy-rounded. | ||
2923 | 2599 | |||
2924 | 2600 | # Noteworthy Technologies #################################### | ||
2925 | 2601 | Full Text Indexing | Yes | ||
2926 | 2602 | Geospatial Types | No | ||
2927 | 2603 | Foreign Keys | Yes | ||
2928 | 2604 | Partitioning | No | ||
2929 | 2605 | InnoDB Compression | Yes | ||
2930 | 2606 | SSL | No | ||
2931 | 2607 | Explicit LOCK TABLES | No | ||
2932 | 2608 | Delayed Insert | No | ||
2933 | 2609 | XA Transactions | No | ||
2934 | 2610 | NDB Cluster | No | ||
2935 | 2611 | Prepared Statements | No | ||
2936 | 2612 | Prepared statement count | 0 | ||
2937 | 2613 | |||
2938 | 2614 | This section shows some specific technologies used on this server. Some of them | ||
2939 | 2615 | are detected from the schema dump performed for the previous sections; others | ||
2940 | 2616 | can be detected by looking at SHOW GLOBAL STATUS. | ||
2941 | 2617 | |||
2942 | 2618 | # InnoDB ##################################################### | ||
2943 | 2619 | Version | 1.1.8 | ||
2944 | 2620 | Buffer Pool Size | 16.0M | ||
2945 | 2621 | Buffer Pool Fill | 100% | ||
2946 | 2622 | Buffer Pool Dirty | 0% | ||
2947 | 2623 | File Per Table | OFF | ||
2948 | 2624 | Page Size | 16k | ||
2949 | 2625 | Log File Size | 2 * 5.0M = 10.0M | ||
2950 | 2626 | Log Buffer Size | 8M | ||
2951 | 2627 | Flush Method | | ||
2952 | 2628 | Flush Log At Commit | 1 | ||
2953 | 2629 | XA Support | ON | ||
2954 | 2630 | Checksums | ON | ||
2955 | 2631 | Doublewrite | ON | ||
2956 | 2632 | R/W I/O Threads | 4 4 | ||
2957 | 2633 | I/O Capacity | 200 | ||
2958 | 2634 | Thread Concurrency | 0 | ||
2959 | 2635 | Concurrency Tickets | 500 | ||
2960 | 2636 | Commit Concurrency | 0 | ||
2961 | 2637 | Txn Isolation Level | REPEATABLE-READ | ||
2962 | 2638 | Adaptive Flushing | ON | ||
2963 | 2639 | Adaptive Checkpoint | | ||
2964 | 2640 | Checkpoint Age | 0 | ||
2965 | 2641 | InnoDB Queue | 0 queries inside InnoDB, 0 queries in queue | ||
2966 | 2642 | Oldest Transaction | 0 Seconds | ||
2967 | 2643 | History List Len | 209 | ||
2968 | 2644 | Read Views | 1 | ||
2969 | 2645 | Undo Log Entries | 1 transactions, 1 total undo, 1 max undo | ||
2970 | 2646 | Pending I/O Reads | 0 buf pool reads, 0 normal AIO, | ||
2971 | 2647 | 0 ibuf AIO, 0 preads | ||
2972 | 2648 | Pending I/O Writes | 0 buf pool (0 LRU, 0 flush list, 0 page); | ||
2973 | 2649 | 0 AIO, 0 sync, 0 log IO (0 log, 0 chkp); | ||
2974 | 2650 | 0 pwrites | ||
2975 | 2651 | Pending I/O Flushes | 0 buf pool, 0 log | ||
2976 | 2652 | Transaction States | 1xnot started | ||
2977 | 2653 | |||
2978 | 2654 | This section shows important configuration variables for the InnoDB storage | ||
2979 | 2655 | engine. The buffer pool fill percent and dirty percent are fuzzy-rounded. The | ||
2980 | 2656 | last few lines are derived from the output of SHOW INNODB STATUS. It is likely | ||
2981 | 2657 | that this output will change in the future to become more useful. | ||
2982 | 2658 | |||
2983 | 2659 | # MyISAM ##################################################### | ||
2984 | 2660 | Key Cache | 16.0M | ||
2985 | 2661 | Pct Used | 10% | ||
2986 | 2662 | Unflushed | 0% | ||
2987 | 2663 | |||
2988 | 2664 | This section shows the size of the MyISAM key cache, followed by the percentage | ||
2989 | 2665 | of the cache in use and percentage unflushed (fuzzy-rounded). | ||
2990 | 2666 | |||
2991 | 2667 | # Security ################################################### | ||
2992 | 2668 | Users | 2 users, 0 anon, 0 w/o pw, 0 old pw | ||
2993 | 2669 | Old Passwords | OFF | ||
2994 | 2670 | |||
2995 | 2671 | This section is generated from queries to tables in the mysql system database. | ||
2996 | 2672 | It shows how many users exist, and various potential security risks such as | ||
2997 | 2673 | old-style passwords and users without passwords. | ||
2998 | 2674 | |||
2999 | 2675 | # Binary Logging ############################################# | ||
3000 | 2676 | Binlogs | 1 | ||
3001 | 2677 | Zero-Sized | 0 | ||
3002 | 2678 | Total Size | 21.8M | ||
3003 | 2679 | binlog_format | STATEMENT | ||
3004 | 2680 | expire_logs_days | 0 | ||
3005 | 2681 | sync_binlog | 0 | ||
3006 | 2682 | server_id | 12345 | ||
3007 | 2683 | binlog_do_db | | ||
3008 | 2684 | binlog_ignore_db | | ||
3009 | 2685 | |||
3010 | 2686 | This section shows configuration and status of the binary logs. If there are | ||
3011 | 2687 | zero-sized binary logs, then it is possible that the binlog index is out of sync | ||
3012 | 2688 | with the binary logs that actually exist on disk. | ||
3013 | 2689 | |||
3014 | 2690 | # Noteworthy Variables ####################################### | ||
3015 | 2691 | Auto-Inc Incr/Offset | 1/1 | ||
3016 | 2692 | default_storage_engine | InnoDB | ||
3017 | 2693 | flush_time | 0 | ||
3018 | 2694 | init_connect | | ||
3019 | 2695 | init_file | | ||
3020 | 2696 | sql_mode | | ||
3021 | 2697 | join_buffer_size | 128k | ||
3022 | 2698 | sort_buffer_size | 2M | ||
3023 | 2699 | read_buffer_size | 128k | ||
3024 | 2700 | read_rnd_buffer_size | 256k | ||
3025 | 2701 | bulk_insert_buffer | 0.00 | ||
3026 | 2702 | max_heap_table_size | 16M | ||
3027 | 2703 | tmp_table_size | 16M | ||
3028 | 2704 | max_allowed_packet | 1M | ||
3029 | 2705 | thread_stack | 192k | ||
3030 | 2706 | log | OFF | ||
3031 | 2707 | log_error | /tmp/12345/data/mysqld.log | ||
3032 | 2708 | log_warnings | 1 | ||
3033 | 2709 | log_slow_queries | ON | ||
3034 | 2710 | log_queries_not_using_indexes | OFF | ||
3035 | 2711 | log_slave_updates | ON | ||
3036 | 2712 | |||
3037 | 2713 | This section shows several noteworthy server configuration variables that might | ||
3038 | 2714 | be important to know about when working with this server. | ||
3039 | 2715 | |||
3040 | 2716 | # Configuration File ######################################### | ||
3041 | 2717 | Config File | /tmp/12345/my.sandbox.cnf | ||
3042 | 2718 | [client] | ||
3043 | 2719 | user = msandbox | ||
3044 | 2720 | password = msandbox | ||
3045 | 2721 | port = 12345 | ||
3046 | 2722 | socket = /tmp/12345/mysql_sandbox12345.sock | ||
3047 | 2723 | [mysqld] | ||
3048 | 2724 | port = 12345 | ||
3049 | 2725 | socket = /tmp/12345/mysql_sandbox12345.sock | ||
3050 | 2726 | pid-file = /tmp/12345/data/mysql_sandbox12345.pid | ||
3051 | 2727 | basedir = /home/baron/5.5.20 | ||
3052 | 2728 | datadir = /tmp/12345/data | ||
3053 | 2729 | key_buffer_size = 16M | ||
3054 | 2730 | innodb_buffer_pool_size = 16M | ||
3055 | 2731 | innodb_data_home_dir = /tmp/12345/data | ||
3056 | 2732 | innodb_log_group_home_dir = /tmp/12345/data | ||
3057 | 2733 | innodb_data_file_path = ibdata1:10M:autoextend | ||
3058 | 2734 | innodb_log_file_size = 5M | ||
3059 | 2735 | log-bin = mysql-bin | ||
3060 | 2736 | relay_log = mysql-relay-bin | ||
3061 | 2737 | log_slave_updates | ||
3062 | 2738 | server-id = 12345 | ||
3063 | 2739 | report-host = 127.0.0.1 | ||
3064 | 2740 | report-port = 12345 | ||
3065 | 2741 | log-error = mysqld.log | ||
3066 | 2742 | innodb_lock_wait_timeout = 3 | ||
3067 | 2743 | # The End #################################################### | ||
3068 | 2744 | |||
3069 | 2745 | This section shows a pretty-printed version of the my.cnf file, with comments | ||
3070 | 2746 | removed and with whitespace added to align things for easy reading. The tool | ||
3071 | 2747 | tries to detect the my.cnf file by looking at the output of ps, and if it does | ||
3072 | 2748 | not find the location of the file there, it tries common locations until it | ||
3073 | 2749 | finds a file. Note that this file might not actually correspond with the server | ||
3074 | 2750 | from which the report was generated. This can happen when the tool isn't run on | ||
3075 | 2751 | the same server it's reporting on, or when detecting the location of the | ||
3076 | 2752 | configuration file fails. | ||
3077 | 2753 | |||
3078 | 1400 | =head1 OPTIONS | 2754 | =head1 OPTIONS |
3079 | 1401 | 2755 | ||
3082 | 1402 | This tool does not have any command-line options of its own. All options | 2756 | All options after -- are passed to C<mysql>. |
3083 | 1403 | are passed to C<mysql>. | 2757 | |
3084 | 2758 | =over | ||
3085 | 2759 | |||
3086 | 2760 | =item --config | ||
3087 | 2761 | |||
3088 | 2762 | type: string | ||
3089 | 2763 | |||
3090 | 2764 | Read this comma-separated list of config files. If specified, this must be the | ||
3091 | 2765 | first option on the command line. | ||
3092 | 2766 | |||
3093 | 2767 | =item --help | ||
3094 | 2768 | |||
3095 | 2769 | Print help and exit. | ||
3096 | 2770 | |||
3097 | 2771 | =item --save-samples | ||
3098 | 2772 | |||
3099 | 2773 | type: string | ||
3100 | 2774 | |||
3101 | 2775 | Save the data files used to generate the summary in this directory. | ||
3102 | 2776 | |||
3103 | 2777 | =item --read-samples | ||
3104 | 2778 | |||
3105 | 2779 | type: string | ||
3106 | 2780 | |||
3107 | 2781 | Create a report from the files found in this directory. | ||
3108 | 2782 | |||
3109 | 2783 | =item --databases | ||
3110 | 2784 | |||
3111 | 2785 | type: string | ||
3112 | 2786 | |||
3113 | 2787 | Names of databases to summarize. If you want all of them, you can use the value | ||
3114 | 2788 | C<--all-databases>; you can also pass in a comma-separated list of database | ||
3115 | 2789 | names. If not provided, the program will ask you for manual input. | ||
3116 | 2790 | |||
3117 | 2791 | =item --sleep | ||
3118 | 2792 | |||
3119 | 2793 | type: int; default: 10 | ||
3120 | 2794 | |||
3121 | 2795 | Seconds to sleep when gathering status counters. | ||
3122 | 2796 | |||
3123 | 2797 | =item --version | ||
3124 | 2798 | |||
3125 | 2799 | Print tool's version and exit. | ||
3126 | 2800 | |||
3127 | 2801 | =back | ||
3128 | 1404 | 2802 | ||
3129 | 1405 | =head1 ENVIRONMENT | 2803 | =head1 ENVIRONMENT |
3130 | 1406 | 2804 | ||
3131 | @@ -1408,7 +2806,9 @@ | |||
3132 | 1408 | 2806 | ||
3133 | 1409 | =head1 SYSTEM REQUIREMENTS | 2807 | =head1 SYSTEM REQUIREMENTS |
3134 | 1410 | 2808 | ||
3136 | 1411 | This tool requires Bash v3 or newer. | 2809 | This tool requires Bash v3 or newer, Perl 5.8 or newer, and binutils. |
3137 | 2810 | These are generally already provided by most distributions. | ||
3138 | 2811 | On BSD systems, it may require a mounted procfs. | ||
3139 | 1412 | 2812 | ||
3140 | 1413 | =head1 BUGS | 2813 | =head1 BUGS |
3141 | 1414 | 2814 | ||
3142 | @@ -1454,7 +2854,7 @@ | |||
3143 | 1454 | 2854 | ||
3144 | 1455 | =head1 AUTHORS | 2855 | =head1 AUTHORS |
3145 | 1456 | 2856 | ||
3147 | 1457 | Baron Schwartz | 2857 | Baron Schwartz, Brian Fraser, and Daniel Nichter. |
3148 | 1458 | 2858 | ||
3149 | 1459 | =head1 ABOUT PERCONA TOOLKIT | 2859 | =head1 ABOUT PERCONA TOOLKIT |
3150 | 1460 | 2860 | ||
3151 | @@ -1467,7 +2867,7 @@ | |||
3152 | 1467 | 2867 | ||
3153 | 1468 | =head1 COPYRIGHT, LICENSE, AND WARRANTY | 2868 | =head1 COPYRIGHT, LICENSE, AND WARRANTY |
3154 | 1469 | 2869 | ||
3156 | 1470 | This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. | 2870 | This program is copyright 2010-2011 Baron Schwartz, 2011 Percona Inc. |
3157 | 1471 | Feedback and improvements are welcome. | 2871 | Feedback and improvements are welcome. |
3158 | 1472 | 2872 | ||
3159 | 1473 | THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED | 2873 | THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED |
3160 | 1474 | 2874 | ||
3161 | === modified file 'bin/pt-summary' | |||
3162 | --- bin/pt-summary 2012-03-07 23:41:54 +0000 | |||
3163 | +++ bin/pt-summary 2012-04-03 15:57:31 +0000 | |||
3164 | @@ -4,45 +4,428 @@ | |||
3165 | 4 | # See "COPYRIGHT, LICENSE, AND WARRANTY" at the end of this file for legal | 4 | # See "COPYRIGHT, LICENSE, AND WARRANTY" at the end of this file for legal |
3166 | 5 | # notices and disclaimers. | 5 | # notices and disclaimers. |
3167 | 6 | 6 | ||
3168 | 7 | set -u | ||
3169 | 8 | |||
3170 | 7 | # ######################################################################## | 9 | # ######################################################################## |
3171 | 8 | # Globals, settings, helper functions | 10 | # Globals, settings, helper functions |
3172 | 9 | # ######################################################################## | 11 | # ######################################################################## |
3173 | 12 | TOOL="pt-summary" | ||
3174 | 10 | POSIXLY_CORRECT=1 | 13 | POSIXLY_CORRECT=1 |
3175 | 11 | export POSIXLY_CORRECT | 14 | export POSIXLY_CORRECT |
3176 | 12 | 15 | ||
3210 | 13 | # The awk code for fuzzy rounding. (It's used in a few places, so makes sense | 16 | # ########################################################################### |
3211 | 14 | # not to duplicate). It fuzzy-rounds the variable named fuzzy_var. It goes in | 17 | # log_warn_die package |
3212 | 15 | # steps of 5, 10, 25, then repeats by a factor of 10 larger (50, 100, 250), and | 18 | # This package is a copy without comments from the original. The original |
3213 | 16 | # so on, until it finds a number that's large enough. The pattern is slightly | 19 | # with comments and its test file can be found in the Bazaar repository at, |
3214 | 17 | # broken between the initial 1 and 50, because rounding to the nearest 2.5 | 20 | # lib/bash/log_warn_die.sh |
3215 | 18 | # doesn't seem right to me. | 21 | # t/lib/bash/log_warn_die.sh |
3216 | 19 | fuzzy_formula=' | 22 | # See https://launchpad.net/percona-toolkit for more information. |
3217 | 20 | rounded = 0; | 23 | # ########################################################################### |
3218 | 21 | if (fuzzy_var <= 10 ) { | 24 | |
3219 | 22 | rounded = 1; | 25 | |
3220 | 23 | } | 26 | set -u |
3221 | 24 | factor = 1; | 27 | |
3222 | 25 | while ( rounded == 0 ) { | 28 | PTFUNCNAME="" |
3223 | 26 | if ( fuzzy_var <= 50 * factor ) { | 29 | PTDEBUG="${PTDEBUG:-""}" |
3224 | 27 | fuzzy_var = sprintf("%.0f", fuzzy_var / (5 * factor)) * 5 * factor; | 30 | EXIT_STATUS=0 |
3225 | 28 | rounded = 1; | 31 | |
3226 | 29 | } | 32 | log() { |
3227 | 30 | else if ( fuzzy_var <= 100 * factor) { | 33 | TS=$(date +%F-%T | tr :- _); |
3228 | 31 | fuzzy_var = sprintf("%.0f", fuzzy_var / (10 * factor)) * 10 * factor; | 34 | echo "$TS $*" |
3229 | 32 | rounded = 1; | 35 | } |
3230 | 33 | } | 36 | |
3231 | 34 | else if ( fuzzy_var <= 250 * factor) { | 37 | warn() { |
3232 | 35 | fuzzy_var = sprintf("%.0f", fuzzy_var / (25 * factor)) * 25 * factor; | 38 | log "$*" >&2 |
3233 | 36 | rounded = 1; | 39 | EXIT_STATUS=1 |
3234 | 37 | } | 40 | } |
3235 | 38 | factor = factor * 10; | 41 | |
3236 | 39 | }' | 42 | die() { |
3237 | 40 | 43 | warn "$*" | |
3238 | 41 | # Does fuzzy rounding: rounds to nearest interval, but the interval gets larger | 44 | exit 1 |
3239 | 42 | # as the number gets larger. This is to make things easier to diff. | 45 | } |
3240 | 43 | fuzz () { | 46 | |
3241 | 44 | echo $1 | $AP_AWK "{fuzzy_var=\$1; ${fuzzy_formula} print fuzzy_var;}" | 47 | _d () { |
3242 | 45 | } | 48 | [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(log "$*")" >&2 |
3243 | 49 | } | ||
3244 | 50 | |||
3245 | 51 | # ########################################################################### | ||
3246 | 52 | # End log_warn_die package | ||
3247 | 53 | # ########################################################################### | ||
3248 | 54 | |||
3249 | 55 | # ########################################################################### | ||
3250 | 56 | # parse_options package | ||
3251 | 57 | # This package is a copy without comments from the original. The original | ||
3252 | 58 | # with comments and its test file can be found in the Bazaar repository at, | ||
3253 | 59 | # lib/bash/parse_options.sh | ||
3254 | 60 | # t/lib/bash/parse_options.sh | ||
3255 | 61 | # See https://launchpad.net/percona-toolkit for more information. | ||
3256 | 62 | # ########################################################################### | ||
3257 | 63 | |||
3258 | 64 | |||
3259 | 65 | |||
3260 | 66 | |||
3261 | 67 | |||
3262 | 68 | set -u | ||
3263 | 69 | |||
3264 | 70 | ARGV="" # Non-option args (probably input files) | ||
3265 | 71 | EXT_ARGV="" # Everything after -- (args for an external command) | ||
3266 | 72 | HAVE_EXT_ARGV="" # Got --, everything else is put into EXT_ARGV | ||
3267 | 73 | OPT_ERRS=0 # How many command line option errors | ||
3268 | 74 | OPT_VERSION="" # If --version was specified | ||
3269 | 75 | OPT_HELP="" # If --help was specified | ||
3270 | 76 | PO_DIR="" # Directory with program option spec files | ||
3271 | 77 | |||
3272 | 78 | usage() { | ||
3273 | 79 | local file="$1" | ||
3274 | 80 | |||
3275 | 81 | local usage=$(grep '^Usage: ' "$file") | ||
3276 | 82 | echo $usage | ||
3277 | 83 | echo | ||
3278 | 84 | echo "For more information, 'man $TOOL' or 'perldoc $file'." | ||
3279 | 85 | } | ||
3280 | 86 | |||
3281 | 87 | usage_or_errors() { | ||
3282 | 88 | local file="$1" | ||
3283 | 89 | |||
3284 | 90 | if [ "$OPT_VERSION" ]; then | ||
3285 | 91 | local version=$(grep '^pt-[^ ]\+ [0-9]' "$file") | ||
3286 | 92 | echo "$version" | ||
3287 | 93 | return 1 | ||
3288 | 94 | fi | ||
3289 | 95 | |||
3290 | 96 | if [ "$OPT_HELP" ]; then | ||
3291 | 97 | usage "$file" | ||
3292 | 98 | echo | ||
3293 | 99 | echo "Command line options:" | ||
3294 | 100 | echo | ||
3295 | 101 | perl -e ' | ||
3296 | 102 | use strict; | ||
3297 | 103 | use warnings FATAL => qw(all); | ||
3298 | 104 | my $lcol = 20; # Allow this much space for option names. | ||
3299 | 105 | my $rcol = 80 - $lcol; # The terminal is assumed to be 80 chars wide. | ||
3300 | 106 | my $name; | ||
3301 | 107 | while ( <> ) { | ||
3302 | 108 | my $line = $_; | ||
3303 | 109 | chomp $line; | ||
3304 | 110 | if ( $line =~ s/^long:/ --/ ) { | ||
3305 | 111 | $name = $line; | ||
3306 | 112 | } | ||
3307 | 113 | elsif ( $line =~ s/^desc:// ) { | ||
3308 | 114 | $line =~ s/ +$//mg; | ||
3309 | 115 | my @lines = grep { $_ } | ||
3310 | 116 | $line =~ m/(.{0,$rcol})(?:\s+|\Z)/g; | ||
3311 | 117 | if ( length($name) >= $lcol ) { | ||
3312 | 118 | print $name, "\n", (q{ } x $lcol); | ||
3313 | 119 | } | ||
3314 | 120 | else { | ||
3315 | 121 | printf "%-${lcol}s", $name; | ||
3316 | 122 | } | ||
3317 | 123 | print join("\n" . (q{ } x $lcol), @lines); | ||
3318 | 124 | print "\n"; | ||
3319 | 125 | } | ||
3320 | 126 | } | ||
3321 | 127 | ' "$PO_DIR"/* | ||
3322 | 128 | echo | ||
3323 | 129 | echo "Options and values after processing arguments:" | ||
3324 | 130 | echo | ||
3325 | 131 | for opt in $(ls "$PO_DIR"); do | ||
3326 | 132 | local varname="OPT_$(echo "$opt" | tr a-z- A-Z_)" | ||
3327 | 133 | local varvalue="${!varname}" | ||
3328 | 134 | printf -- " --%-30s %s" "$opt" "${varvalue:-(No value)}" | ||
3329 | 135 | echo | ||
3330 | 136 | done | ||
3331 | 137 | return 1 | ||
3332 | 138 | fi | ||
3333 | 139 | |||
3334 | 140 | if [ $OPT_ERRS -gt 0 ]; then | ||
3335 | 141 | echo | ||
3336 | 142 | usage "$file" | ||
3337 | 143 | return 1 | ||
3338 | 144 | fi | ||
3339 | 145 | |||
3340 | 146 | return 0 | ||
3341 | 147 | } | ||
3342 | 148 | |||
3343 | 149 | option_error() { | ||
3344 | 150 | local err="$1" | ||
3345 | 151 | OPT_ERRS=$(($OPT_ERRS + 1)) | ||
3346 | 152 | echo "$err" >&2 | ||
3347 | 153 | } | ||
3348 | 154 | |||
3349 | 155 | parse_options() { | ||
3350 | 156 | local file="$1" | ||
3351 | 157 | shift | ||
3352 | 158 | |||
3353 | 159 | ARGV="" | ||
3354 | 160 | EXT_ARGV="" | ||
3355 | 161 | HAVE_EXT_ARGV="" | ||
3356 | 162 | OPT_ERRS=0 | ||
3357 | 163 | OPT_VERSION="" | ||
3358 | 164 | OPT_HELP="" | ||
3359 | 165 | PO_DIR="$TMPDIR/po" | ||
3360 | 166 | |||
3361 | 167 | if [ ! -d "$PO_DIR" ]; then | ||
3362 | 168 | mkdir "$PO_DIR" | ||
3363 | 169 | if [ $? -ne 0 ]; then | ||
3364 | 170 | echo "Cannot mkdir $PO_DIR" >&2 | ||
3365 | 171 | exit 1 | ||
3366 | 172 | fi | ||
3367 | 173 | fi | ||
3368 | 174 | |||
3369 | 175 | rm -rf "$PO_DIR"/* | ||
3370 | 176 | if [ $? -ne 0 ]; then | ||
3371 | 177 | echo "Cannot rm -rf $PO_DIR/*" >&2 | ||
3372 | 178 | exit 1 | ||
3373 | 179 | fi | ||
3374 | 180 | |||
3375 | 181 | _parse_pod "$file" # Parse POD into program option (po) spec files | ||
3376 | 182 | _eval_po # Eval po into existence with default values | ||
3377 | 183 | |||
3378 | 184 | if [ $# -ge 2 ] && [ "$1" = "--config" ]; then | ||
3379 | 185 | shift # --config | ||
3380 | 186 | local user_config_files="$1" | ||
3381 | 187 | shift # that ^ | ||
3382 | 188 | local IFS="," | ||
3383 | 189 | for user_config_file in $user_config_files; do | ||
3384 | 190 | _parse_config_files "$user_config_file" | ||
3385 | 191 | done | ||
3386 | 192 | else | ||
3387 | 193 | _parse_config_files "/etc/percona-toolkit/percona-toolkit.conf" "/etc/percona-toolkit/$TOOL.conf" "$HOME/.percona-toolkit.conf" "$HOME/.$TOOL.conf" | ||
3388 | 194 | fi | ||
3389 | 195 | |||
3390 | 196 | _parse_command_line "$@" | ||
3391 | 197 | } | ||
3392 | 198 | |||
3393 | 199 | _parse_pod() { | ||
3394 | 200 | local file="$1" | ||
3395 | 201 | |||
3396 | 202 | cat "$file" | PO_DIR="$PO_DIR" perl -ne ' | ||
3397 | 203 | BEGIN { $/ = ""; } | ||
3398 | 204 | next unless $_ =~ m/^=head1 OPTIONS/; | ||
3399 | 205 | while ( defined(my $para = <>) ) { | ||
3400 | 206 | last if $para =~ m/^=head1/; | ||
3401 | 207 | chomp; | ||
3402 | 208 | if ( $para =~ m/^=item --(\S+)/ ) { | ||
3403 | 209 | my $opt = $1; | ||
3404 | 210 | my $file = "$ENV{PO_DIR}/$opt"; | ||
3405 | 211 | open my $opt_fh, ">", $file or die "Cannot open $file: $!"; | ||
3406 | 212 | print $opt_fh "long:$opt\n"; | ||
3407 | 213 | $para = <>; | ||
3408 | 214 | chomp; | ||
3409 | 215 | if ( $para =~ m/^[a-z ]+:/ ) { | ||
3410 | 216 | map { | ||
3411 | 217 | chomp; | ||
3412 | 218 | my ($attrib, $val) = split(/: /, $_); | ||
3413 | 219 | print $opt_fh "$attrib:$val\n"; | ||
3414 | 220 | } split(/; /, $para); | ||
3415 | 221 | $para = <>; | ||
3416 | 222 | chomp; | ||
3417 | 223 | } | ||
3418 | 224 | my ($desc) = $para =~ m/^([^?.]+)/; | ||
3419 | 225 | print $opt_fh "desc:$desc.\n"; | ||
3420 | 226 | close $opt_fh; | ||
3421 | 227 | } | ||
3422 | 228 | } | ||
3423 | 229 | last; | ||
3424 | 230 | ' | ||
3425 | 231 | } | ||
3426 | 232 | |||
3427 | 233 | _eval_po() { | ||
3428 | 234 | local IFS=":" | ||
3429 | 235 | for opt_spec in "$PO_DIR"/*; do | ||
3430 | 236 | local opt="" | ||
3431 | 237 | local default_val="" | ||
3432 | 238 | local neg=0 | ||
3433 | 239 | local size=0 | ||
3434 | 240 | while read key val; do | ||
3435 | 241 | case "$key" in | ||
3436 | 242 | long) | ||
3437 | 243 | opt=$(echo $val | sed 's/-/_/g' | tr [:lower:] [:upper:]) | ||
3438 | 244 | ;; | ||
3439 | 245 | default) | ||
3440 | 246 | default_val="$val" | ||
3441 | 247 | ;; | ||
3442 | 248 | "short form") | ||
3443 | 249 | ;; | ||
3444 | 250 | type) | ||
3445 | 251 | [ "$val" = "size" ] && size=1 | ||
3446 | 252 | ;; | ||
3447 | 253 | desc) | ||
3448 | 254 | ;; | ||
3449 | 255 | negatable) | ||
3450 | 256 | if [ "$val" = "yes" ]; then | ||
3451 | 257 | neg=1 | ||
3452 | 258 | fi | ||
3453 | 259 | ;; | ||
3454 | 260 | *) | ||
3455 | 261 | echo "Invalid attribute in $opt_spec: $line" >&2 | ||
3456 | 262 | exit 1 | ||
3457 | 263 | esac | ||
3458 | 264 | done < "$opt_spec" | ||
3459 | 265 | |||
3460 | 266 | if [ -z "$opt" ]; then | ||
3461 | 267 | echo "No long attribute in option spec $opt_spec" >&2 | ||
3462 | 268 | exit 1 | ||
3463 | 269 | fi | ||
3464 | 270 | |||
3465 | 271 | if [ $neg -eq 1 ]; then | ||
3466 | 272 | if [ -z "$default_val" ] || [ "$default_val" != "yes" ]; then | ||
3467 | 273 | echo "Option $opt_spec is negatable but not default: yes" >&2 | ||
3468 | 274 | exit 1 | ||
3469 | 275 | fi | ||
3470 | 276 | fi | ||
3471 | 277 | |||
3472 | 278 | if [ $size -eq 1 -a -n "$default_val" ]; then | ||
3473 | 279 | default_val=$(size_to_bytes $default_val) | ||
3474 | 280 | fi | ||
3475 | 281 | |||
3476 | 282 | eval "OPT_${opt}"="$default_val" | ||
3477 | 283 | done | ||
3478 | 284 | } | ||
3479 | 285 | |||
3480 | 286 | _parse_config_files() { | ||
3481 | 287 | |||
3482 | 288 | for config_file in "$@"; do | ||
3483 | 289 | test -f "$config_file" || continue | ||
3484 | 290 | |||
3485 | 291 | while read config_opt; do | ||
3486 | 292 | |||
3487 | 293 | echo "$config_opt" | grep '^[ ]*[^#]' >/dev/null 2>&1 || continue | ||
3488 | 294 | |||
3489 | 295 | config_opt="$(echo "$config_opt" | sed -e 's/^ *//g' -e 's/ *$//g' -e 's/[ ]*=[ ]*/=/' -e 's/[ ]*#.*$//')" | ||
3490 | 296 | |||
3491 | 297 | [ "$config_opt" = "" ] && continue | ||
3492 | 298 | |||
3493 | 299 | if ! [ "$HAVE_EXT_ARGV" ]; then | ||
3494 | 300 | config_opt="--$config_opt" | ||
3495 | 301 | fi | ||
3496 | 302 | |||
3497 | 303 | _parse_command_line "$config_opt" | ||
3498 | 304 | |||
3499 | 305 | done < "$config_file" | ||
3500 | 306 | |||
3501 | 307 | HAVE_EXT_ARGV="" # reset for each file | ||
3502 | 308 | |||
3503 | 309 | done | ||
3504 | 310 | } | ||
3505 | 311 | |||
3506 | 312 | _parse_command_line() { | ||
3507 | 313 | local opt="" | ||
3508 | 314 | local val="" | ||
3509 | 315 | local next_opt_is_val="" | ||
3510 | 316 | local opt_is_ok="" | ||
3511 | 317 | local opt_is_negated="" | ||
3512 | 318 | local real_opt="" | ||
3513 | 319 | local required_arg="" | ||
3514 | 320 | local spec="" | ||
3515 | 321 | |||
3516 | 322 | for opt in "$@"; do | ||
3517 | 323 | if [ "$opt" = "--" -o "$opt" = "----" ]; then | ||
3518 | 324 | HAVE_EXT_ARGV=1 | ||
3519 | 325 | continue | ||
3520 | 326 | fi | ||
3521 | 327 | if [ "$HAVE_EXT_ARGV" ]; then | ||
3522 | 328 | if [ "$EXT_ARGV" ]; then | ||
3523 | 329 | EXT_ARGV="$EXT_ARGV $opt" | ||
3524 | 330 | else | ||
3525 | 331 | EXT_ARGV="$opt" | ||
3526 | 332 | fi | ||
3527 | 333 | continue | ||
3528 | 334 | fi | ||
3529 | 335 | |||
3530 | 336 | if [ "$next_opt_is_val" ]; then | ||
3531 | 337 | next_opt_is_val="" | ||
3532 | 338 | if [ $# -eq 0 ] || [ $(expr "$opt" : "-") -eq 1 ]; then | ||
3533 | 339 | option_error "$real_opt requires a $required_arg argument" | ||
3534 | 340 | continue | ||
3535 | 341 | fi | ||
3536 | 342 | val="$opt" | ||
3537 | 343 | opt_is_ok=1 | ||
3538 | 344 | else | ||
3539 | 345 | if [ $(expr "$opt" : "-") -eq 0 ]; then | ||
3540 | 346 | if [ -z "$ARGV" ]; then | ||
3541 | 347 | ARGV="$opt" | ||
3542 | 348 | else | ||
3543 | 349 | ARGV="$ARGV $opt" | ||
3544 | 350 | fi | ||
3545 | 351 | continue | ||
3546 | 352 | fi | ||
3547 | 353 | |||
3548 | 354 | real_opt="$opt" | ||
3549 | 355 | |||
3550 | 356 | if $(echo $opt | grep '^--no-' >/dev/null); then | ||
3551 | 357 | opt_is_negated=1 | ||
3552 | 358 | opt=$(echo $opt | sed 's/^--no-//') | ||
3553 | 359 | else | ||
3554 | 360 | opt_is_negated="" | ||
3555 | 361 | opt=$(echo $opt | sed 's/^-*//') | ||
3556 | 362 | fi | ||
3557 | 363 | |||
3558 | 364 | if $(echo $opt | grep '^[a-z-][a-z-]*=' >/dev/null 2>&1); then | ||
3559 | 365 | val="$(echo $opt | awk -F= '{print $2}')" | ||
3560 | 366 | opt="$(echo $opt | awk -F= '{print $1}')" | ||
3561 | 367 | fi | ||
3562 | 368 | |||
3563 | 369 | if [ -f "$TMPDIR/po/$opt" ]; then | ||
3564 | 370 | spec="$TMPDIR/po/$opt" | ||
3565 | 371 | else | ||
3566 | 372 | spec=$(grep "^short form:-$opt\$" "$TMPDIR"/po/* | cut -d ':' -f 1) | ||
3567 | 373 | if [ -z "$spec" ]; then | ||
3568 | 374 | option_error "Unknown option: $real_opt" | ||
3569 | 375 | continue | ||
3570 | 376 | fi | ||
3571 | 377 | fi | ||
3572 | 378 | |||
3573 | 379 | required_arg=$(cat "$spec" | awk -F: '/^type:/{print $2}') | ||
3574 | 380 | if [ "$required_arg" ]; then | ||
3575 | 381 | if [ "$val" ]; then | ||
3576 | 382 | opt_is_ok=1 | ||
3577 | 383 | else | ||
3578 | 384 | next_opt_is_val=1 | ||
3579 | 385 | fi | ||
3580 | 386 | else | ||
3581 | 387 | if [ "$val" ]; then | ||
3582 | 388 | option_error "Option $real_opt does not take a value" | ||
3583 | 389 | continue | ||
3584 | 390 | fi | ||
3585 | 391 | if [ "$opt_is_negated" ]; then | ||
3586 | 392 | val="" | ||
3587 | 393 | else | ||
3588 | 394 | val="yes" | ||
3589 | 395 | fi | ||
3590 | 396 | opt_is_ok=1 | ||
3591 | 397 | fi | ||
3592 | 398 | fi | ||
3593 | 399 | |||
3594 | 400 | if [ "$opt_is_ok" ]; then | ||
3595 | 401 | opt=$(cat "$spec" | grep '^long:' | cut -d':' -f2 | sed 's/-/_/g' | tr [:lower:] [:upper:]) | ||
3596 | 402 | |||
3597 | 403 | if grep "^type:size" "$spec" >/dev/null; then | ||
3598 | 404 | val=$(size_to_bytes $val) | ||
3599 | 405 | fi | ||
3600 | 406 | |||
3601 | 407 | eval "OPT_$opt"="'$val'" | ||
3602 | 408 | |||
3603 | 409 | opt="" | ||
3604 | 410 | val="" | ||
3605 | 411 | next_opt_is_val="" | ||
3606 | 412 | opt_is_ok="" | ||
3607 | 413 | opt_is_negated="" | ||
3608 | 414 | real_opt="" | ||
3609 | 415 | required_arg="" | ||
3610 | 416 | spec="" | ||
3611 | 417 | fi | ||
3612 | 418 | done | ||
3613 | 419 | } | ||
3614 | 420 | |||
3615 | 421 | size_to_bytes() { | ||
3616 | 422 | local size="$1" | ||
3617 | 423 | echo $size | perl -ne '%f=(B=>1, K=>1_024, M=>1_048_576, G=>1_073_741_824, T=>1_099_511_627_776); m/^(\d+)([kMGT])?/i; print $1 * $f{uc($2 || "B")};' | ||
3618 | 424 | } | ||
3619 | 425 | |||
3620 | 426 | # ########################################################################### | ||
3621 | 427 | # End parse_options package | ||
3622 | 428 | # ########################################################################### | ||
3623 | 46 | 429 | ||
3624 | 47 | # ########################################################################### | 430 | # ########################################################################### |
3625 | 48 | # tmpdir package | 431 | # tmpdir package |
3626 | @@ -53,18 +436,21 @@ | |||
3627 | 53 | # See https://launchpad.net/percona-toolkit for more information. | 436 | # See https://launchpad.net/percona-toolkit for more information. |
3628 | 54 | # ########################################################################### | 437 | # ########################################################################### |
3629 | 55 | 438 | ||
3630 | 439 | |||
3631 | 440 | set -u | ||
3632 | 441 | |||
3633 | 56 | TMPDIR="" | 442 | TMPDIR="" |
3634 | 57 | 443 | ||
3635 | 58 | mk_tmpdir() { | 444 | mk_tmpdir() { |
3637 | 59 | local dir=${1:-""} | 445 | local dir="${1:-""}" |
3638 | 60 | 446 | ||
3639 | 61 | if [ -n "$dir" ]; then | 447 | if [ -n "$dir" ]; then |
3640 | 62 | if [ ! -d "$dir" ]; then | 448 | if [ ! -d "$dir" ]; then |
3642 | 63 | mkdir $dir || die "Cannot make tmpdir $dir" | 449 | mkdir "$dir" || die "Cannot make tmpdir $dir" |
3643 | 64 | fi | 450 | fi |
3644 | 65 | TMPDIR="$dir" | 451 | TMPDIR="$dir" |
3645 | 66 | else | 452 | else |
3647 | 67 | local tool=`basename $0` | 453 | local tool="${0##*/}" |
3648 | 68 | local pid="$$" | 454 | local pid="$$" |
3649 | 69 | TMPDIR=`mktemp -d /tmp/${tool}.${pid}.XXXXX` \ | 455 | TMPDIR=`mktemp -d /tmp/${tool}.${pid}.XXXXX` \ |
3650 | 70 | || die "Cannot make secure tmpdir" | 456 | || die "Cannot make secure tmpdir" |
3651 | @@ -73,7 +459,7 @@ | |||
3652 | 73 | 459 | ||
3653 | 74 | rm_tmpdir() { | 460 | rm_tmpdir() { |
3654 | 75 | if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then | 461 | if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then |
3656 | 76 | rm -rf $TMPDIR | 462 | rm -rf "$TMPDIR" |
3657 | 77 | fi | 463 | fi |
3658 | 78 | TMPDIR="" | 464 | TMPDIR="" |
3659 | 79 | } | 465 | } |
3660 | @@ -82,180 +468,893 @@ | |||
3661 | 82 | # End tmpdir package | 468 | # End tmpdir package |
3662 | 83 | # ########################################################################### | 469 | # ########################################################################### |
3663 | 84 | 470 | ||
3676 | 85 | # The temp files are for storing working results so we don't call commands many | 471 | # ########################################################################### |
3677 | 86 | # times (gives inconsistent results, maybe adds load on things I don't want to | 472 | # alt_cmds package |
3678 | 87 | # such as RAID controllers). They must not exist -- if they did, someone would | 473 | # This package is a copy without comments from the original. The original |
3679 | 88 | # symlink them to /etc/passwd and then run this program as root. Call this | 474 | # with comments and its test file can be found in the Bazaar repository at, |
3680 | 89 | # function with "rm" or "touch" as an argument. | 475 | # lib/bash/alt_cmds.sh |
3681 | 90 | temp_files() { | 476 | # t/lib/bash/alt_cmds.sh |
3682 | 91 | for file in $TMPDIR/percona-toolkit $TMPDIR/percona-toolkit2; do | 477 | # See https://launchpad.net/percona-toolkit for more information. |
3683 | 92 | case "$1" in | 478 | # ########################################################################### |
3684 | 93 | touch) | 479 | |
3685 | 94 | if ! touch "${file}"; then | 480 | |
3686 | 95 | echo "I can't make my temp file ${file}"; | 481 | set -u |
3687 | 96 | exit 1; | 482 | |
3688 | 483 | _seq() { | ||
3689 | 484 | local i="$1" | ||
3690 | 485 | awk "BEGIN { for(i=1; i<=$i; i++) print i; }" | ||
3691 | 486 | } | ||
3692 | 487 | |||
3693 | 488 | _pidof() { | ||
3694 | 489 | local cmd="$1" | ||
3695 | 490 | if ! pidof "$cmd" 2>/dev/null; then | ||
3696 | 491 | ps -eo pid,ucomm | awk -v comm="$cmd" '$2 == comm { print $1 }' | ||
3697 | 492 | fi | ||
3698 | 493 | } | ||
3699 | 494 | |||
3700 | 495 | _lsof() { | ||
3701 | 496 | local pid="$1" | ||
3702 | 497 | if ! lsof -p $pid 2>/dev/null; then | ||
3703 | 498 | /bin/ls -l /proc/$pid/fd 2>/dev/null | ||
3704 | 499 | fi | ||
3705 | 500 | } | ||
3706 | 501 | |||
3707 | 502 | |||
3708 | 503 | |||
3709 | 504 | _which() { | ||
3710 | 505 | if [ -x /usr/bin/which ]; then | ||
3711 | 506 | /usr/bin/which "$1" 2>/dev/null | awk '{print $1}' | ||
3712 | 507 | elif which which 1>/dev/null 2>&1; then | ||
3713 | 508 | which "$1" 2>/dev/null | awk '{print $1}' | ||
3714 | 509 | else | ||
3715 | 510 | echo "$1" | ||
3716 | 511 | fi | ||
3717 | 512 | } | ||
3718 | 513 | |||
3719 | 514 | # ########################################################################### | ||
3720 | 515 | # End alt_cmds package | ||
3721 | 516 | # ########################################################################### | ||
3722 | 517 | |||
3723 | 518 | # ########################################################################### | ||
3724 | 519 | # summary_common package | ||
3725 | 520 | # This package is a copy without comments from the original. The original | ||
3726 | 521 | # with comments and its test file can be found in the Bazaar repository at, | ||
3727 | 522 | # lib/bash/summary_common.sh | ||
3728 | 523 | # t/lib/bash/summary_common.sh | ||
3729 | 524 | # See https://launchpad.net/percona-toolkit for more information. | ||
3730 | 525 | # ########################################################################### | ||
3731 | 526 | |||
3732 | 527 | |||
3733 | 528 | set -u | ||
3734 | 529 | |||
3735 | 530 | CMD_FILE="$( _which file 2>/dev/null )" | ||
3736 | 531 | CMD_NM="$( _which nm 2>/dev/null )" | ||
3737 | 532 | CMD_OBJDUMP="$( _which objdump 2>/dev/null )" | ||
3738 | 533 | |||
3739 | 534 | get_nice_of_pid () { | ||
3740 | 535 | local pid="$1" | ||
3741 | 536 | local niceness="$(ps -p $pid -o nice | awk '$1 !~ /[^0-9]/ {print $1; exit}')" | ||
3742 | 537 | |||
3743 | 538 | if [ -n "${niceness}" ]; then | ||
3744 | 539 | echo $niceness | ||
3745 | 540 | else | ||
3746 | 541 | local tmpfile="$TMPDIR/nice_through_c.tmp.c" | ||
3747 | 542 | _d "Getting the niceness from ps failed, somehow. We are about to try this:" | ||
3748 | 543 | cat <<EOC > "$tmpfile" | ||
3749 | 544 | |||
3750 | 545 | int main(void) { | ||
3751 | 546 | int priority = getpriority(PRIO_PROCESS, $pid); | ||
3752 | 547 | if ( priority == -1 && errno == ESRCH ) { | ||
3753 | 548 | return 1; | ||
3754 | 549 | } | ||
3755 | 550 | else { | ||
3756 | 551 | printf("%d\\n", priority); | ||
3757 | 552 | return 0; | ||
3758 | 553 | } | ||
3759 | 554 | } | ||
3760 | 555 | |||
3761 | 556 | EOC | ||
3762 | 557 | local c_comp=$(_which gcc) | ||
3763 | 558 | if [ -z "${c_comp}" ]; then | ||
3764 | 559 | c_comp=$(_which cc) | ||
3765 | 560 | fi | ||
3766 | 561 | _d "$tmpfile: $( cat "$tmpfile" )" | ||
3767 | 562 | _d "$c_comp -xc \"$tmpfile\" -o \"$tmpfile\" && eval \"$tmpfile\"" | ||
3768 | 563 | $c_comp -xc "$tmpfile" -o "$tmpfile" 2>/dev/null && eval "$tmpfile" 2>/dev/null | ||
3769 | 564 | if [ $? -ne 0 ]; then | ||
3770 | 565 | echo "?" | ||
3771 | 566 | _d "Failed to get a niceness value for $pid" | ||
3772 | 567 | fi | ||
3773 | 568 | fi | ||
3774 | 569 | } | ||
3775 | 570 | |||
3776 | 571 | get_oom_of_pid () { | ||
3777 | 572 | local pid="$1" | ||
3778 | 573 | local oom_adj="" | ||
3779 | 574 | |||
3780 | 575 | if [ -n "${pid}" -a -e /proc/cpuinfo ]; then | ||
3781 | 576 | if [ -s "/proc/$pid/oom_score_adj" ]; then | ||
3782 | 577 | oom_adj=$(cat "/proc/$pid/oom_score_adj" 2>/dev/null) | ||
3783 | 578 | _d "For $pid, the oom value is $oom_adj, retreived from oom_score_adj" | ||
3784 | 579 | else | ||
3785 | 580 | oom_adj=$(cat "/proc/$pid/oom_adj" 2>/dev/null) | ||
3786 | 581 | _d "For $pid, the oom value is $oom_adj, retreived from oom_adj" | ||
3787 | 582 | fi | ||
3788 | 583 | fi | ||
3789 | 584 | |||
3790 | 585 | if [ -n "${oom_adj}" ]; then | ||
3791 | 586 | echo "${oom_adj}" | ||
3792 | 587 | else | ||
3793 | 588 | echo "?" | ||
3794 | 589 | _d "Can't find the oom value for $pid" | ||
3795 | 590 | fi | ||
3796 | 591 | } | ||
3797 | 592 | |||
3798 | 593 | has_symbols () { | ||
3799 | 594 | local executable="$(_which "$1")" | ||
3800 | 595 | local has_symbols="" | ||
3801 | 596 | |||
3802 | 597 | if [ "${CMD_FILE}" ] \ | ||
3803 | 598 | && [ "$($CMD_FILE "${executable}" | grep 'not stripped' )" ]; then | ||
3804 | 599 | has_symbols=1 | ||
3805 | 600 | elif [ "${CMD_NM}" ] \ | ||
3806 | 601 | || [ "${CMD_OBJDMP}" ]; then | ||
3807 | 602 | if [ "${CMD_NM}" ] \ | ||
3808 | 603 | && [ !"$("${CMD_NM}" -- "${executable}" 2>&1 | grep 'File format not recognized' )" ]; then | ||
3809 | 604 | if [ -z "$( $CMD_NM -- "${executable}" 2>&1 | grep ': no symbols' )" ]; then | ||
3810 | 605 | has_symbols=1 | ||
3811 | 97 | fi | 606 | fi |
3823 | 98 | ;; | 607 | elif [ -z "$("${CMD_OBJDUMP}" -t -- "${executable}" | grep '^no symbols$' )" ]; then |
3824 | 99 | rm) | 608 | has_symbols=1 |
3825 | 100 | rm -f "${file}" | 609 | fi |
3826 | 101 | ;; | 610 | fi |
3827 | 102 | esac | 611 | |
3828 | 103 | done | 612 | if [ "${has_symbols}" ]; then |
3829 | 104 | } | 613 | echo "Yes" |
3830 | 105 | 614 | else | |
3831 | 106 | # Print a space-padded string into $line. Then translate spaces to hashes, and | 615 | echo "No" |
3832 | 107 | # underscores to spaces. End result is a line of hashes with words at the | 616 | fi |
3833 | 108 | # start. | 617 | } |
3834 | 618 | |||
3835 | 619 | setup_data_dir () { | ||
3836 | 620 | local existing_dir="$1" | ||
3837 | 621 | local data_dir="" | ||
3838 | 622 | if [ -z "$existing_dir" ]; then | ||
3839 | 623 | mkdir "$TMPDIR/data" || die "Cannot mkdir $TMPDIR/data" | ||
3840 | 624 | data_dir="$TMPDIR/data" | ||
3841 | 625 | else | ||
3842 | 626 | if [ ! -d "$existing_dir" ]; then | ||
3843 | 627 | mkdir "$existing_dir" || die "Cannot mkdir $existing_dir" | ||
3844 | 628 | elif [ "$( ls -A "$existing_dir" )" ]; then | ||
3845 | 629 | die "--save-samples directory isn't empty, halting." | ||
3846 | 630 | fi | ||
3847 | 631 | touch "$existing_dir/test" || die "Cannot write to $existing_dir" | ||
3848 | 632 | rm "$existing_dir/test" || die "Cannot rm $existing_dir/test" | ||
3849 | 633 | data_dir="$existing_dir" | ||
3850 | 634 | fi | ||
3851 | 635 | echo "$data_dir" | ||
3852 | 636 | } | ||
3853 | 637 | |||
3854 | 638 | get_var () { | ||
3855 | 639 | local varname="$1" | ||
3856 | 640 | local file="$2" | ||
3857 | 641 | awk -v pattern="${varname}" '$1 == pattern { if (length($2)) { len = length($1); print substr($0, len+index(substr($0, len+1), $2)) } }' "${file}" | ||
3858 | 642 | } | ||
3859 | 643 | |||
3860 | 644 | # ########################################################################### | ||
3861 | 645 | # End summary_common package | ||
3862 | 646 | # ########################################################################### | ||
3863 | 647 | |||
3864 | 648 | # ########################################################################### | ||
3865 | 649 | # report_formatting package | ||
3866 | 650 | # This package is a copy without comments from the original. The original | ||
3867 | 651 | # with comments and its test file can be found in the Bazaar repository at, | ||
3868 | 652 | # lib/bash/report_formatting.sh | ||
3869 | 653 | # t/lib/bash/report_formatting.sh | ||
3870 | 654 | # See https://launchpad.net/percona-toolkit for more information. | ||
3871 | 655 | # ########################################################################### | ||
3872 | 656 | |||
3873 | 657 | |||
3874 | 658 | set -u | ||
3875 | 659 | |||
3876 | 660 | POSIXLY_CORRECT=1 | ||
3877 | 661 | export POSIXLY_CORRECT | ||
3878 | 662 | |||
3879 | 663 | fuzzy_formula=' | ||
3880 | 664 | rounded = 0; | ||
3881 | 665 | if (fuzzy_var <= 10 ) { | ||
3882 | 666 | rounded = 1; | ||
3883 | 667 | } | ||
3884 | 668 | factor = 1; | ||
3885 | 669 | while ( rounded == 0 ) { | ||
3886 | 670 | if ( fuzzy_var <= 50 * factor ) { | ||
3887 | 671 | fuzzy_var = sprintf("%.0f", fuzzy_var / (5 * factor)) * 5 * factor; | ||
3888 | 672 | rounded = 1; | ||
3889 | 673 | } | ||
3890 | 674 | else if ( fuzzy_var <= 100 * factor) { | ||
3891 | 675 | fuzzy_var = sprintf("%.0f", fuzzy_var / (10 * factor)) * 10 * factor; | ||
3892 | 676 | rounded = 1; | ||
3893 | 677 | } | ||
3894 | 678 | else if ( fuzzy_var <= 250 * factor) { | ||
3895 | 679 | fuzzy_var = sprintf("%.0f", fuzzy_var / (25 * factor)) * 25 * factor; | ||
3896 | 680 | rounded = 1; | ||
3897 | 681 | } | ||
3898 | 682 | factor = factor * 10; | ||
3899 | 683 | }' | ||
3900 | 684 | |||
3901 | 685 | fuzz () { | ||
3902 | 686 | awk -v fuzzy_var="$1" "BEGIN { ${fuzzy_formula} print fuzzy_var;}" | ||
3903 | 687 | } | ||
3904 | 688 | |||
3905 | 689 | fuzzy_pct () { | ||
3906 | 690 | local pct="$(awk -v one="$1" -v two="$2" 'BEGIN{ if (two > 0) { printf "%d", one/two*100; } else {print 0} }')"; | ||
3907 | 691 | echo "$(fuzz "${pct}")%" | ||
3908 | 692 | } | ||
3909 | 693 | |||
3910 | 109 | section () { | 694 | section () { |
3920 | 110 | echo "$1" | awk '{l=sprintf("#_%-60s", $0 "_"); print l}' | sed -e 's/ /#/g' -e 's/_/ /g' | 695 | local str="$1" |
3921 | 111 | } | 696 | awk -v var="${str} _" 'BEGIN { |
3922 | 112 | 697 | line = sprintf("# %-60s", var); | |
3923 | 113 | # Print a "name | value" line. | 698 | i = index(line, "_"); |
3924 | 114 | name_val() { | 699 | x = substr(line, i); |
3925 | 115 | printf "%12s | %s\n" "$1" "$(echo $2)" | 700 | gsub(/[_ \t]/, "#", x); |
3926 | 116 | } | 701 | printf("%s%s\n", substr(line, 1, i-1), x); |
3927 | 117 | 702 | }' | |
3928 | 118 | # Converts a value to units of power of 2. Arg 1: the value. Arg 2: precision (defaults to 2). | 703 | } |
3929 | 704 | |||
3930 | 705 | NAME_VAL_LEN=12 | ||
3931 | 706 | name_val () { | ||
3932 | 707 | printf "%+*s | %s\n" "${NAME_VAL_LEN}" "$1" "$2" | ||
3933 | 708 | } | ||
3934 | 709 | |||
3935 | 119 | shorten() { | 710 | shorten() { |
3939 | 120 | echo $@ | awk '{ | 711 | local num="$1" |
3940 | 121 | unit = "k"; | 712 | local prec="${2:-2}" |
3941 | 122 | size = 1024; | 713 | local div="${3:-1024}" |
3942 | 714 | |||
3943 | 715 | echo "$num" | awk -v prec="$prec" -v div="$div" ' | ||
3944 | 716 | { | ||
3945 | 717 | size = 4; | ||
3946 | 123 | val = $1; | 718 | val = $1; |
3965 | 124 | prec = 2; | 719 | |
3966 | 125 | if ( $2 ~ /./ ) { | 720 | unit = val >= 1099511627776 ? "T" : val >= 1073741824 ? "G" : val >= 1048576 ? "M" : val >= 1024 ? "k" : ""; |
3967 | 126 | prec = $2; | 721 | |
3968 | 127 | } | 722 | while ( int(val) && !(val % 1024) ) { |
3969 | 128 | if ( val >= 1099511627776 ) { | 723 | val /= 1024; |
3970 | 129 | size = 1099511627776; | 724 | } |
3971 | 130 | unit = "T"; | 725 | |
3972 | 131 | } | 726 | while ( val > 1000 ) { |
3973 | 132 | else if ( val >= 1073741824 ) { | 727 | val /= div; |
3974 | 133 | size = 1073741824; | 728 | } |
3975 | 134 | unit = "G"; | 729 | |
3976 | 135 | } | 730 | printf "%.*f%s", prec, val, unit; |
3977 | 136 | else if ( val >= 1048576 ) { | 731 | } |
3978 | 137 | size = 1048576; | 732 | ' |
3961 | 138 | unit = "M"; | ||
3962 | 139 | } | ||
3963 | 140 | printf "%." prec "f%s", val / size, unit; | ||
3964 | 141 | }' | ||
3979 | 142 | } | 733 | } |
3980 | 143 | 734 | ||
3981 | 144 | # ############################################################################## | ||
3982 | 145 | # Function to take a file and collapse it into an aggregated list. This | ||
3983 | 146 | # function works on $1, which it expects to be created with 'sort | | ||
3984 | 147 | # uniq -c'. Leading whitespace is deleted. The result will look like | ||
3985 | 148 | # "4xabc, 1xdef" Copy any changes to 'mysql-summary' too. | ||
3986 | 149 | # ############################################################################## | ||
3987 | 150 | group_concat () { | 735 | group_concat () { |
4009 | 151 | sed -e '{H; $!d}' -e 'x' -e 's/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/, //' ${1} | 736 | sed -e '{H; $!d;}' -e 'x' -e 's/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/, //' "${1}" |
4010 | 152 | # In words: save the whole file into the hold space, | 737 | } |
4011 | 153 | # {H; $!d} | 738 | |
4012 | 154 | # Swap it back into the pattern space, | 739 | # ########################################################################### |
4013 | 155 | # x | 740 | # End report_formatting package |
4014 | 156 | # Join lines with a comma, delete leading whitespace, and put an 'x' between | 741 | # ########################################################################### |
4015 | 157 | # the number and the text that follows, | 742 | |
4016 | 158 | # s/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g | 743 | # ########################################################################### |
4017 | 159 | # Collapse whitespace, | 744 | # collect_system_info package |
4018 | 160 | # s/[[:space:]][[:space:]]*/ /g | 745 | # This package is a copy without comments from the original. The original |
4019 | 161 | # And delete the leading comma-space. | 746 | # with comments and its test file can be found in the Bazaar repository at, |
4020 | 162 | # s/, // | 747 | # lib/bash/collect_system_info.sh |
4021 | 163 | } | 748 | # t/lib/bash/collect_system_info.sh |
4022 | 164 | 749 | # See https://launchpad.net/percona-toolkit for more information. | |
4023 | 165 | # ############################################################################## | 750 | # ########################################################################### |
4024 | 166 | # Functions for parsing specific files and getting desired info from them. | 751 | |
4025 | 167 | # These are called from within main() and are separated so they can be tested | 752 | |
4026 | 168 | # easily. The calling convention is that the data they need to run is prepared | 753 | |
4027 | 169 | # first by putting it into $TMPDIR/percona-toolkit. Then code that's testing | 754 | set -u |
4028 | 170 | # just needs to put sample data into $TMPDIR/percona-toolkit and call it. | 755 | |
4029 | 171 | # ############################################################################## | 756 | setup_commands () { |
4030 | 757 | CMD_SYSCTL="$(_which sysctl 2>/dev/null )" | ||
4031 | 758 | CMD_DMIDECODE="$(_which dmidecode 2>/dev/null )" | ||
4032 | 759 | CMD_ZONENAME="$(_which zonename 2>/dev/null )" | ||
4033 | 760 | CMD_DMESG="$(_which dmesg 2>/dev/null )" | ||
4034 | 761 | CMD_FILE="$(_which file 2>/dev/null )" | ||
4035 | 762 | CMD_LSPCI="$(_which lspci 2>/dev/null )" | ||
4036 | 763 | CMD_PRTDIAG="$(_which prtdiag 2>/dev/null )" | ||
4037 | 764 | CMD_SMBIOS="$(_which smbios 2>/dev/null )" | ||
4038 | 765 | CMD_GETENFORCE="$(_which getenforce 2>/dev/null )" | ||
4039 | 766 | CMD_PRTCONF="$(_which prtconf 2>/dev/null )" | ||
4040 | 767 | CMD_LVS="$(_which lvs 2>/dev/null)" | ||
4041 | 768 | CMD_VGS="$(_which vgs 2>/dev/null)" | ||
4042 | 769 | CMD_PRSTAT="$(_which prstat 2>/dev/null)" | ||
4043 | 770 | CMD_ISAINFO="$(_which isainfo 2>/dev/null)" | ||
4044 | 771 | CMD_TOP="$(_which top 2>/dev/null)" | ||
4045 | 772 | CMD_ARCCONF="$( _which arcconf 2>/dev/null )" | ||
4046 | 773 | CMD_HPACUCLI="$( _which hpacucli 2>/dev/null )" | ||
4047 | 774 | CMD_MEGACLI64="$( _which MegaCli64 2>/dev/null )" | ||
4048 | 775 | CMD_VMSTAT="$(_which vmstat 2>/dev/null)" | ||
4049 | 776 | CMD_IP="$( _which ip 2>/dev/null )" | ||
4050 | 777 | CMD_NETSTAT="$( _which netstat 2>/dev/null )" | ||
4051 | 778 | CMD_PSRINFO="$( _which psrinfo 2>/dev/null )" | ||
4052 | 779 | CMD_SWAPCTL="$( _which swapctl 2>/dev/null )" | ||
4053 | 780 | CMD_LSB_RELEASE="$( _which lsb_release 2>/dev/null )" | ||
4054 | 781 | CMD_ETHTOOL="$( _which ethtool 2>/dev/null )" | ||
4055 | 782 | CMD_GETCONF="$( _which getconf 2>/dev/null )" | ||
4056 | 783 | } | ||
4057 | 784 | |||
4058 | 785 | collect_system_data () { local PTFUNCNAME=collect_system_data; | ||
4059 | 786 | local data_dir="$1" | ||
4060 | 787 | |||
4061 | 788 | if [ -r /var/log/dmesg -a -s /var/log/dmesg ]; then | ||
4062 | 789 | cat "/var/log/dmesg" > "$data_dir/dmesg_file" | ||
4063 | 790 | fi | ||
4064 | 791 | |||
4065 | 792 | $CMD_SYSCTL -a > "$data_dir/sysctl" 2>/dev/null | ||
4066 | 793 | |||
4067 | 794 | if [ "${CMD_LSPCI}" ]; then | ||
4068 | 795 | $CMD_LSPCI > "$data_dir/lspci_file" 2>/dev/null | ||
4069 | 796 | fi | ||
4070 | 797 | |||
4071 | 798 | local platform="$(uname -s)" | ||
4072 | 799 | echo "platform $platform" >> "$data_dir/summary" | ||
4073 | 800 | echo "hostname $(uname -n)" >> "$data_dir/summary" | ||
4074 | 801 | uptime >> "$data_dir/uptime" | ||
4075 | 802 | |||
4076 | 803 | processor_info "$data_dir" | ||
4077 | 804 | find_release_and_kernel "$platform" >> "$data_dir/summary" | ||
4078 | 805 | cpu_and_os_arch "$platform" >> "$data_dir/summary" | ||
4079 | 806 | find_virtualization "$platform" "$data_dir/dmesg_file" "$data_dir/lspci_file" >> "$data_dir/summary" | ||
4080 | 807 | dmidecode_system_info >> "$data_dir/summary" | ||
4081 | 808 | |||
4082 | 809 | if [ "${platform}" = "SunOS" -a "${CMD_ZONENAME}" ]; then | ||
4083 | 810 | echo "zonename $($CMD_ZONENAME)" >> "$data_dir/summary" | ||
4084 | 811 | fi | ||
4085 | 812 | |||
4086 | 813 | if [ -x /lib/libc.so.6 ]; then | ||
4087 | 814 | echo "compiler $(/lib/libc.so.6 | grep 'Compiled by' | cut -c13-)" >> "$data_dir/summary" | ||
4088 | 815 | fi | ||
4089 | 816 | |||
4090 | 817 | local rss=$(ps -eo rss 2>/dev/null | awk '/[0-9]/{total += $1 * 1024} END {print total}') | ||
4091 | 818 | echo "rss ${rss}" >> "$data_dir/summary" | ||
4092 | 819 | |||
4093 | 820 | [ "$CMD_DMIDECODE" ] && $CMD_DMIDECODE > "$data_dir/dmidecode" 2>/dev/null | ||
4094 | 821 | |||
4095 | 822 | find_memory_stats "$platform" > "$data_dir/memory" | ||
4096 | 823 | [ "$OPT_SUMMARIZE_MOUNTS" ] && mounted_fs_info "$platform" > "$data_dir/mounted_fs" | ||
4097 | 824 | raid_controller "$data_dir/dmesg_file" "$data_dir/lspci_file" >> "$data_dir/summary" | ||
4098 | 825 | |||
4099 | 826 | local controller="$(get_var raid_controller "$data_dir/summary")" | ||
4100 | 827 | propietary_raid_controller "$data_dir/raid-controller" "$data_dir/summary" "$data_dir" "$controller" | ||
4101 | 828 | |||
4102 | 829 | [ "${platform}" = "Linux" ] && linux_exclusive_collection "$data_dir" | ||
4103 | 830 | |||
4104 | 831 | if [ "$CMD_IP" -a "$OPT_SUMMARIZE_NETWORK" ]; then | ||
4105 | 832 | $CMD_IP -s link > "$data_dir/ip" | ||
4106 | 833 | network_device_info "$data_dir/ip" > "$data_dir/network_devices" | ||
4107 | 834 | fi | ||
4108 | 835 | |||
4109 | 836 | [ "$CMD_SWAPCTL" ] && $CMD_SWAPCTL -s > "$data_dir/swapctl" | ||
4110 | 837 | |||
4111 | 838 | if [ "$OPT_SUMMARIZE_PROCESSES" ]; then | ||
4112 | 839 | top_processes > "$data_dir/processes" | ||
4113 | 840 | notable_processes_info > "$data_dir/notable_procs" | ||
4114 | 841 | |||
4115 | 842 | if [ "$CMD_VMSTAT" ]; then | ||
4116 | 843 | touch "$data_dir/vmstat" | ||
4117 | 844 | ( | ||
4118 | 845 | $CMD_VMSTAT 1 $OPT_SLEEP > "$data_dir/vmstat" | ||
4119 | 846 | ) & | ||
4120 | 847 | fi | ||
4121 | 848 | fi | ||
4122 | 849 | |||
4123 | 850 | for file in $data_dir/*; do | ||
4124 | 851 | [ "$file" = "vmstat" ] && continue | ||
4125 | 852 | [ ! -s "$file" ] && rm "$file" | ||
4126 | 853 | done | ||
4127 | 854 | } | ||
4128 | 855 | |||
4129 | 856 | linux_exclusive_collection () { local PTFUNCNAME=linux_exclusive_collection; | ||
4130 | 857 | local data_dir="$1" | ||
4131 | 858 | |||
4132 | 859 | echo "threading $(getconf GNU_LIBPTHREAD_VERSION)" >> "$data_dir/summary" | ||
4133 | 860 | |||
4134 | 861 | local getenforce="" | ||
4135 | 862 | [ "$CMD_GETENFORCE" ] && getenforce="$($CMD_GETENFORCE 2>&1)" | ||
4136 | 863 | echo "getenforce ${getenforce:-"No SELinux detected"}" >> "$data_dir/summary" | ||
4137 | 864 | |||
4138 | 865 | echo "swappiness $(awk '/vm.swappiness/{print $3}' "$data_dir/sysctl")" >> "$data_dir/summary" | ||
4139 | 866 | |||
4140 | 867 | local dirty_ratio="$(awk '/vm.dirty_ratio/{print $3}' "$data_dir/sysctl")" | ||
4141 | 868 | local dirty_bg_ratio="$(awk '/vm.dirty_background_ratio/{print $3}' "$data_dir/sysctl")" | ||
4142 | 869 | if [ "$dirty_ratio" -a "$dirty_bg_ratio" ]; then | ||
4143 | 870 | echo "dirtypolicy $dirty_ratio, $dirty_bg_ratio" >> "$data_dir/summary" | ||
4144 | 871 | fi | ||
4145 | 872 | |||
4146 | 873 | local dirty_bytes="$(awk '/vm.dirty_bytes/{print $3}' "$data_dir/sysctl")" | ||
4147 | 874 | if [ "$dirty_bytes" ]; then | ||
4148 | 875 | echo "dirtystatus $(awk '/vm.dirty_bytes/{print $3}' "$data_dir/sysctl"), $(awk '/vm.dirty_background_bytes/{print $3}' "$data_dir/sysctl")" >> "$data_dir/summary" | ||
4149 | 876 | fi | ||
4150 | 877 | |||
4151 | 878 | schedulers_and_queue_size "$data_dir/summary" > "$data_dir/partitioning" | ||
4152 | 879 | |||
4153 | 880 | for file in dentry-state file-nr inode-nr; do | ||
4154 | 881 | echo "${file} $(cat /proc/sys/fs/${file} 2>&1)" >> "$data_dir/summary" | ||
4155 | 882 | done | ||
4156 | 883 | |||
4157 | 884 | [ "$CMD_LVS" -a -x "$CMD_LVS" ] && $CMD_LVS 1>"$data_dir/lvs" 2>"$data_dir/lvs.stderr" | ||
4158 | 885 | |||
4159 | 886 | [ "$CMD_VGS" -a -x "$CMD_VGS" ] && \ | ||
4160 | 887 | $CMD_VGS -o vg_name,vg_size,vg_free 2>/dev/null > "$data_dir/vgs" | ||
4161 | 888 | |||
4162 | 889 | [ "$CMD_NETSTAT" -a "$OPT_SUMMARIZE_NETWORK" ] && \ | ||
4163 | 890 | $CMD_NETSTAT -antp > "$data_dir/netstat" 2>/dev/null | ||
4164 | 891 | } | ||
4165 | 892 | |||
4166 | 893 | network_device_info () { | ||
4167 | 894 | local ip_minus_s_file="$1" | ||
4168 | 895 | |||
4169 | 896 | if [ "$CMD_ETHTOOL" ]; then | ||
4170 | 897 | local tempfile="$TMPDIR/ethtool_output_temp" | ||
4171 | 898 | for device in $( awk '/^[1-9]/{ print $2 }' "$ip_minus_s_file" \ | ||
4172 | 899 | | awk -F: '{print $1}' \ | ||
4173 | 900 | | grep -v '^lo\|^in\|^gr' \ | ||
4174 | 901 | | sort -u ); do | ||
4175 | 902 | ethtool $device > "$tempfile" 2>/dev/null | ||
4176 | 903 | |||
4177 | 904 | if ! grep -q 'No data available' "$tempfile"; then | ||
4178 | 905 | cat "$tempfile" | ||
4179 | 906 | fi | ||
4180 | 907 | done | ||
4181 | 908 | fi | ||
4182 | 909 | } | ||
4183 | 910 | |||
4184 | 911 | find_release_and_kernel () { local PTFUNCNAME=find_release_and_kernel; | ||
4185 | 912 | local platform="$1" | ||
4186 | 913 | |||
4187 | 914 | local kernel="" | ||
4188 | 915 | local release="" | ||
4189 | 916 | if [ "${platform}" = "Linux" ]; then | ||
4190 | 917 | kernel="$(uname -r)" | ||
4191 | 918 | if [ -e /etc/fedora-release ]; then | ||
4192 | 919 | release=$(cat /etc/fedora-release); | ||
4193 | 920 | elif [ -e /etc/redhat-release ]; then | ||
4194 | 921 | release=$(cat /etc/redhat-release); | ||
4195 | 922 | elif [ -e /etc/system-release ]; then | ||
4196 | 923 | release=$(cat /etc/system-release); | ||
4197 | 924 | elif [ "$CMD_LSB_RELEASE" ]; then | ||
4198 | 925 | release="$($CMD_LSB_RELEASE -ds) ($($CMD_LSB_RELEASE -cs))" | ||
4199 | 926 | elif [ -e /etc/lsb-release ]; then | ||
4200 | 927 | release=$(grep DISTRIB_DESCRIPTION /etc/lsb-release |awk -F'=' '{print $2}' |sed 's#"##g'); | ||
4201 | 928 | elif [ -e /etc/debian_version ]; then | ||
4202 | 929 | release="Debian-based version $(cat /etc/debian_version)"; | ||
4203 | 930 | if [ -e /etc/apt/sources.list ]; then | ||
4204 | 931 | local code=` awk '/^deb/ {print $3}' /etc/apt/sources.list \ | ||
4205 | 932 | | awk -F/ '{print $1}'| awk 'BEGIN {FS="|"}{print $1}' \ | ||
4206 | 933 | | sort | uniq -c | sort -rn | head -n1 | awk '{print $2}'` | ||
4207 | 934 | release="${release} (${code})" | ||
4208 | 935 | fi | ||
4209 | 936 | elif ls /etc/*release >/dev/null 2>&1; then | ||
4210 | 937 | if grep -q DISTRIB_DESCRIPTION /etc/*release; then | ||
4211 | 938 | release=$(grep DISTRIB_DESCRIPTION /etc/*release | head -n1); | ||
4212 | 939 | else | ||
4213 | 940 | release=$(cat /etc/*release | head -n1); | ||
4214 | 941 | fi | ||
4215 | 942 | fi | ||
4216 | 943 | elif [ "${platform}" = "FreeBSD" ] \ | ||
4217 | 944 | || [ "${platform}" = "NetBSD" ] \ | ||
4218 | 945 | || [ "${platform}" = "OpenBSD" ]; then | ||
4219 | 946 | release="$(uname -r)" | ||
4220 | 947 | kernel="$($CMD_SYSCTL -n "kern.osrevision")" | ||
4221 | 948 | elif [ "${platform}" = "SunOS" ]; then | ||
4222 | 949 | release="$(head -n1 /etc/release)" | ||
4223 | 950 | if [ -z "${release}" ]; then | ||
4224 | 951 | release="$(uname -r)" | ||
4225 | 952 | fi | ||
4226 | 953 | kernel="$(uname -v)" | ||
4227 | 954 | fi | ||
4228 | 955 | echo "kernel $kernel" | ||
4229 | 956 | echo "release $release" | ||
4230 | 957 | } | ||
4231 | 958 | |||
4232 | 959 | cpu_and_os_arch () { local PTFUNCNAME=cpu_and_os_arch; | ||
4233 | 960 | local platform="$1" | ||
4234 | 961 | |||
4235 | 962 | local CPU_ARCH='32-bit' | ||
4236 | 963 | local OS_ARCH='32-bit' | ||
4237 | 964 | if [ "${platform}" = "Linux" ]; then | ||
4238 | 965 | if grep -q ' lm ' /proc/cpuinfo; then | ||
4239 | 966 | CPU_ARCH='64-bit' | ||
4240 | 967 | fi | ||
4241 | 968 | elif [ "${platform}" = "FreeBSD" ] || [ "${platform}" = "NetBSD" ]; then | ||
4242 | 969 | if $CMD_SYSCTL "hw.machine_arch" | grep -v 'i[36]86' >/dev/null; then | ||
4243 | 970 | CPU_ARCH='64-bit' | ||
4244 | 971 | fi | ||
4245 | 972 | elif [ "${platform}" = "OpenBSD" ]; then | ||
4246 | 973 | if $CMD_SYSCTL "hw.machine" | grep -v 'i[36]86' >/dev/null; then | ||
4247 | 974 | CPU_ARCH='64-bit' | ||
4248 | 975 | fi | ||
4249 | 976 | elif [ "${platform}" = "SunOS" ]; then | ||
4250 | 977 | if $CMD_ISAINFO -b | grep 64 >/dev/null ; then | ||
4251 | 978 | CPU_ARCH="64-bit" | ||
4252 | 979 | fi | ||
4253 | 980 | fi | ||
4254 | 981 | if [ -z "$CMD_FILE" ]; then | ||
4255 | 982 | if [ "$CMD_GETCONF" ] && $CMD_GETCONF LONG_BIT 1>/dev/null 2>&1; then | ||
4256 | 983 | OS_ARCH="$($CMD_GETCONF LONG_BIT 2>/dev/null)-bit" | ||
4257 | 984 | else | ||
4258 | 985 | OS_ARCH='N/A' | ||
4259 | 986 | fi | ||
4260 | 987 | elif $CMD_FILE /bin/sh | grep '64-bit' >/dev/null; then | ||
4261 | 988 | OS_ARCH='64-bit' | ||
4262 | 989 | fi | ||
4263 | 990 | |||
4264 | 991 | echo "CPU_ARCH $CPU_ARCH" | ||
4265 | 992 | echo "OS_ARCH $OS_ARCH" | ||
4266 | 993 | } | ||
4267 | 994 | |||
4268 | 995 | find_virtualization () { local PTFUNCNAME=find_virtualization; | ||
4269 | 996 | local platform="$1" | ||
4270 | 997 | local dmesg_file="$2" | ||
4271 | 998 | local lspci_file="$3" | ||
4272 | 999 | |||
4273 | 1000 | local tempfile="$TMPDIR/find_virtualziation.tmp" | ||
4274 | 1001 | |||
4275 | 1002 | local virt="" | ||
4276 | 1003 | if [ -s "$dmesg_file" ]; then | ||
4277 | 1004 | virt="$(find_virtualization_dmesg "$dmesg_file")" | ||
4278 | 1005 | fi | ||
4279 | 1006 | if [ -z "${virt}" ] && [ -s "$lspci_file" ]; then | ||
4280 | 1007 | if grep -qi "virtualbox" "$lspci_file" ; then | ||
4281 | 1008 | virt="VirtualBox" | ||
4282 | 1009 | elif grep -qi "vmware" "$lspci_file" ; then | ||
4283 | 1010 | virt="VMWare" | ||
4284 | 1011 | fi | ||
4285 | 1012 | elif [ "${platform}" = "FreeBSD" ]; then | ||
4286 | 1013 | if ps -o stat | grep J ; then | ||
4287 | 1014 | virt="FreeBSD Jail" | ||
4288 | 1015 | fi | ||
4289 | 1016 | elif [ "${platform}" = "SunOS" ]; then | ||
4290 | 1017 | if [ "$CMD_PRTDIAG" ] && $CMD_PRTDIAG > "$tempfile" 2>/dev/null; then | ||
4291 | 1018 | virt="$(find_virtualization_generic "$tempfile" )" | ||
4292 | 1019 | elif [ "$CMD_SMBIOS" ] && $CMD_SMBIOS > "$tempfile" 2>/dev/null; then | ||
4293 | 1020 | virt="$(find_virtualization_generic "$tempfile" )" | ||
4294 | 1021 | fi | ||
4295 | 1022 | elif [ -e /proc/user_beancounters ]; then | ||
4296 | 1023 | virt="OpenVZ/Virtuozzo" | ||
4297 | 1024 | fi | ||
4298 | 1025 | echo "virt ${virt:-"No virtualization detected"}" | ||
4299 | 1026 | } | ||
4300 | 1027 | |||
4301 | 1028 | find_virtualization_generic() { local PTFUNCNAME=find_virtualization_generic; | ||
4302 | 1029 | local file="$1" | ||
4303 | 1030 | if grep -i -e "virtualbox" "$file" >/dev/null; then | ||
4304 | 1031 | echo "VirtualBox" | ||
4305 | 1032 | elif grep -i -e "vmware" "$file" >/dev/null; then | ||
4306 | 1033 | echo "VMWare" | ||
4307 | 1034 | fi | ||
4308 | 1035 | } | ||
4309 | 1036 | |||
4310 | 1037 | find_virtualization_dmesg () { local PTFUNCNAME=find_virtualization_dmesg; | ||
4311 | 1038 | local file="$1" | ||
4312 | 1039 | if grep -qi -e "vmware" -e "vmxnet" -e 'paravirtualized kernel on vmi' "${file}"; then | ||
4313 | 1040 | echo "VMWare"; | ||
4314 | 1041 | elif grep -qi -e 'paravirtualized kernel on xen' -e 'Xen virtual console' "${file}"; then | ||
4315 | 1042 | echo "Xen"; | ||
4316 | 1043 | elif grep -qi "qemu" "${file}"; then | ||
4317 | 1044 | echo "QEmu"; | ||
4318 | 1045 | elif grep -qi 'paravirtualized kernel on KVM' "${file}"; then | ||
4319 | 1046 | echo "KVM"; | ||
4320 | 1047 | elif grep -q "VBOX" "${file}"; then | ||
4321 | 1048 | echo "VirtualBox"; | ||
4322 | 1049 | elif grep -qi 'hd.: Virtual .., ATA.*drive' "${file}"; then | ||
4323 | 1050 | echo "Microsoft VirtualPC"; | ||
4324 | 1051 | fi | ||
4325 | 1052 | } | ||
4326 | 1053 | |||
4327 | 1054 | dmidecode_system_info () { local PTFUNCNAME=dmidecode_system_info; | ||
4328 | 1055 | if [ "${CMD_DMIDECODE}" ]; then | ||
4329 | 1056 | local vendor="$($CMD_DMIDECODE -s "system-manufacturer" 2>/dev/null | sed 's/ *$//g')" | ||
4330 | 1057 | echo "vendor ${vendor}" | ||
4331 | 1058 | if [ "${vendor}" ]; then | ||
4332 | 1059 | local product="$($CMD_DMIDECODE -s "system-product-name" 2>/dev/null | sed 's/ *$//g')" | ||
4333 | 1060 | local version="$($CMD_DMIDECODE -s "system-version" 2>/dev/null | sed 's/ *$//g')" | ||
4334 | 1061 | local chassis="$($CMD_DMIDECODE -s "chassis-type" 2>/dev/null | sed 's/ *$//g')" | ||
4335 | 1062 | local servicetag="$($CMD_DMIDECODE -s "system-serial-number" 2>/dev/null | sed 's/ *$//g')" | ||
4336 | 1063 | local system="${vendor}; ${product}; v${version} (${chassis})" | ||
4337 | 1064 | |||
4338 | 1065 | echo "system ${system}" | ||
4339 | 1066 | echo "servicetag ${servicetag:-"Not found"}" | ||
4340 | 1067 | fi | ||
4341 | 1068 | fi | ||
4342 | 1069 | } | ||
4343 | 1070 | |||
4344 | 1071 | find_memory_stats () { local PTFUNCNAME=find_memory_stats; | ||
4345 | 1072 | local platform="$1" | ||
4346 | 1073 | |||
4347 | 1074 | if [ "${platform}" = "Linux" ]; then | ||
4348 | 1075 | free -b | ||
4349 | 1076 | cat /proc/meminfo | ||
4350 | 1077 | elif [ "${platform}" = "SunOS" ]; then | ||
4351 | 1078 | $CMD_PRTCONF | awk -F: '/Memory/{print $2}' | ||
4352 | 1079 | fi | ||
4353 | 1080 | } | ||
4354 | 1081 | |||
4355 | 1082 | mounted_fs_info () { local PTFUNCNAME=mounted_fs_info; | ||
4356 | 1083 | local platform="$1" | ||
4357 | 1084 | |||
4358 | 1085 | if [ "${platform}" != "SunOS" ]; then | ||
4359 | 1086 | local cmd="df -h" | ||
4360 | 1087 | if [ "${platform}" = "Linux" ]; then | ||
4361 | 1088 | cmd="df -h -P" | ||
4362 | 1089 | fi | ||
4363 | 1090 | $cmd | sort > "$TMPDIR/mounted_fs_info.tmp" | ||
4364 | 1091 | mount | sort | join "$TMPDIR/mounted_fs_info.tmp" - | ||
4365 | 1092 | fi | ||
4366 | 1093 | } | ||
4367 | 1094 | |||
4368 | 1095 | raid_controller () { local PTFUNCNAME=raid_controller; | ||
4369 | 1096 | local dmesg_file="$1" | ||
4370 | 1097 | local lspci_file="$2" | ||
4371 | 1098 | |||
4372 | 1099 | local tempfile="$TMPDIR/raid_controller.tmp" | ||
4373 | 1100 | |||
4374 | 1101 | local controller="" | ||
4375 | 1102 | if [ -s "$lspci_file" ]; then | ||
4376 | 1103 | controller="$(find_raid_controller_lspci "$lspci_file")" | ||
4377 | 1104 | fi | ||
4378 | 1105 | if [ -z "${controller}" ] && [ -s "$dmesg_file" ]; then | ||
4379 | 1106 | controller="$(find_raid_controller_dmesg "$dmesg_file")" | ||
4380 | 1107 | fi | ||
4381 | 1108 | |||
4382 | 1109 | echo "raid_controller ${controller:-"No RAID controller detected"}" | ||
4383 | 1110 | } | ||
4384 | 1111 | |||
4385 | 1112 | find_raid_controller_dmesg () { local PTFUNCNAME=find_raid_controller_dmesg; | ||
4386 | 1113 | local file="$1" | ||
4387 | 1114 | local pat='scsi[0-9].*: .*' | ||
4388 | 1115 | if grep -qi "${pat}megaraid" "${file}"; then | ||
4389 | 1116 | echo 'LSI Logic MegaRAID SAS' | ||
4390 | 1117 | elif grep -q "Fusion MPT SAS" "${file}"; then | ||
4391 | 1118 | echo 'Fusion-MPT SAS' | ||
4392 | 1119 | elif grep -q "${pat}aacraid" "${file}"; then | ||
4393 | 1120 | echo 'AACRAID' | ||
4394 | 1121 | elif grep -q "${pat}3ware [0-9]* Storage Controller" "${file}"; then | ||
4395 | 1122 | echo '3Ware' | ||
4396 | 1123 | fi | ||
4397 | 1124 | } | ||
4398 | 1125 | |||
4399 | 1126 | find_raid_controller_lspci () { local PTFUNCNAME=find_raid_controller_lspci; | ||
4400 | 1127 | local file="$1" | ||
4401 | 1128 | if grep -q "RAID bus controller: LSI Logic / Symbios Logic MegaRAID SAS" "${file}"; then | ||
4402 | 1129 | echo 'LSI Logic MegaRAID SAS' | ||
4403 | 1130 | elif grep -q "Fusion-MPT SAS" "${file}"; then | ||
4404 | 1131 | echo 'Fusion-MPT SAS' | ||
4405 | 1132 | elif grep -q "RAID bus controller: LSI Logic / Symbios Logic Unknown" "${file}"; then | ||
4406 | 1133 | echo 'LSI Logic Unknown' | ||
4407 | 1134 | elif grep -q "RAID bus controller: Adaptec AAC-RAID" "${file}"; then | ||
4408 | 1135 | echo 'AACRAID' | ||
4409 | 1136 | elif grep -q "3ware [0-9]* Storage Controller" "${file}"; then | ||
4410 | 1137 | echo '3Ware' | ||
4411 | 1138 | elif grep -q "Hewlett-Packard Company Smart Array" "${file}"; then | ||
4412 | 1139 | echo 'HP Smart Array' | ||
4413 | 1140 | elif grep -q " RAID bus controller: " "${file}"; then | ||
4414 | 1141 | awk -F: '/RAID bus controller\:/ {print $3" "$5" "$6}' "${file}" | ||
4415 | 1142 | fi | ||
4416 | 1143 | } | ||
4417 | 1144 | |||
4418 | 1145 | schedulers_and_queue_size () { local PTFUNCNAME=schedulers_and_queue_size; | ||
4419 | 1146 | local file="$1" | ||
4420 | 1147 | |||
4421 | 1148 | local disks="$(ls /sys/block/ | grep -v -e ram -e loop -e 'fd[0-9]' | xargs echo)" | ||
4422 | 1149 | echo "internal::disks $disks" >> "$file" | ||
4423 | 1150 | |||
4424 | 1151 | for disk in $disks; do | ||
4425 | 1152 | if [ -e "/sys/block/${disk}/queue/scheduler" ]; then | ||
4426 | 1153 | echo "internal::${disk} $(cat /sys/block/${disk}/queue/scheduler | grep -o '\[.*\]') $(cat /sys/block/${disk}/queue/nr_requests)" >> "$file" | ||
4427 | 1154 | fdisk -l "/dev/${disk}" 2>/dev/null | ||
4428 | 1155 | fi | ||
4429 | 1156 | done | ||
4430 | 1157 | } | ||
4431 | 1158 | |||
4432 | 1159 | top_processes () { local PTFUNCNAME=top_processes; | ||
4433 | 1160 | if [ "$CMD_PRSTAT" ]; then | ||
4434 | 1161 | $CMD_PRSTAT | head | ||
4435 | 1162 | elif [ "$CMD_TOP" ]; then | ||
4436 | 1163 | local cmd="$CMD_TOP -bn 1" | ||
4437 | 1164 | if [ "${platform}" = "FreeBSD" ] \ | ||
4438 | 1165 | || [ "${platform}" = "NetBSD" ] \ | ||
4439 | 1166 | || [ "${platform}" = "OpenBSD" ]; then | ||
4440 | 1167 | cmd="$CMD_TOP -b -d 1" | ||
4441 | 1168 | fi | ||
4442 | 1169 | $cmd \ | ||
4443 | 1170 | | sed -e 's# *$##g' -e '/./{H;$!d;}' -e 'x;/PID/!d;' \ | ||
4444 | 1171 | | grep . \ | ||
4445 | 1172 | | head | ||
4446 | 1173 | fi | ||
4447 | 1174 | } | ||
4448 | 1175 | |||
4449 | 1176 | notable_processes_info () { local PTFUNCNAME=notable_processes_info; | ||
4450 | 1177 | local format="%5s %+2d %s\n" | ||
4451 | 1178 | local sshd_pid=$(ps -eo pid,args | awk '$2 ~ /\/usr\/sbin\/sshd/ { print $1; exit }') | ||
4452 | 1179 | |||
4453 | 1180 | echo " PID OOM COMMAND" | ||
4454 | 1181 | |||
4455 | 1182 | if [ "$sshd_pid" ]; then | ||
4456 | 1183 | printf "$format" "$sshd_pid" "$(get_oom_of_pid $sshd_pid)" "sshd" | ||
4457 | 1184 | else | ||
4458 | 1185 | printf "%5s %3s %s\n" "?" "?" "sshd doesn't appear to be running" | ||
4459 | 1186 | fi | ||
4460 | 1187 | |||
4461 | 1188 | local PTDEBUG="" | ||
4462 | 1189 | ps -eo pid,ucomm | grep '^[0-9]' | while read pid proc; do | ||
4463 | 1190 | [ "$sshd_pid" ] && [ "$sshd_pid" = "$pid" ] && continue | ||
4464 | 1191 | local oom="$(get_oom_of_pid $pid)" | ||
4465 | 1192 | if [ "$oom" ] && [ "$oom" != "?" ] && [ "$oom" = "-17" ]; then | ||
4466 | 1193 | printf "$format" "$pid" "$oom" "$proc" | ||
4467 | 1194 | fi | ||
4468 | 1195 | done | ||
4469 | 1196 | } | ||
4470 | 1197 | |||
4471 | 1198 | processor_info () { local PTFUNCNAME=processor_info; | ||
4472 | 1199 | local data_dir="$1" | ||
4473 | 1200 | if [ -f /proc/cpuinfo ]; then | ||
4474 | 1201 | cat /proc/cpuinfo > "$data_dir/proc_cpuinfo_copy" 2>/dev/null | ||
4475 | 1202 | elif [ "${platform}" = "SunOS" ]; then | ||
4476 | 1203 | $CMD_PSRINFO -v > "$data_dir/psrinfo_minus_v" | ||
4477 | 1204 | fi | ||
4478 | 1205 | } | ||
4479 | 1206 | |||
4480 | 1207 | propietary_raid_controller () { local PTFUNCNAME=propietary_raid_controller; | ||
4481 | 1208 | local file="$1" | ||
4482 | 1209 | local variable_file="$2" | ||
4483 | 1210 | local data_dir="$3" | ||
4484 | 1211 | local controller="$4" | ||
4485 | 1212 | |||
4486 | 1213 | notfound="" | ||
4487 | 1214 | if [ "${controller}" = "AACRAID" ]; then | ||
4488 | 1215 | if [ -z "$CMD_ARCCONF" ]; then | ||
4489 | 1216 | notfound="e.g. http://www.adaptec.com/en-US/support/raid/scsi_raid/ASR-2120S/" | ||
4490 | 1217 | elif $CMD_ARCCONF getconfig 1 > "$file" 2>/dev/null; then | ||
4491 | 1218 | echo "internal::raid_opt 1" >> "$variable_file" | ||
4492 | 1219 | fi | ||
4493 | 1220 | elif [ "${controller}" = "HP Smart Array" ]; then | ||
4494 | 1221 | if [ -z "$CMD_HPACUCLI" ]; then | ||
4495 | 1222 | notfound="your package repository or the manufacturer's website" | ||
4496 | 1223 | elif $CMD_HPACUCLI ctrl all show config > "$file" 2>/dev/null; then | ||
4497 | 1224 | echo "internal::raid_opt 2" >> "$variable_file" | ||
4498 | 1225 | fi | ||
4499 | 1226 | elif [ "${controller}" = "LSI Logic MegaRAID SAS" ]; then | ||
4500 | 1227 | if [ -z "$CMD_MEGACLI64" ]; then | ||
4501 | 1228 | notfound="your package repository or the manufacturer's website" | ||
4502 | 1229 | else | ||
4503 | 1230 | echo "internal::raid_opt 3" >> "$variable_file" | ||
4504 | 1231 | $CMD_MEGACLI64 -AdpAllInfo -aALL -NoLog > "$data_dir/lsi_megaraid_adapter_info.tmp" 2>/dev/null | ||
4505 | 1232 | $CMD_MEGACLI64 -AdpBbuCmd -GetBbuStatus -aALL -NoLog > "$data_dir/lsi_megaraid_bbu_status.tmp" 2>/dev/null | ||
4506 | 1233 | $CMD_MEGACLI64 -LdPdInfo -aALL -NoLog > "$data_dir/lsi_megaraid_devices.tmp" 2>/dev/null | ||
4507 | 1234 | fi | ||
4508 | 1235 | fi | ||
4509 | 1236 | |||
4510 | 1237 | if [ "${notfound}" ]; then | ||
4511 | 1238 | echo "internal::raid_opt 0" >> "$variable_file" | ||
4512 | 1239 | echo " RAID controller software not found; try getting it from" > "$file" | ||
4513 | 1240 | echo " ${notfound}" >> "$file" | ||
4514 | 1241 | fi | ||
4515 | 1242 | } | ||
4516 | 1243 | |||
4517 | 1244 | # ########################################################################### | ||
4518 | 1245 | # End collect_system_info package | ||
4519 | 1246 | # ########################################################################### | ||
4520 | 1247 | |||
4521 | 1248 | # ########################################################################### | ||
4522 | 1249 | # report_system_info package | ||
4523 | 1250 | # This package is a copy without comments from the original. The original | ||
4524 | 1251 | # with comments and its test file can be found in the Bazaar repository at, | ||
4525 | 1252 | # lib/bash/report_system_info.sh | ||
4526 | 1253 | # t/lib/bash/report_system_info.sh | ||
4527 | 1254 | # See https://launchpad.net/percona-toolkit for more information. | ||
4528 | 1255 | # ########################################################################### | ||
4529 | 1256 | |||
4530 | 1257 | |||
4531 | 1258 | set -u | ||
4532 | 1259 | |||
4533 | 172 | 1260 | ||
4553 | 173 | # ############################################################################## | 1261 | parse_proc_cpuinfo () { local PTFUNCNAME=parse_proc_cpuinfo; |
4554 | 174 | # Parse Linux's /proc/cpuinfo, which should be stored in $TMPDIR/percona-toolkit. | 1262 | local file="$1" |
4555 | 175 | # ############################################################################## | 1263 | local virtual="$(grep -c ^processor "${file}")"; |
4556 | 176 | parse_proc_cpuinfo () { | 1264 | local physical="$(grep 'physical id' "${file}" | sort -u | wc -l)"; |
4557 | 177 | local file=$1 | 1265 | local cores="$(grep 'cpu cores' "${file}" | head -n 1 | cut -d: -f2)"; |
4558 | 178 | # Physical processors are indicated by distinct 'physical id'. Virtual CPUs | 1266 | |
4559 | 179 | # are indicated by paragraphs -- one per paragraph. We assume that all | 1267 | [ "${physical}" = "0" ] && physical="${virtual}" |
4560 | 180 | # processors are identical, i.e. that there are not some processors with dual | 1268 | [ -z "${cores}" ] && cores=0 |
4561 | 181 | # cores and some with quad cores. | 1269 | |
4543 | 182 | virtual=$(grep -c ^processor $file); | ||
4544 | 183 | physical=$(grep 'physical id' $file | sort -u | wc -l); | ||
4545 | 184 | cores=$(grep 'cpu cores' $file | head -n 1 | cut -d: -f2); | ||
4546 | 185 | |||
4547 | 186 | # Older kernel won't have 'physical id' or 'cpu cores'. | ||
4548 | 187 | if [ "${physical}" = "0" ]; then physical=${virtual}; fi | ||
4549 | 188 | if [ -z "${cores}" ]; then cores=0; fi | ||
4550 | 189 | |||
4551 | 190 | # Test for HTT; cannot trust the 'ht' flag. If physical * cores < virtual, | ||
4552 | 191 | # then hyperthreading is in use. | ||
4562 | 192 | cores=$((${cores} * ${physical})); | 1270 | cores=$((${cores} * ${physical})); |
4563 | 1271 | local htt="" | ||
4564 | 193 | if [ ${cores} -gt 0 -a $cores -lt $virtual ]; then htt=yes; else htt=no; fi | 1272 | if [ ${cores} -gt 0 -a $cores -lt $virtual ]; then htt=yes; else htt=no; fi |
4565 | 194 | 1273 | ||
4566 | 195 | name_val "Processors" "physical = ${physical}, cores = ${cores}, virtual = ${virtual}, hyperthreading = ${htt}" | 1274 | name_val "Processors" "physical = ${physical}, cores = ${cores}, virtual = ${virtual}, hyperthreading = ${htt}" |
4567 | 196 | 1275 | ||
4597 | 197 | awk -F: '/cpu MHz/{print $2}' $file \ | 1276 | awk -F: '/cpu MHz/{print $2}' "${file}" \ |
4598 | 198 | | sort | uniq -c > "$file.unq" | 1277 | | sort | uniq -c > "$TMPDIR/parse_proc_cpuinfo_cpu.unq" |
4599 | 199 | name_val "Speeds" "$(group_concat "$file.unq")" | 1278 | name_val "Speeds" "$(group_concat "$TMPDIR/parse_proc_cpuinfo_cpu.unq")" |
4600 | 200 | 1279 | ||
4601 | 201 | awk -F: '/model name/{print $2}' $file \ | 1280 | awk -F: '/model name/{print $2}' "${file}" \ |
4602 | 202 | | sort | uniq -c > "$file.unq" | 1281 | | sort | uniq -c > "$TMPDIR/parse_proc_cpuinfo_model.unq" |
4603 | 203 | name_val "Models" "$(group_concat "$file.unq")" | 1282 | name_val "Models" "$(group_concat "$TMPDIR/parse_proc_cpuinfo_model.unq")" |
4604 | 204 | 1283 | ||
4605 | 205 | awk -F: '/cache size/{print $2}' $file \ | 1284 | awk -F: '/cache size/{print $2}' "${file}" \ |
4606 | 206 | | sort | uniq -c > "$file.unq" | 1285 | | sort | uniq -c > "$TMPDIR/parse_proc_cpuinfo_cache.unq" |
4607 | 207 | name_val "Caches" "$(group_concat "$file.unq")" | 1286 | name_val "Caches" "$(group_concat "$TMPDIR/parse_proc_cpuinfo_cache.unq")" |
4608 | 208 | } | 1287 | } |
4609 | 209 | 1288 | ||
4610 | 210 | # ############################################################################## | 1289 | parse_sysctl_cpu_freebsd() { local PTFUNCNAME=parse_sysctl_cpu_freebsd; |
4611 | 211 | # Parse sysctl -a output on FreeBSD, and format it as CPU info. The file is the | 1290 | local file="$1" |
4612 | 212 | # first argument. | 1291 | [ -e "$file" ] || return; |
4613 | 213 | # ############################################################################## | 1292 | local virtual="$(awk '/hw.ncpu/{print $2}' "$file")" |
4614 | 214 | parse_sysctl_cpu_freebsd() { | 1293 | name_val "Processors" "virtual = ${virtual}" |
4615 | 215 | virtual="$(awk '/hw.ncpu/{print $2}' "$1")" | 1294 | name_val "Speeds" "$(awk '/hw.clockrate/{print $2}' "$file")" |
4616 | 216 | name_val "Processors" "virtual = ${virtual}" | 1295 | name_val "Models" "$(awk -F: '/hw.model/{print substr($2, 2)}' "$file")" |
4617 | 217 | name_val "Speeds" "$(awk '/hw.clockrate/{print $2}' "$1")" | 1296 | } |
4618 | 218 | name_val "Models" "$(awk -F: '/hw.model/{print substr($2, 2)}' "$1")" | 1297 | |
4619 | 219 | } | 1298 | parse_sysctl_cpu_netbsd() { local PTFUNCNAME=parse_sysctl_cpu_netbsd; |
4620 | 220 | 1299 | local file="$1" | |
4621 | 221 | # ############################################################################## | 1300 | |
4622 | 222 | # Parse CPU info from psrinfo -v | 1301 | [ -e "$file" ] || return |
4623 | 223 | # ############################################################################## | 1302 | |
4624 | 224 | parse_psrinfo_cpus() { | 1303 | local virtual="$(awk '/hw.ncpu /{print $NF}' "$file")" |
4625 | 225 | name_val Processors $(grep -c 'Status of .* processor' "$1") | 1304 | name_val "Processors" "virtual = ${virtual}" |
4626 | 1305 | name_val "Models" "$(awk -F: '/hw.model/{print $3}' "$file")" | ||
4627 | 1306 | } | ||
4628 | 1307 | |||
4629 | 1308 | parse_sysctl_cpu_openbsd() { local PTFUNCNAME=parse_sysctl_cpu_openbsd; | ||
4630 | 1309 | local file="$1" | ||
4631 | 1310 | |||
4632 | 1311 | [ -e "$file" ] || return | ||
4633 | 1312 | |||
4634 | 1313 | name_val "Processors" "$(awk -F= '/hw.ncpu=/{print $2}' "$file")" | ||
4635 | 1314 | name_val "Speeds" "$(awk -F= '/hw.cpuspeed/{print $2}' "$file")" | ||
4636 | 1315 | name_val "Models" "$(awk -F= '/hw.model/{print substr($2, 1, index($2, " "))}' "$file")" | ||
4637 | 1316 | } | ||
4638 | 1317 | |||
4639 | 1318 | parse_psrinfo_cpus() { local PTFUNCNAME=parse_psrinfo_cpus; | ||
4640 | 1319 | local file="$1" | ||
4641 | 1320 | |||
4642 | 1321 | [ -e "$file" ] || return | ||
4643 | 1322 | |||
4644 | 1323 | name_val "Processors" "$(grep -c 'Status of .* processor' "$file")" | ||
4645 | 226 | awk '/operates at/ { | 1324 | awk '/operates at/ { |
4646 | 227 | start = index($0, " at ") + 4; | 1325 | start = index($0, " at ") + 4; |
4647 | 228 | end = length($0) - start - 4 | 1326 | end = length($0) - start - 4 |
4648 | 229 | print substr($0, start, end); | 1327 | print substr($0, start, end); |
4651 | 230 | }' "$1" | sort | uniq -c > $TMPDIR/percona-toolkit2 | 1328 | }' "$file" | sort | uniq -c > "$TMPDIR/parse_psrinfo_cpus.tmp" |
4652 | 231 | name_val "Speeds" "$(group_concat $TMPDIR/percona-toolkit2)" | 1329 | name_val "Speeds" "$(group_concat "$TMPDIR/parse_psrinfo_cpus.tmp")" |
4653 | 232 | } | 1330 | } |
4654 | 233 | 1331 | ||
4660 | 234 | # ############################################################################## | 1332 | parse_free_minus_b () { local PTFUNCNAME=parse_free_minus_b; |
4661 | 235 | # Parse the output of 'free -b' plus the contents of /proc/meminfo | 1333 | local file="$1" |
4662 | 236 | # ############################################################################## | 1334 | |
4663 | 237 | parse_free_minus_b () { | 1335 | [ -e "$file" ] || return |
4659 | 238 | local file=$1 | ||
4664 | 239 | 1336 | ||
4665 | 240 | local physical=$(awk '/Mem:/{print $3}' "${file}") | 1337 | local physical=$(awk '/Mem:/{print $3}' "${file}") |
4668 | 241 | local swap=$(awk '/Swap:/{print $3}' "${file}") | 1338 | local swap_alloc=$(awk '/Swap:/{print $2}' "${file}") |
4669 | 242 | local virtual=$(shorten $(($physical + $swap))) | 1339 | local swap_used=$(awk '/Swap:/{print $3}' "${file}") |
4670 | 1340 | local virtual=$(shorten $(($physical + $swap_used)) 1) | ||
4671 | 243 | 1341 | ||
4678 | 244 | name_val Total $(shorten $(awk '/Mem:/{print $2}' "${file}")) | 1342 | name_val "Total" $(shorten $(awk '/Mem:/{print $2}' "${file}") 1) |
4679 | 245 | name_val Free $(shorten $(awk '/Mem:/{print $4}' "${file}")) | 1343 | name_val "Free" $(shorten $(awk '/Mem:/{print $4}' "${file}") 1) |
4680 | 246 | name_val Used "physical = $(shorten ${physical}), swap = $(shorten ${swap}), virtual = ${virtual}" | 1344 | name_val "Used" "physical = $(shorten ${physical} 1), swap allocated = $(shorten ${swap_alloc} 1), swap used = $(shorten ${swap_used} 1), virtual = ${virtual}" |
4681 | 247 | name_val Buffers $(shorten $(awk '/Mem:/{print $6}' "${file}")) | 1345 | name_val "Buffers" $(shorten $(awk '/Mem:/{print $6}' "${file}") 1) |
4682 | 248 | name_val Caches $(shorten $(awk '/Mem:/{print $7}' "${file}")) | 1346 | name_val "Caches" $(shorten $(awk '/Mem:/{print $7}' "${file}") 1) |
4683 | 249 | name_val Dirty "$(awk '/Dirty:/ {print $2, $3}' "${file}")" | 1347 | name_val "Dirty" "$(awk '/Dirty:/ {print $2, $3}' "${file}")" |
4684 | 250 | } | 1348 | } |
4685 | 251 | 1349 | ||
4693 | 252 | # ############################################################################## | 1350 | parse_memory_sysctl_freebsd() { local PTFUNCNAME=parse_memory_sysctl_freebsd; |
4694 | 253 | # Parse FreeBSD memory info from sysctl output. | 1351 | local file="$1" |
4695 | 254 | # ############################################################################## | 1352 | |
4696 | 255 | parse_memory_sysctl_freebsd() { | 1353 | [ -e "$file" ] || return |
4697 | 256 | physical=$(awk '/hw.realmem:/{print $2}' "${1}") | 1354 | |
4698 | 257 | mem_hw=$(awk '/hw.physmem:/{print $2}' "${1}") | 1355 | local physical=$(awk '/hw.realmem:/{print $2}' "${file}") |
4699 | 258 | mem_used=$(awk ' | 1356 | local mem_hw=$(awk '/hw.physmem:/{print $2}' "${file}") |
4700 | 1357 | local mem_used=$(awk ' | ||
4701 | 259 | /hw.physmem/ { mem_hw = $2; } | 1358 | /hw.physmem/ { mem_hw = $2; } |
4702 | 260 | /vm.stats.vm.v_inactive_count/ { mem_inactive = $2; } | 1359 | /vm.stats.vm.v_inactive_count/ { mem_inactive = $2; } |
4703 | 261 | /vm.stats.vm.v_cache_count/ { mem_cache = $2; } | 1360 | /vm.stats.vm.v_cache_count/ { mem_cache = $2; } |
4704 | @@ -267,50 +1366,66 @@ | |||
4705 | 267 | mem_free *= pagesize; | 1366 | mem_free *= pagesize; |
4706 | 268 | print mem_hw - mem_inactive - mem_cache - mem_free; | 1367 | print mem_hw - mem_inactive - mem_cache - mem_free; |
4707 | 269 | } | 1368 | } |
4719 | 270 | ' "$1"); | 1369 | ' "$file"); |
4720 | 271 | name_val Total $(shorten ${mem_hw} 1) | 1370 | name_val "Total" $(shorten ${mem_hw} 1) |
4721 | 272 | name_val Virtual $(shorten ${physical} 1) | 1371 | name_val "Virtual" $(shorten ${physical} 1) |
4722 | 273 | name_val Used $(shorten ${mem_used} 1) | 1372 | name_val "Used" $(shorten ${mem_used} 1) |
4723 | 274 | } | 1373 | } |
4724 | 275 | 1374 | ||
4725 | 276 | # ############################################################################## | 1375 | parse_memory_sysctl_netbsd() { local PTFUNCNAME=parse_memory_sysctl_netbsd; |
4726 | 277 | # Parse memory devices from the output of 'dmidecode'. | 1376 | local file="$1" |
4727 | 278 | # ############################################################################## | 1377 | local swapctl_file="$2" |
4728 | 279 | parse_dmidecode_mem_devices () { | 1378 | |
4729 | 280 | local file=$1 | 1379 | [ -e "$file" -a -e "$swapctl_file" ] || return |
4730 | 1380 | |||
4731 | 1381 | local swap_mem="$(echo "$(awk '{print $2;}' "$swapctl_file")*512" | bc -l)" | ||
4732 | 1382 | name_val "Total" $(shorten "$(awk '/hw.physmem /{print $NF}' "$file")" 1) | ||
4733 | 1383 | name_val "User" $(shorten "$(awk '/hw.usermem /{print $NF}' "$file")" 1) | ||
4734 | 1384 | name_val "Swap" $(shorten ${swap_mem} 1) | ||
4735 | 1385 | } | ||
4736 | 1386 | |||
4737 | 1387 | parse_memory_sysctl_openbsd() { local PTFUNCNAME=parse_memory_sysctl_openbsd; | ||
4738 | 1388 | local file="$1" | ||
4739 | 1389 | local swapctl_file="$2" | ||
4740 | 1390 | |||
4741 | 1391 | [ -e "$file" -a -e "$swapctl_file" ] || return | ||
4742 | 1392 | |||
4743 | 1393 | local swap_mem="$(echo "$(awk '{print $2;}' "$swapctl_file")*512" | bc -l)" | ||
4744 | 1394 | name_val "Total" $(shorten "$(awk -F= '/hw.physmem/{print $2}' "$file")" 1) | ||
4745 | 1395 | name_val "User" $(shorten "$(awk -F= '/hw.usermem/{print $2}' "$file")" 1) | ||
4746 | 1396 | name_val "Swap" $(shorten ${swap_mem} 1) | ||
4747 | 1397 | } | ||
4748 | 1398 | |||
4749 | 1399 | parse_dmidecode_mem_devices () { local PTFUNCNAME=parse_dmidecode_mem_devices; | ||
4750 | 1400 | local file="$1" | ||
4751 | 1401 | |||
4752 | 1402 | [ -e "$file" ] || return | ||
4753 | 1403 | |||
4754 | 281 | echo " Locator Size Speed Form Factor Type Type Detail" | 1404 | echo " Locator Size Speed Form Factor Type Type Detail" |
4755 | 282 | echo " ========= ======== ================= ============= ============= ===========" | 1405 | echo " ========= ======== ================= ============= ============= ===========" |
4756 | 283 | # Print paragraphs containing 'Memory Device\n', extract the desired bits, | ||
4757 | 284 | # concatenate them into one long line, then format as a table. The data | ||
4758 | 285 | # comes out in this order for each paragraph: | ||
4759 | 286 | # $2 Size 2048 MB | ||
4760 | 287 | # $3 Form Factor <OUT OF SPEC> | ||
4761 | 288 | # $4 Locator DIMM1 | ||
4762 | 289 | # $5 Type <OUT OF SPEC> | ||
4763 | 290 | # $6 Type Detail Synchronous | ||
4764 | 291 | # $7 Speed 667 MHz (1.5 ns) | ||
4765 | 292 | sed -e '/./{H;$!d;}' \ | 1406 | sed -e '/./{H;$!d;}' \ |
4766 | 293 | -e 'x;/Memory Device\n/!d;' \ | 1407 | -e 'x;/Memory Device\n/!d;' \ |
4767 | 294 | -e 's/: /:/g' \ | 1408 | -e 's/: /:/g' \ |
4768 | 295 | -e 's/</{/g' \ | 1409 | -e 's/</{/g' \ |
4769 | 296 | -e 's/>/}/g' \ | 1410 | -e 's/>/}/g' \ |
4770 | 297 | -e 's/[ \t]*\n/\n/g' \ | 1411 | -e 's/[ \t]*\n/\n/g' \ |
4772 | 298 | $file \ | 1412 | "${file}" \ |
4773 | 299 | | awk -F: '/Size|Type|Form.Factor|Type.Detail|[^ ]Locator/{printf("|%s", $2)}/Speed/{print "|" $2}' \ | 1413 | | awk -F: '/Size|Type|Form.Factor|Type.Detail|[^ ]Locator/{printf("|%s", $2)}/Speed/{print "|" $2}' \ |
4774 | 300 | | sed -e 's/No Module Installed/{EMPTY}/' \ | 1414 | | sed -e 's/No Module Installed/{EMPTY}/' \ |
4775 | 301 | | sort \ | 1415 | | sort \ |
4776 | 302 | | awk -F'|' '{printf(" %-9s %-8s %-17s %-13s %-13s %-8s\n", $4, $2, $7, $3, $5, $6);}' | 1416 | | awk -F'|' '{printf(" %-9s %-8s %-17s %-13s %-13s %-8s\n", $4, $2, $7, $3, $5, $6);}' |
4777 | 303 | } | 1417 | } |
4778 | 304 | 1418 | ||
4783 | 305 | # ############################################################################## | 1419 | parse_ip_s_link () { local PTFUNCNAME=parse_ip_s_link; |
4784 | 306 | # Parse the output of 'netstat -antp' | 1420 | local file="$1" |
4785 | 307 | # ############################################################################## | 1421 | |
4786 | 308 | parse_ip_s_link () { | 1422 | [ -e "$file" ] || return |
4787 | 1423 | |||
4788 | 309 | echo " interface rx_bytes rx_packets rx_errors tx_bytes tx_packets tx_errors" | 1424 | echo " interface rx_bytes rx_packets rx_errors tx_bytes tx_packets tx_errors" |
4789 | 310 | echo " ========= ========= ========== ========== ========== ========== ==========" | 1425 | echo " ========= ========= ========== ========== ========== ========== ==========" |
4790 | 311 | 1426 | ||
4791 | 312 | awk "/^[1-9][0-9]*:/ { | 1427 | awk "/^[1-9][0-9]*:/ { |
4793 | 313 | save[\"iface\"] = substr(\$2, 0, index(\$2, \":\") - 1); | 1428 | save[\"iface\"] = substr(\$2, 1, index(\$2, \":\") - 1); |
4794 | 314 | new = 1; | 1429 | new = 1; |
4795 | 315 | } | 1430 | } |
4796 | 316 | \$0 !~ /[^0-9 ]/ { | 1431 | \$0 !~ /[^0-9 ]/ { |
4797 | @@ -324,20 +1439,48 @@ | |||
4798 | 324 | fuzzy_var = \$1; ${fuzzy_formula} tx_bytes = fuzzy_var; | 1439 | fuzzy_var = \$1; ${fuzzy_formula} tx_bytes = fuzzy_var; |
4799 | 325 | fuzzy_var = \$2; ${fuzzy_formula} tx_packets = fuzzy_var; | 1440 | fuzzy_var = \$2; ${fuzzy_formula} tx_packets = fuzzy_var; |
4800 | 326 | fuzzy_var = \$3; ${fuzzy_formula} tx_errors = fuzzy_var; | 1441 | fuzzy_var = \$3; ${fuzzy_formula} tx_errors = fuzzy_var; |
4811 | 327 | printf \" %-8s %10d %10d %10d %10d %10d %10d\\n\", save[\"iface\"], save[\"bytes\"], save[\"packs\"], save[\"errs\"], tx_bytes, tx_packets, tx_errors; | 1442 | printf \" %-8s %10.0f %10.0f %10.0f %10.0f %10.0f %10.0f\\n\", save[\"iface\"], save[\"bytes\"], save[\"packs\"], save[\"errs\"], tx_bytes, tx_packets, tx_errors; |
4812 | 328 | } | 1443 | } |
4813 | 329 | }" $@ | 1444 | }" "$file" |
4814 | 330 | } | 1445 | } |
4815 | 331 | 1446 | ||
4816 | 332 | # ############################################################################## | 1447 | parse_ethtool () { |
4817 | 333 | # Parse the output of 'netstat -antp' which should be in $TMPDIR/percona-toolkit. | 1448 | local file="$1" |
4818 | 334 | # ############################################################################## | 1449 | |
4819 | 335 | parse_netstat () { | 1450 | [ -e "$file" ] || return |
4820 | 336 | local file=$1 | 1451 | |
4821 | 1452 | echo " Device Speed Duplex" | ||
4822 | 1453 | echo " ========= ========= =========" | ||
4823 | 1454 | |||
4824 | 1455 | |||
4825 | 1456 | awk ' | ||
4826 | 1457 | /^Settings for / { | ||
4827 | 1458 | device = substr($3, 1, index($3, ":") ? index($3, ":")-1 : length($3)); | ||
4828 | 1459 | device_names[device] = device; | ||
4829 | 1460 | } | ||
4830 | 1461 | /Speed:/ { devices[device ",speed"] = $2 } | ||
4831 | 1462 | /Duplex:/ { devices[device ",duplex"] = $2 } | ||
4832 | 1463 | END { | ||
4833 | 1464 | for ( device in device_names ) { | ||
4834 | 1465 | printf(" %-10s %-10s %-10s\n", | ||
4835 | 1466 | device, | ||
4836 | 1467 | devices[device ",speed"], | ||
4837 | 1468 | devices[device ",duplex"]); | ||
4838 | 1469 | } | ||
4839 | 1470 | } | ||
4840 | 1471 | ' "$file" | ||
4841 | 1472 | |||
4842 | 1473 | } | ||
4843 | 1474 | |||
4844 | 1475 | parse_netstat () { local PTFUNCNAME=parse_netstat; | ||
4845 | 1476 | local file="$1" | ||
4846 | 1477 | |||
4847 | 1478 | [ -e "$file" ] || return | ||
4848 | 1479 | |||
4849 | 337 | echo " Connections from remote IP addresses" | 1480 | echo " Connections from remote IP addresses" |
4850 | 338 | awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ { | 1481 | awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ { |
4853 | 339 | print substr($5, 0, index($5, ":") - 1); | 1482 | print substr($5, 1, index($5, ":") - 1); |
4854 | 340 | }' $file | sort | uniq -c \ | 1483 | }' "${file}" | sort | uniq -c \ |
4855 | 341 | | awk "{ | 1484 | | awk "{ |
4856 | 342 | fuzzy_var=\$1; | 1485 | fuzzy_var=\$1; |
4857 | 343 | ${fuzzy_formula} | 1486 | ${fuzzy_formula} |
4858 | @@ -346,8 +1489,8 @@ | |||
4859 | 346 | | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 | 1489 | | sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 |
4860 | 347 | echo " Connections to local IP addresses" | 1490 | echo " Connections to local IP addresses" |
4861 | 348 | awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ { | 1491 | awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ { |
4864 | 349 | print substr($4, 0, index($4, ":") - 1); | 1492 | print substr($4, 1, index($4, ":") - 1); |
4865 | 350 | }' $file | sort | uniq -c \ | 1493 | }' "${file}" | sort | uniq -c \ |
4866 | 351 | | awk "{ | 1494 | | awk "{ |
4867 | 352 | fuzzy_var=\$1; | 1495 | fuzzy_var=\$1; |
4868 | 353 | ${fuzzy_formula} | 1496 | ${fuzzy_formula} |
4869 | @@ -357,7 +1500,7 @@ | |||
4870 | 357 | echo " Connections to top 10 local ports" | 1500 | echo " Connections to top 10 local ports" |
4871 | 358 | awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ { | 1501 | awk '$1 ~ /^tcp/ && $5 ~ /^[1-9]/ { |
4872 | 359 | print substr($4, index($4, ":") + 1); | 1502 | print substr($4, index($4, ":") + 1); |
4874 | 360 | }' $file | sort | uniq -c | sort -rn | head -n10 \ | 1503 | }' "${file}" | sort | uniq -c | sort -rn | head -n10 \ |
4875 | 361 | | awk "{ | 1504 | | awk "{ |
4876 | 362 | fuzzy_var=\$1; | 1505 | fuzzy_var=\$1; |
4877 | 363 | ${fuzzy_formula} | 1506 | ${fuzzy_formula} |
4878 | @@ -366,7 +1509,7 @@ | |||
4879 | 366 | echo " States of connections" | 1509 | echo " States of connections" |
4880 | 367 | awk '$1 ~ /^tcp/ { | 1510 | awk '$1 ~ /^tcp/ { |
4881 | 368 | print $6; | 1511 | print $6; |
4883 | 369 | }' $file | sort | uniq -c | sort -rn \ | 1512 | }' "${file}" | sort | uniq -c | sort -rn \ |
4884 | 370 | | awk "{ | 1513 | | awk "{ |
4885 | 371 | fuzzy_var=\$1; | 1514 | fuzzy_var=\$1; |
4886 | 372 | ${fuzzy_formula} | 1515 | ${fuzzy_formula} |
4887 | @@ -374,19 +1517,13 @@ | |||
4888 | 374 | }" | sort | 1517 | }" | sort |
4889 | 375 | } | 1518 | } |
4890 | 376 | 1519 | ||
4904 | 377 | # ############################################################################## | 1520 | parse_filesystems () { local PTFUNCNAME=parse_filesystems; |
4905 | 378 | # Parse the joined output of 'mount' and 'df -hP'. $1 = file; $2 = ostype. | 1521 | local file="$1" |
4906 | 379 | # ############################################################################## | 1522 | local platform="$2" |
4907 | 380 | parse_filesystems () { | 1523 | |
4908 | 381 | # Filesystem names and mountpoints can be very long. We try to align things | 1524 | [ -e "$file" ] || return |
4909 | 382 | # as nicely as possible by making columns only as wide as needed. This | 1525 | |
4910 | 383 | # requires two passes through the file. The first pass finds the max size of | 1526 | local spec="$(awk " |
4898 | 384 | # these columns and prints out a printf spec, and the second prints out the | ||
4899 | 385 | # file nicely aligned. | ||
4900 | 386 | local file=$1 | ||
4901 | 387 | local platform=$2 | ||
4902 | 388 | |||
4903 | 389 | local spec=$(awk " | ||
4911 | 390 | BEGIN { | 1527 | BEGIN { |
4912 | 391 | device = 10; | 1528 | device = 10; |
4913 | 392 | fstype = 4; | 1529 | fstype = 4; |
4914 | @@ -396,7 +1533,7 @@ | |||
4915 | 396 | f_device = \$1; | 1533 | f_device = \$1; |
4916 | 397 | f_fstype = \$10; | 1534 | f_fstype = \$10; |
4917 | 398 | f_options = substr(\$11, 2, length(\$11) - 2); | 1535 | f_options = substr(\$11, 2, length(\$11) - 2); |
4919 | 399 | if ( \"$2\" == \"FreeBSD\" ) { | 1536 | if ( \"$2\" ~ /(Free|Open|Net)BSD/ ) { |
4920 | 400 | f_fstype = substr(\$9, 2, length(\$9) - 2); | 1537 | f_fstype = substr(\$9, 2, length(\$9) - 2); |
4921 | 401 | f_options = substr(\$0, index(\$0, \",\") + 2); | 1538 | f_options = substr(\$0, index(\$0, \",\") + 2); |
4922 | 402 | f_options = substr(f_options, 1, length(f_options) - 1); | 1539 | f_options = substr(f_options, 1, length(f_options) - 1); |
4923 | @@ -414,7 +1551,7 @@ | |||
4924 | 414 | END{ | 1551 | END{ |
4925 | 415 | print \"%-\" device \"s %5s %4s %-\" fstype \"s %-\" options \"s %s\"; | 1552 | print \"%-\" device \"s %5s %4s %-\" fstype \"s %-\" options \"s %s\"; |
4926 | 416 | } | 1553 | } |
4928 | 417 | " $file) | 1554 | " "${file}")" |
4929 | 418 | 1555 | ||
4930 | 419 | awk " | 1556 | awk " |
4931 | 420 | BEGIN { | 1557 | BEGIN { |
4932 | @@ -424,22 +1561,21 @@ | |||
4933 | 424 | { | 1561 | { |
4934 | 425 | f_fstype = \$10; | 1562 | f_fstype = \$10; |
4935 | 426 | f_options = substr(\$11, 2, length(\$11) - 2); | 1563 | f_options = substr(\$11, 2, length(\$11) - 2); |
4937 | 427 | if ( \"$2\" == \"FreeBSD\" ) { | 1564 | if ( \"$2\" ~ /(Free|Open|Net)BSD/ ) { |
4938 | 428 | f_fstype = substr(\$9, 2, length(\$9) - 2); | 1565 | f_fstype = substr(\$9, 2, length(\$9) - 2); |
4939 | 429 | f_options = substr(\$0, index(\$0, \",\") + 2); | 1566 | f_options = substr(\$0, index(\$0, \",\") + 2); |
4940 | 430 | f_options = substr(f_options, 1, length(f_options) - 1); | 1567 | f_options = substr(f_options, 1, length(f_options) - 1); |
4941 | 431 | } | 1568 | } |
4942 | 432 | printf spec, \$1, \$2, \$5, f_fstype, f_options, \$6; | 1569 | printf spec, \$1, \$2, \$5, f_fstype, f_options, \$6; |
4943 | 433 | } | 1570 | } |
4945 | 434 | " $file | 1571 | " "${file}" |
4946 | 435 | } | 1572 | } |
4947 | 436 | 1573 | ||
4954 | 437 | # ############################################################################## | 1574 | parse_fdisk () { local PTFUNCNAME=parse_fdisk; |
4955 | 438 | # Parse the output of fdisk -l, which should be in $TMPDIR/percona-toolkit; there might be | 1575 | local file="$1" |
4956 | 439 | # multiple fdisk -l outputs in the file. | 1576 | |
4957 | 440 | # ############################################################################## | 1577 | [ -e "$file" -a -s "$file" ] || return |
4958 | 441 | parse_fdisk () { | 1578 | |
4953 | 442 | local file=$1 | ||
4959 | 443 | awk ' | 1579 | awk ' |
4960 | 444 | BEGIN { | 1580 | BEGIN { |
4961 | 445 | format="%-12s %4s %10s %10s %18s\n"; | 1581 | format="%-12s %4s %10s %10s %18s\n"; |
4962 | @@ -465,128 +1601,55 @@ | |||
4963 | 465 | } | 1601 | } |
4964 | 466 | printf(format, $1, "Part", start, end, sprintf("%.0f", (end - start) * units)); | 1602 | printf(format, $1, "Part", start, end, sprintf("%.0f", (end - start) * units)); |
4965 | 467 | } | 1603 | } |
4966 | 468 | ' $file | ||
4967 | 469 | } | ||
4968 | 470 | |||
4969 | 471 | # ############################################################################## | ||
4970 | 472 | # Parse the output of dmesg, which should be in $TMPDIR/percona-toolkit, and detect | ||
4971 | 473 | # virtualization. | ||
4972 | 474 | # ############################################################################## | ||
4973 | 475 | parse_virtualization_dmesg () { | ||
4974 | 476 | local file=$1 | ||
4975 | 477 | if grep -qi -e vmware -e vmxnet -e 'paravirtualized kernel on vmi' $file; then | ||
4976 | 478 | echo "VMWare"; | ||
4977 | 479 | elif grep -qi -e 'paravirtualized kernel on xen' -e 'Xen virtual console' $file; then | ||
4978 | 480 | echo "Xen"; | ||
4979 | 481 | elif grep -qi qemu $file; then | ||
4980 | 482 | echo "QEmu"; | ||
4981 | 483 | elif grep -qi 'paravirtualized kernel on KVM' $file; then | ||
4982 | 484 | echo "KVM"; | ||
4983 | 485 | elif grep -q VBOX $file; then | ||
4984 | 486 | echo "VirtualBox"; | ||
4985 | 487 | elif grep -qi 'hd.: Virtual .., ATA.*drive' $file; then | ||
4986 | 488 | echo "Microsoft VirtualPC"; | ||
4987 | 489 | fi | ||
4988 | 490 | } | ||
4989 | 491 | |||
4990 | 492 | # ############################################################################## | ||
4991 | 493 | # Try to figure out if a system is a guest by looking at prtdiag, smbios, etc. | ||
4992 | 494 | # ############################################################################## | ||
4993 | 495 | parse_virtualization_generic() { | ||
4994 | 496 | if grep -i -e virtualbox "$1" >/dev/null; then | ||
4995 | 497 | echo VirtualBox | ||
4996 | 498 | elif grep -i -e vmware "$1" >/dev/null; then | ||
4997 | 499 | echo VMWare | ||
4998 | 500 | fi | ||
4999 | 501 | } | ||
5000 | 502 |
The diff has been truncated for viewing.
pt-summary and pt-mysql-summary integration tests fail on Debian 6.