mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-26 05:58:16 +00:00
Change --disk-byte-limit to --disk-bytes-free and --disk-pct-limit to --disk-pct-free.
This commit is contained in:
96
bin/pt-stalk
96
bin/pt-stalk
@@ -198,6 +198,7 @@ _eval_po() {
|
||||
local opt=""
|
||||
local default_val=""
|
||||
local neg=0
|
||||
local size=0
|
||||
while read key val; do
|
||||
case "$key" in
|
||||
long)
|
||||
@@ -209,6 +210,7 @@ _eval_po() {
|
||||
"short form")
|
||||
;;
|
||||
type)
|
||||
[ "$val" = "size" ] && size=1
|
||||
;;
|
||||
desc)
|
||||
;;
|
||||
@@ -235,6 +237,10 @@ _eval_po() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $size -eq 1 -a -n "$default_val" ]; then
|
||||
default_val=$(size_to_bytes $default_val)
|
||||
fi
|
||||
|
||||
eval "OPT_${opt}"="$default_val"
|
||||
done
|
||||
|
||||
@@ -275,6 +281,7 @@ _parse_command_line() {
|
||||
local opt_is_negated=""
|
||||
local real_opt=""
|
||||
local required_arg=""
|
||||
local spec=""
|
||||
|
||||
for opt in "$@"; do
|
||||
if [ "$opt" = "--" -o "$opt" = "----" ]; then
|
||||
@@ -360,6 +367,10 @@ _parse_command_line() {
|
||||
if [ "$opt_is_ok" ]; then
|
||||
opt=$(cat "$spec" | grep '^long:' | cut -d':' -f2 | sed 's/-/_/g' | tr [:lower:] [:upper:])
|
||||
|
||||
if grep "^type:size" "$spec" >/dev/null; then
|
||||
val=$(size_to_bytes $val)
|
||||
fi
|
||||
|
||||
eval "OPT_$opt"="'$val'"
|
||||
|
||||
opt=""
|
||||
@@ -369,10 +380,16 @@ _parse_command_line() {
|
||||
opt_is_negated=""
|
||||
real_opt=""
|
||||
required_arg=""
|
||||
spec=""
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
size_to_bytes() {
|
||||
local size="$1"
|
||||
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")};'
|
||||
}
|
||||
|
||||
# ###########################################################################
|
||||
# End parse_options package
|
||||
# ###########################################################################
|
||||
@@ -458,33 +475,37 @@ disk_space() {
|
||||
|
||||
check_disk_space() {
|
||||
local file="$1"
|
||||
local mb="${2:-0}"
|
||||
local pc="${3:-0}"
|
||||
local mb_margin="${4:-0}"
|
||||
local min_free_bytes="${2:-0}"
|
||||
local min_free_pct="${3:-0}"
|
||||
local bytes_margin="${4:-0}"
|
||||
|
||||
local kb=$(($mb * 1024))
|
||||
local kb_margin=$(($mb_margin * 1024))
|
||||
local used_bytes=$(cat "$file" | awk '/^\//{print $3 * 1024}');
|
||||
local free_bytes=$(cat "$file" | awk '/^\//{print $4 * 1024}');
|
||||
local pct_used=$(cat "$file" | awk '/^\//{print $5}' | sed -e 's/%//g');
|
||||
local pct_free=$((100 - $pct_used))
|
||||
|
||||
local kb_used=$(cat "$file" | awk '/^\//{print $3}');
|
||||
local kb_free=$(cat "$file" | awk '/^\//{print $4}');
|
||||
local pc_used=$(cat "$file" | awk '/^\//{print $5}' | sed -e 's/%//g');
|
||||
local real_free_bytes=$free_bytes
|
||||
local real_pct_free=$pct_free
|
||||
|
||||
if [ "$kb_margin" -gt "0" ]; then
|
||||
local kb_total=$(($kb_used + $kb_free))
|
||||
if [ $bytes_margin -gt 0 ]; then
|
||||
used_bytes=$(($used_bytes + $bytes_margin))
|
||||
free_bytes=$(($free_bytes - $bytes_margin))
|
||||
pct_used=$(awk "BEGIN { printf(\"%d\", ($used_bytes/($used_bytes + $free_bytes)) * 100) }")
|
||||
|
||||
kb_used=$(($kb_used + $kb_margin))
|
||||
kb_free=$(($kb_free - $kb_margin))
|
||||
pc_used=$(awk "BEGIN { printf(\"%d\", $kb_used/$kb_total * 100) }")
|
||||
pct_free=$((100 - $pct_used))
|
||||
fi
|
||||
|
||||
local pc_free=$((100 - $pc_used))
|
||||
if [ $free_bytes -lt $min_free_bytes -o $pct_free -lt $min_free_pct ]; then
|
||||
warn "Not enough free disk space:
|
||||
Limit: ${min_free_pct}% free, ${min_free_bytes} bytes free
|
||||
Actual: ${real_pct_free}% free, ${real_free_bytes} bytes free (- $bytes_margin bytes margin)
|
||||
"
|
||||
cat "$file" >&2
|
||||
|
||||
if [ "$kb_free" -le "$kb" -o "$pc_free" -le "$pc" ]; then
|
||||
warn "Not enough free disk space: ${pc_free}% free, ${kb_free} KB free; wanted more than ${pc}% free or ${kb} KB free"
|
||||
return 1
|
||||
return 1 # not enough disk space
|
||||
fi
|
||||
|
||||
return 0
|
||||
return 0 # disk space is OK
|
||||
}
|
||||
|
||||
# ###########################################################################
|
||||
@@ -674,8 +695,8 @@ collect() {
|
||||
disk_space $d > $d/$p-disk-space
|
||||
check_disk_space \
|
||||
$d/$p-disk-space \
|
||||
"$OPT_DISK_BYTE_LIMIT" \
|
||||
"$OPT_DISK_PCT_LIMIT" \
|
||||
"$OPT_DISK_BYTES_FREE" \
|
||||
"$OPT_DISK_PCT_FREE" \
|
||||
|| break
|
||||
|
||||
sleep $(date +%s.%N | awk '{print 1 - ($1 % 1)}')
|
||||
@@ -980,16 +1001,16 @@ stalk() {
|
||||
|
||||
# Check if we'll have enough disk space to collect. Disk space
|
||||
# is also checked every interval while collecting.
|
||||
local margin="20" # default 20M margin, unless:
|
||||
local margin="20971520" # default 20M margin, unless:
|
||||
if [ -n "$last_prefix" ]; then
|
||||
margin=$(du -mc "$OPT_DEST"/"$last_prefix"-* | tail -n 1 | awk '{print $1'})
|
||||
fi
|
||||
disk_space "$OPT_DEST" > "$OPT_DEST/$prefix-disk-space"
|
||||
check_disk_space \
|
||||
"$OPT_DEST/$prefix-disk-space" \
|
||||
"$OPT_DISK_BYTE_LIMIT" \
|
||||
"$OPT_DISK_PCT_LIMIT" \
|
||||
"$margin" # real used MB + margin MB
|
||||
"$OPT_DISK_BYTES_FREE" \
|
||||
"$OPT_DISK_PCT_FREE" \
|
||||
"$margin"
|
||||
if [ $? -eq 0 ]; then
|
||||
# There should be enough disk space, so collect.
|
||||
log "$msg" >> "$OPT_DEST/$prefix-trigger"
|
||||
@@ -1313,29 +1334,34 @@ type: string; default: /var/lib/pt-stalk
|
||||
Where to store the diagnostic data. Each time the tool collects data, it writes
|
||||
to a new set of files, which are named with the current system timestamp.
|
||||
|
||||
=item --disk-byte-limit
|
||||
=item --disk-bytes-free
|
||||
|
||||
type: int; default: 100
|
||||
type: size; default: 100M
|
||||
|
||||
Don't collect data unless the destination disk has this much free space. This
|
||||
prevents the tool from filling up the disk with diagnostic data.
|
||||
Don't collect data if the disk has less than this much free space.
|
||||
This prevents the tool from filling up the disk with diagnostic data.
|
||||
|
||||
If the destination directory contains a previously captured sample of data, the
|
||||
tool will measure its size and use that as an estimate of how much data is
|
||||
If the L<"--dest"> directory contains a previously captured sample of data,
|
||||
the tool will measure its size and use that as an estimate of how much data is
|
||||
likely to be gathered this time, too. It will then be even more pessimistic,
|
||||
and will refuse to collect data unless the disk has enough free space to hold
|
||||
the sample and still have the desired amount of free space. For example, if
|
||||
you'd like 100MB of free space and the previous diagnostic sample consumed
|
||||
100MB, the tool won't collect any data unless the disk has 200MB free.
|
||||
|
||||
=item --disk-pct-limit
|
||||
Valid size value suffixes are k, M, G, and T.
|
||||
|
||||
=item --disk-pct-free
|
||||
|
||||
type: int; default: 5
|
||||
|
||||
Don't collect data unless the disk has at least this percent free space. This
|
||||
option works similarly to --disk-byte-limit, but specifies a percentage margin
|
||||
of safety instead of a byte margin of safety. The tool honors both options, and
|
||||
will not collect any data unless both margins are satisfied.
|
||||
Don't collect data if the disk has less than this percent free space.
|
||||
This prevents the tool from filling up the disk with diagnostic data.
|
||||
|
||||
This option works similarly to L<"--disk-bytes-free"> but specifies a
|
||||
percentage margin of safety instead of a bytes margin of safety.
|
||||
The tool honors both options, and will not collect any data unless both
|
||||
margins are satisfied.
|
||||
|
||||
=item --function
|
||||
|
||||
|
@@ -178,8 +178,8 @@ collect() {
|
||||
disk_space $d > $d/$p-disk-space
|
||||
check_disk_space \
|
||||
$d/$p-disk-space \
|
||||
"$OPT_DISK_BYTE_LIMIT" \
|
||||
"$OPT_DISK_PCT_LIMIT" \
|
||||
"$OPT_DISK_BYTES_FREE" \
|
||||
"$OPT_DISK_PCT_FREE" \
|
||||
|| break
|
||||
|
||||
# Synchronize ourselves onto the clock tick, so the sleeps are 1-second
|
||||
|
@@ -15,7 +15,7 @@ source "$LIB_DIR/safeguards.sh"
|
||||
source "$LIB_DIR/alt_cmds.sh"
|
||||
source "$LIB_DIR/collect.sh"
|
||||
|
||||
parse_options "$T_LIB_DIR/samples/bash/po002.sh" --run-time 1 -- --defaults-file=/tmp/12345/my.sandbox.cnf
|
||||
parse_options "$BIN_DIR/pt-stalk" --run-time 1 -- --defaults-file=/tmp/12345/my.sandbox.cnf
|
||||
|
||||
# Prefix (with path) for the collect files.
|
||||
local p="$TMPDIR/collect/2011_12_05"
|
||||
@@ -112,7 +112,7 @@ is "$iters" "1" "1 iteration/1s run time"
|
||||
# Try longer run time.
|
||||
# ###########################################################################
|
||||
|
||||
parse_options "$T_LIB_DIR/samples/bash/po002.sh" --run-time 2 -- --defaults-file=/tmp/12345/my.sandbox.cnf
|
||||
parse_options "$BIN_DIR/pt-stalk" --run-time 2 -- --defaults-file=/tmp/12345/my.sandbox.cnf
|
||||
|
||||
rm $TMPDIR/collect/*
|
||||
|
||||
|
@@ -1,212 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
:
|
||||
|
||||
# ############################################################################
|
||||
# Documentation
|
||||
# ############################################################################
|
||||
:<<'DOCUMENTATION'
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
pt-stalk - Wait for a condition to occur then begin collecting data.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over
|
||||
|
||||
=item --collect
|
||||
|
||||
default: yes; negatable: yes
|
||||
|
||||
Collect system information.
|
||||
|
||||
=item --collect-gdb
|
||||
|
||||
Collect GDB stacktraces.
|
||||
|
||||
=item --collect-oprofile
|
||||
|
||||
Collect oprofile data.
|
||||
|
||||
=item --collect-strace
|
||||
|
||||
Collect strace data.
|
||||
|
||||
=item --collect-tcpdump
|
||||
|
||||
Collect tcpdump data.
|
||||
|
||||
=item --cycles
|
||||
|
||||
type: int; default: 5
|
||||
|
||||
Number of times condition must be met before triggering collection.
|
||||
|
||||
=item --daemonize
|
||||
|
||||
default: yes; negatable: yes
|
||||
|
||||
Daemonize the tool.
|
||||
|
||||
=item --dest
|
||||
|
||||
type: string
|
||||
|
||||
Where to store collected data.
|
||||
|
||||
=item --disk-byte-limit
|
||||
|
||||
type: int; default: 100
|
||||
|
||||
Exit if the disk has less than this many MB free.
|
||||
|
||||
=item --disk-pct-limit
|
||||
|
||||
type: int; default: 5
|
||||
|
||||
Exit if the disk is less than this %full.
|
||||
|
||||
=item --execute-command
|
||||
|
||||
type: string; default: pt-collect
|
||||
|
||||
Location of the C<pt-collect> tool.
|
||||
|
||||
=item --function
|
||||
|
||||
type: string; default: status
|
||||
|
||||
Built-in function name or plugin file name which returns the value of C<VARIABLE>.
|
||||
|
||||
Possible values are:
|
||||
|
||||
=over
|
||||
|
||||
=item * status
|
||||
|
||||
Grep the value of C<VARIABLE> from C<mysqladmin extended-status>.
|
||||
|
||||
=item * processlist
|
||||
|
||||
Count the number of processes in C<mysqladmin processlist> whose
|
||||
C<VARIABLE> column matches C<MATCH>. For example:
|
||||
|
||||
TRIGGER_FUNCTION="processlist" \
|
||||
VARIABLE="State" \
|
||||
MATCH="statistics" \
|
||||
THRESHOLD="10"
|
||||
|
||||
The above triggers when more than 10 processes are in the "statistics" state.
|
||||
C<MATCH> must be specified for this trigger function.
|
||||
|
||||
=item * magic
|
||||
|
||||
TODO
|
||||
|
||||
=item * plugin file name
|
||||
|
||||
A plugin file allows you to specify a custom trigger function. The plugin
|
||||
file must contain a function called C<trg_plugin>. For example:
|
||||
|
||||
trg_plugin() {
|
||||
# Do some stuff.
|
||||
echo "$value"
|
||||
}
|
||||
|
||||
The last output if the function (its "return value") must be a number.
|
||||
This number is compared to C<THRESHOLD>. All L<"ENVIRONMENT"> variables
|
||||
are available to the function.
|
||||
|
||||
Do not alter the tool's existing global variables. Prefix any plugin-specific
|
||||
global variables with "PLUGIN_".
|
||||
|
||||
=back
|
||||
|
||||
=item --help
|
||||
|
||||
Print help and exit.
|
||||
|
||||
=item --interval
|
||||
|
||||
type: int; default: 1
|
||||
|
||||
Interval between checks.
|
||||
|
||||
=item --iterations
|
||||
|
||||
type: int
|
||||
|
||||
Exit after triggering C<pt-collect> this many times. By default, the tool
|
||||
will collect as many times as it's triggered.
|
||||
|
||||
=item --log
|
||||
|
||||
type: string; default: /var/log/pt-stalk.log
|
||||
|
||||
Print all output to this file when daemonized.
|
||||
|
||||
=item --match
|
||||
|
||||
type: string
|
||||
|
||||
Match pattern for C<processles> L<"--function">.
|
||||
|
||||
=item --notify-by-email
|
||||
|
||||
type: string
|
||||
|
||||
Send mail to this list of addresses when C<pt-collect> triggers.
|
||||
|
||||
=item --pid FILE
|
||||
|
||||
type: string; default: /var/run/pt-stalk.pid
|
||||
|
||||
Create a PID file when daemonized.
|
||||
|
||||
=item --retention-time
|
||||
|
||||
type: int; default: 30
|
||||
|
||||
Remove samples after this many days.
|
||||
|
||||
=item --run-time
|
||||
|
||||
type: int; default: 30
|
||||
|
||||
How long to collect statistics data for?
|
||||
|
||||
Make sure that this isn't longer than SLEEP.
|
||||
|
||||
=item --sleep
|
||||
|
||||
type: int; default: 300
|
||||
|
||||
How long to sleep after collecting?
|
||||
|
||||
=item --threshold N
|
||||
|
||||
type: int; default: 25
|
||||
|
||||
Max number of C<N> to tolerate.
|
||||
|
||||
=item --variable NAME
|
||||
|
||||
type: string; default: Threads_running
|
||||
|
||||
This is the thing to check for.
|
||||
|
||||
=item --version
|
||||
|
||||
Print tool's version and exit.
|
||||
|
||||
=back
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
No env vars used.
|
||||
|
||||
=cut
|
||||
|
||||
DOCUMENTATION
|
Reference in New Issue
Block a user