| #!/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