Skip to content

Instantly share code, notes, and snippets.

@ssokolow
Created September 21, 2012 00:41
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ssokolow/3759156 to your computer and use it in GitHub Desktop.
Save ssokolow/3759156 to your computer and use it in GitHub Desktop.
Novice-safe shell script for gathering data to report bugs in Linux games
#!/bin/sh
# dash-Compatible Linux Configuration Dumper for Troubleshooting Games
# (Sort of like DxDiag but for Linux)
#
# Get and contribute updates to this script at: https://gist.github.com/3759156
#
# NOTE: Please test changes on as many of the following shells as possible:
# dash, bash, pdksh, busybox, ash, zsh
#
# TODO:
# - Confirm that the presence or absence of S3 Texture Compression support is
# included in existing read-outs. If feasible, list it separately for easy
# recognition by users should the developers ask them to check.
# - Linking and crash logs:
# - Provide support for taking the relative path to the game binary (both
# hard-coded and as an argument)
# - If the game binary is provided, include the binary format (eg. ELF64) and
# data about the system's supported binary formats in the readout.
# - If the game binary is provided, include the ldd output in the log
# - Support a --log-crash flag which causes it to also run the game under gdb
# and automatically collect the output of "bt full".
# - Compositing and window management:
# - Find a way to detect whether a compositor like Compiz is running
# 1. log into KDE 4
# 2. (xrandr -q -v ; xdpyinfo -queryExtensions -ext all; glxinfo -t -v -l) 2>&1 1>log.txt`
# 3. toggle compositing, log them again, and diff the logs to see if
# anything reliable shows up.
# - Find a generic mechanism for detecting the active WM (eg. How does
# fusion-icon do it?)
# - Design tests for whether Compiz and Kwin are set to suspend compositing
# for fullscreen windows.
# - Audio:
# - A list of audio devices (input and output, waveform, midi, and mixers)
# - Which audio devices are default?
# - Are the PulseAudio, OSS4, JACK, etc. daemons installed?
# - Are the PulseAudio, JACK, CUSE ossproxy, etc. daemons running?
# - A list of installed libpulse/libjack/etc. to clarify ld and dlopen behavior
# (locate libpulse | fgrep .so | xargs ls -l)
# - Use lsof or equivalent to check what's hanging on the soundcard endpoints
# - Is pasuspender installed?
# - Is another application using pasuspender to block the sound card?
# - What else can cause audio issues?
# - Input Devices:
# - List of connected Joystics
# - List of XInput devices
# - Find a way to detect off-calibration joysticks which could cause in-game
# menus to cycle wildly. (Known problem with some USB-PS2 controller bridges
# and at least the official Windows drivers for 3DConnexion Space Navigators)
# - Look into whether any other kind of input debugging data would be
# worth gathering
# - Decide what network-related data would be useful.
# - Compare my output to Steam's output as shown at
# http://phoronix.com/forums/showthread.php?p=369297#post369297
#
# Known Bugs:
# - busybox's free is ignorant of memory used for opportunistic disk caching.
# - The version of busybox included with the OpenPandora misunderstands
# the command `df -h /`
#
# Copyright (c) 2012 Stephan Sokolow
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# Edit these as appropriate to your specific debugging needs
DUMP_FILE=~/game_troubleshooting_dump.txt
REQUIRE_CMDS="glxinfo"
# ---=== Respawn self early if necessary ===---
# Since we don't read from stdin anyway, it's reasonable to assume that, if
# it's not a TTY, the user must need a terminal window to see our output.
# (As opposed to being intentionally piped or redirected by the user)
if [ ! -t 0 ]; then
for CMD in x-terminal-emulator urxvt uxterm rxvt xterm; do
if type "$CMD" 1>/dev/null 2>&1; then
exec "$CMD" -e "$0" --wait
fi
done
fi
# Redirect stdout to the dump file to avoid repetitive output redirects
exec > "$DUMP_FILE"
# ---=== Function Declarations ===---
posix_check() {
if ! type "$1" 1>/dev/null 2>&1; then
echo "ERROR: Your system is either broken or not POSIX-compatible." 1>&2
echo " Please run this in a shell that provides the $1 command." 1>&2
exit 1
fi
}
prefer_cmd() {
if ! type "$1" 1>/dev/null 2>&1; then
printf "$3 $1 missing.\n"
printf "WARNING: %s is not installed. $3\n" "$1" 1>&2
printf " (It is often found in a package with a name like '%s')\n\n" "$2" 1>&2
local REQUIRE_CMDS=" $REQUIRE_CMDS "
case $REQUIRE_CMDS in *" $1 "*)
printf "ERROR: The data gathered by "$1" is required. Please install it and try again.\n\n" 1>&2
exit 2
;;
esac
return 1
fi
}
#FIXME: This breaks on the version of BusyBox provided by the OpenPandora
# (because they misunderstand `df -h /` to match only dev nodes)
# Implement some kind of line-counting and condense into one awk expr.
# http://www.catonmat.net/blog/awk-one-liners-explained-part-one/
# http://mywiki.wooledge.org/BashFAQ/094
show_free() {
if [ -z "$2" ]; then
name="$1"
else
name="$2"
fi
# The "grep %" strips off the long device paths that busybox or bad luck
# can use to word-wrap the rows.
# The first awk ensures the second awk will count fields properly if
# word-wrap occurred.
fspace="`LC_ALL=C df -h \"$1\" | grep % | awk '{ getline; printf \"x%s\", $0 }' | awk '{ print $4 }'`"
# We need the "grep %" so long device paths like those in busybox won't
# break things when they trigger word-wrap
printf "%-20s: %s\n" "$name" "$fspace"
}
# Check for basic system sanity to be ridiculously thorough
posix_check type
posix_check printf
posix_check cat
posix_check grep
posix_check sed
posix_check awk
# Get the OS name and platform architecture strings since they're not included
# in the kernel version
if prefer_cmd uname coreutils "Cannot read platform string. This system may be very broken or not Linux."; then
printf "Platform:\n %s %s\n\n" "`uname -o`" "`uname -m`"
fi
# Get the kernel version (an all-around useful thing to know)
printf "Kernel Version:\n"
cat /proc/version | sed 's@^@ @'
printf "\n=== distro release version ===\n\n"
if type lsb_release 1>/dev/null 2>&1; then
lsb_release -a 2>/dev/null
elif [ -e /etc/lsb-release ]; then
cat /etc/lsb-release
else
printf "WARNING: No Linux Standards Base release metadata found.\n" 1>&2
printf " Verify the distro name and version before submitting.\n\n" 1>&2
grep '' /etc/issue /etc/*_release /etc/*-release /etc/*_version /etc/*-version 2>|/dev/null
fi
printf "\n=== desktop environment ===\n\n"
printf "DESKTOP_SESSION : %s\n" "$DESKTOP_SESSION"
printf "XDG_CURRENT_DESKTOP : %s\n" "$XDG_CURRENT_DESKTOP"
printf "\n=== SDL environment ===\n\n"
set | grep -a SDL_
# Get the CPU model in case it's incompatible with the build options
printf "\n=== cpu information (per core) ===\n\n"
if [ -e /proc/cpuinfo ]; then
cpuinfo=`cat /proc/cpuinfo | grep -E '^(processor|model name|flags|cpu MHz|$)'`
if [ -z "$cpuinfo" ]; then
cat /proc/cpuinfo
printf "\n"
else
printf "%s\n\n" "$cpuinfo"
fi
else
printf "ERROR: /proc/cpuinfo not found! (Non-Linux platform?)\n\n"
printf "WARNING: /proc/cpuinfo not found! This script only supports Linux.\n" 1>&2
fi
if [ -e /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies ]; then (
printf 'CPU Frequency Scaling:\n'
cd /sys/devices/system/cpu
for CPU in cpu*; do
(
# Skip folders not corresponding to individual CPUs
# (Can't use continue here in pdksh)
if [ -e "$CPU/cpufreq" ]; then
cd "$CPU/cpufreq"
printf " $CPU:\n"
grep '' scaling_min_freq scaling_max_freq scaling_governor | sed 's@^@ @'
fi
)
done )
printf '\n'
else
printf "Unable to query CPU frequency scaling settings\n\n"
fi
# Get the memory stats in case the user is experiencing an OOM-related crash
# TODO: Find some way to detect busybox and warn about the +/- buffers issue
if prefer_cmd free procps "This system may be very broken or not Linux."; then
printf "=== memory information (in megabytes) ===\n\n"
free -m
elif [ -e /proc/meminfo ]; then
printf "=== memory information (fallback) ===\n\n"
cat /proc/meminfo | grep -E '^(MemTotal|MemFree|Buffers|Cached|SwapTotal|SwapFree)'
else
printf "=== memory information ===\n\n"
printf "Unable to retrieve memory statistics (Non-Linux platform?)\n\n"
printf "ERROR: Neither /usr/bin/free nor /proc/meminfo exist!\n" 1>&2
fi
# Record the free disk space in places known to cause death by failure to write
printf "\n=== free disk space ===\n\n"
show_free /
show_free /tmp
show_free /var/tmp
show_free /var/log
show_free ~ "User Home Directory"
show_free "$0" "Game Directory"
printf "\n"
# Try to look up the video driver used by X.org
if [ -e /var/log/Xorg.0.log ]; then
printf "=== X.org Drivers Used ===\n"
# Source: http://askubuntu.com/a/28037
x_drivers=`egrep -i " connected|card detect|primary dev|rgb weight|default visual is" /var/log/Xorg.0.log | sed 's@^@ @'`
if [ -z "$x_drivers" ]; then
continue
fi
printf "%s" "$x_drivers"
printf '\n\n'
elif type glxinfo 1>/dev/null 2>&1; then
printf "=== X.org Drivers Used (glxinfo) ===\n"
glxinfo | grep -i vendor
printf '\n'
printf "WARNING: Detection of in-use video drivers is vague. /var/log/Xorg.0.log is missing!\n" 1>&2
else
printf "Unable to detect in-use video drivers. /var/log/Xorg.0.log does not exist.\n\n"
printf "WARNING: Unable to detect in-use video drivers. glxinfo and /var/log/Xorg.0.log are missing!\n" 1>&2
fi
if prefer_cmd lspci pciutils "Unable to identify video card model and kernel driver."; then
printf "=== video card details ===\n\n"
for X in `lspci | grep VGA | cut -d' ' -f1`; do
lspci -v -s "$X" | grep -E '(VGA|Subsystem|Kernel|^$)'
done
fi
if prefer_cmd xrandr x11-server-utils "Unable to detect available monitor resolutions."; then
printf "=== available monitor resolutions ===\n\n"
xrandr 2>/dev/null
fi
if prefer_cmd xdpyinfo x11-utils "Unable to check for Xinerama (multi-monitor) data."; then
printf "\nXinerama Info:\n"
xdpyinfo -ext XINERAMA 2>/dev/null | grep head | sed 's@^@ @'
fi
if prefer_cmd glxinfo mesa-utils "Unable to dump OpenGL data for debugging 2D/3D acceleration."; then
printf "\n=== glxinfo output ===\n\n"
glxinfo
fi
# Weird, misconfigured locale settings have been known to cause problems
printf "\n=== language and localization ===\n\n"
if type locale 1>/dev/null 2>&1; then
locale
else
set | grep -a LANG
set | grep -a LC_
fi
printf "\n=== diagnostic script info ===\n\n"
printf "Novice-safe shell script for gathering data to report bugs in Linux games\n\n"
printf "Source:\n https://gist.github.com/3759156\n"
# XXX: If you know another robust way to pin down this script's version, I'm all ears.
if type sha1sum 1>/dev/null 2>&1; then
printf "Version Hash (SHA1):\n %s\n" "`sha1sum \"$0\" | cut -d' ' -f1`"
elif type md5sum 1>/dev/null 2>&1; then
printf "Version Hash (MD5):\n %s\n" "`md5sum \"$0\" | cut -d' ' -f1`"
else
printf " Unable to identify script version\n"
printf " WARNING: You are advised to re-run this script with sha1sum or md5sum installed so it can note its own version.\n" 1>&2
fi
printf '\nThis Report Generated: %s' "`date -R`"
printf "Data gathered. Please attach this file to your bug report:\n %s\n" "$DUMP_FILE" 1>&2
# In case we exec'd ourself into a terminal
if [ "$1" = "--wait" ]; then
printf '\nPress Enter to close this window... ' 1>&2
read throwaway
fi
# vim: set noexpandtab sw=4 sts=4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment