Show More
Commit Description:
merge
Commit Description:
merge
References:
File last commit:
Show/Diff file:
Action:
isolate/isolate-check-environment
| 224 lines
| 6.4 KiB
| text/plain
| TextLexer
|
r256 | #!/bin/sh | |||
# | ||||
# Identifies potential sources issues when using isolate. | ||||
# | ||||
# (c) 2017 Bernard Blackham <bernard@blackham.com.au> | ||||
# | ||||
usage() { | ||||
cat <<EOT >&2 | ||||
Usage: $0 [-q|--quiet] [-e|--execute] | ||||
Use this script to identify sources of run-time variability and other issues on | ||||
Linux machines which may affect isolate. If --execute is not specified, the | ||||
recommended actions are written to stdout as an executable shell script, | ||||
otherwise, using --execute will attempt to make changes to make the system | ||||
behave more deterministically. The changes performed by --execute persist only | ||||
until a reboot. To persist across reboots, the standard output from this script | ||||
should be added to /etc/rc.local or some other script that is run on each boot. | ||||
Alternately, you could add the following line to /etc/rc.local to automatically | ||||
apply these changes on boot, but use this with caution as not all issues can | ||||
be resolved in this way. | ||||
isolate-check-environment --quiet --execute | ||||
The exit status of this script will be 0 if all checks pass, or 1 if some | ||||
checks have failed. | ||||
Note that there are more strategies to reduce run-time variability further. | ||||
See the man page of isolate for details under REPRODUCIBILITY. | ||||
EOT | ||||
exit 2 | ||||
} | ||||
# Parse options. | ||||
args=$(getopt -o "ehq" --long "execute,help,quiet" -- "$@") || usage | ||||
eval set -- "$args" | ||||
quiet= | ||||
execute= | ||||
while : ; do | ||||
case "$1" in | ||||
-q|--quiet) quiet=1 ; shift ;; | ||||
-e|--execute) execute=1 ; shift ;; | ||||
-h|--help) usage ;; | ||||
--) shift ; break ;; | ||||
*) usage ;; | ||||
esac | ||||
done | ||||
[ -n "$*" ] && usage | ||||
# Some helper boilerplate machinery. | ||||
exit_status=0 | ||||
red=$(tput setaf 1) | ||||
green=$(tput setaf 2) | ||||
yellow=$(tput setaf 3) | ||||
normal=$(tput sgr0) | ||||
# Return true (0) if we are being quiet. | ||||
quiet() { | ||||
[ -n "$quiet" ] | ||||
} | ||||
# Print all arguments to stderr as warning. | ||||
warn() { | ||||
quiet || echo WARNING: "$*" >&2 | ||||
} | ||||
# Print first argument to stderr as warning, and second argument to stdout as | ||||
# the recommended remedial action, or execute if --execute is given. | ||||
action() { | ||||
quiet || warn "$1" | ||||
if [ -n "$execute" ] ; then | ||||
quiet || echo "+ $2" | ||||
sh -c "$2" | ||||
else | ||||
quiet || echo $2 | ||||
fi | ||||
} | ||||
print_start_check() { | ||||
quiet && return | ||||
print_check_status=1 | ||||
echo -n "Checking for $@ ... " >&2 | ||||
} | ||||
print_fail() { | ||||
exit_status=1 | ||||
quiet && return | ||||
[ -n "$print_check_status" ] && echo "${red}FAIL${normal}" >&2 | ||||
print_check_status= | ||||
} | ||||
print_dubious() { | ||||
exit_status=1 | ||||
quiet && return | ||||
[ -n "$print_check_status" ] && echo "${yellow}CAUTION${normal}" >&2 | ||||
print_check_status= | ||||
} | ||||
print_skipped() { | ||||
quiet && return | ||||
[ -n "$print_check_status" ] && echo "SKIPPED (not detected)" >&2 | ||||
print_check_status= | ||||
} | ||||
print_finish() { | ||||
quiet && return | ||||
[ -n "$print_check_status" ] && echo "${green}PASS${normal}" >&2 | ||||
print_check_status= | ||||
} | ||||
# Check that cgroups are enabled. | ||||
cgroup_check() { | ||||
local cgroup=$1 | ||||
print_start_check "cgroup support for $cgroup" | ||||
if ! test -f "/sys/fs/cgroup/$cgroup/tasks" ; then | ||||
print_dubious | ||||
warn "the $cgroup is not present. isolate --cg cannot be used." | ||||
fi | ||||
print_finish | ||||
} | ||||
cgroup_check memory | ||||
cgroup_check cpuacct | ||||
cgroup_check cpuset | ||||
# Check that swap is either disabled or accounted for. | ||||
swap_check() { | ||||
print_start_check "swap" | ||||
# If swap is disabled, there is nothing to worry about. | ||||
local swaps | ||||
swaps=$(swapon --noheadings) | ||||
if [ -n "$swaps" ] ; then | ||||
# Swap is enabled. We had better have the memsw support in the memory | ||||
# cgroup. | ||||
if ! test -f "/sys/fs/cgroup/memory/memory.memsw.usage_in_bytes" ; then | ||||
print_fail | ||||
action \ | ||||
"swap is enabled, but swap accounting is not. isolate will not be able to enforce memory limits." \ | ||||
"swapoff -a" | ||||
else | ||||
print_dubious | ||||
warn "swap is enabled, and although accounted for, may still give run-time variability under memory pressure." | ||||
fi | ||||
fi | ||||
print_finish | ||||
} | ||||
swap_check | ||||
# Check that CPU frequency scaling is disabled. | ||||
cpufreq_check() { | ||||
print_start_check "CPU frequency scaling" | ||||
local anycpus policy | ||||
anycpus= | ||||
# Ensure cpufreq governor is set to performance on all CPUs | ||||
for cpufreq_file in $(find /sys/devices/system/cpu/cpufreq/ -name scaling_governor) ; do | ||||
policy=$(cat $cpufreq_file) | ||||
if [ "$policy" != "performance" ] ; then | ||||
print_fail | ||||
action \ | ||||
"cpufreq governor set to '$policy', but 'performance' would be better" \ | ||||
"echo performance > $cpufreq_file" | ||||
fi | ||||
anycpus=1 | ||||
done | ||||
[ -z "$anycpus" ] && print_skipped | ||||
print_finish | ||||
} | ||||
cpufreq_check | ||||
# Check that address space layout randomisation is disabled. | ||||
aslr_check() { | ||||
print_start_check "kernel address space randomisation" | ||||
local val | ||||
if val=$(cat /proc/sys/kernel/randomize_va_space 2>/dev/null) ; then | ||||
if [ "$val" -ne 0 ] ; then | ||||
print_fail | ||||
action \ | ||||
"address space randomisation is enabled." \ | ||||
"echo 0 > /proc/sys/kernel/randomize_va_space" | ||||
fi | ||||
else | ||||
print_skipped | ||||
fi | ||||
print_finish | ||||
} | ||||
aslr_check | ||||
# Check that transparent huge-pages are disabled, as this leads to | ||||
# non-determinism depending on whether the kernel can allocate 2 MiB pages or | ||||
# not. | ||||
thp_check() { | ||||
print_start_check "transparent hugepage support" | ||||
local val | ||||
if val=$(cat /sys/kernel/mm/transparent_hugepage/enabled 2>/dev/null) ; then | ||||
case $val in | ||||
*'[never]'*) ;; | ||||
*) print_fail | ||||
action \ | ||||
"transparent hugepages are enabled." \ | ||||
"echo never > /sys/kernel/mm/transparent_hugepage/enabled" ;; | ||||
esac | ||||
fi | ||||
if val=$(cat /sys/kernel/mm/transparent_hugepage/defrag 2>/dev/null) ; then | ||||
case $val in | ||||
*'[never]'*) ;; | ||||
*) print_fail | ||||
action \ | ||||
"transparent hugepage defrag is enabled." \ | ||||
"echo never > /sys/kernel/mm/transparent_hugepage/defrag" ;; | ||||
esac | ||||
fi | ||||
if val=$(cat /sys/kernel/mm/transparent_hugepage/khugepaged/defrag 2>/dev/null) ; then | ||||
if [ "$val" -ne 0 ] ; then | ||||
print_fail | ||||
action \ | ||||
"khugepaged defrag is enabled." \ | ||||
"echo 0 > /sys/kernel/mm/transparent_hugepage/khugepaged/defrag" | ||||
fi | ||||
fi | ||||
print_finish | ||||
} | ||||
thp_check | ||||
exit $exit_status | ||||