#!/bin/sh # Copyright (c) 2004-2017 Apple Inc. # # get-mobility-info # # Collect system & network configuration information. # PATH=/bin:/usr/bin:/sbin:/usr/sbin OUTDIR="" NO_PCAP=0 NO_TAR=0 while getopts f:PT OPTION ; do case ${OPTION} in f) OUTDIR="${OPTARG}" if [ ! -d "${OUTDIR}" ]; then echo "# ${PROGNAME}: \"${OUTDIR}\" is not a directory" exit 1 fi ;; P) NO_PCAP=1 ;; T) NO_TAR=1 ;; \?) ;; esac done # # Disclaimer # cat <<_END_OF_DISCLAIMER This diagnostic tool generates files that allow Apple to investigate issues with your computer and help Apple to improve its products. The generated files may contain some of your personal information, which may include, but not be limited to, the serial number or similar unique number for your device, your user name, or your computer name. The information is used by Apple in accordance with its privacy policy (www.apple.com/privacy) and is not shared with any third party. By enabling this diagnostic tool and sending a copy of the generated files to Apple, you are consenting to Apple's use of the content of such files. _END_OF_DISCLAIMER /bin/echo "Press 'Enter' to continue." read reply # # Setup # PRIV="" if [ ${EUID} -ne 0 ]; then PRIV="sudo" fi if [ -x /usr/bin/tail ]; then TAIL_2000="/usr/bin/tail -n 2000" TAIL_25000="/usr/bin/tail -n 25000" else TAIL_2000="/bin/cat" TAIL_25000="/bin/cat" fi OUT="mobility-info-`date +'%Y.%m.%d.%H%M%S'`" if [ -z $OUTDIR ]; then OUTDIR="/var/tmp" if [ -d ~/Desktop ]; then OUTDIR=~/Desktop elif [ "`readlink /tmp`" = "private/var/tmp" ]; then OUTDIR=/Library/Logs/DiagnosticReports if [ ! -d /Library/Logs/DiagnosticReports -a -d /Library/Logs/CrashReporter ]; then OUTDIR=/Library/Logs/CrashReporter fi mkdir -p ${OUTDIR} fi fi umask 077 WORKDIR=`mktemp -d -q "/tmp/${OUT}"` if [ $? -ne 0 ]; then echo "Could not create snapshot directory" exit 1 fi if [ $NO_TAR -eq 0 ]; then GZ_EXT="" GZ_OPT="" if [ -x /usr/bin/gzip ]; then GZ_EXT=".gz" GZ_OPT="-z" fi ARCHIVE=`mktemp -q "${OUTDIR}/${OUT}.tar${GZ_EXT}"` if [ $? -ne 0 ]; then echo "Could not create snapshot archive" rm -rf "${WORKDIR}" exit 1 fi fi cd "${WORKDIR}" echo "" echo "Please wait, collecting information and statistics" echo "" # # collect packet capture with kernel ring buffer if available # stop_pcap () { # # Stop the packet capture # if [ ${PCAP_STARTED} -ne 0 ]; then trap '' SIGINT /usr/local/bin/netdiagnose stop packetcapture 2>&1 PCAP_STARTED=0 fi } PCAP_STARTED=0 if [ -x /usr/local/bin/netdiagnose -a ${NO_PCAP} -ne 1 ]; then trap stop_pcap SIGINT /usr/local/bin/netdiagnose -p "${WORKDIR}" start packetcapture 2>&1 PCAP_STARTED=1 fi # # get-network-info # if [ -x /System/Library/Frameworks/SystemConfiguration.framework/Resources/get-network-info ]; then /System/Library/Frameworks/SystemConfiguration.framework/Resources/get-network-info -s -c -P "${WORKDIR}" elif [ -x /System/Library/Frameworks/SystemConfiguration.framework/get-network-info ]; then /System/Library/Frameworks/SystemConfiguration.framework/get-network-info -s -c -P "${WORKDIR}" elif [ -x /System/Library/PrivateFrameworks/SystemConfiguration.framework/get-network-info ]; then /System/Library/PrivateFrameworks/SystemConfiguration.framework/get-network-info -s -c -P "${WORKDIR}" fi # # processes # if [ -x /bin/ps ]; then /bin/ps axlww > ps 2>&1 fi # # AirPort info # if [ -x /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport ]; then /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport --getinfo \ > airport 2>&1 fi # # collect wifi dump # if [ -x /usr/bin/wdutil -a -x /bin/ls ]; then ${PRIV} /usr/bin/wdutil dump mkdir -p "wifi_dump" /bin/ls -1 /private/tmp/wifi-* 2>/dev/null \ | while read log do if [ -f "${log}" ]; then b="`basename ${log}`" ${PRIV} cat "${log}" > "wifi_dump/${b}" 2>&1 fi done fi # # OS info # if [ -e /System/Library/CoreServices/SystemVersion.plist ]; then cat /System/Library/CoreServices/SystemVersion.plist \ > SystemVersion.plist 2>&1 fi # # IOKit info # if [ -x /usr/sbin/ioreg ]; then /usr/sbin/ioreg -i -l -w 0 > ioreg 2>&1 /usr/sbin/ioreg -i -l -p IODeviceTree -w 0 >> ioreg 2>&1 fi # # Power Management info # if [ -x /usr/bin/pmset ]; then echo "#" > pmset echo "# pmset -g everything" >> pmset echo "#" >> pmset /usr/bin/pmset -g everything 2>/dev/null | ${TAIL_25000} >> pmset fi # # Host configuration # if [ -x /usr/bin/hostinfo ]; then /usr/bin/hostinfo > hostinfo 2>&1 fi if [ -e /etc/hostconfig ]; then cat /etc/hostconfig > etc.hostconfig 2>&1 fi # # System / network preferences # for f in \ /Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist \ /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist \ /Library/Preferences/SystemConfiguration/com.apple.wifi.plist \ /Library/Preferences/com.apple.alf.plist \ /Library/Preferences/com.apple.sharing.firewall.plist \ /Library/Preferences/com.apple.wwand.plist \ do if [ -e "${f}" ]; then b="`basename ${f}`" cat "${f}" > "${b}" 2>&1 fi done # # Install log # if [ -e /var/log/install.log ]; then cat /var/log/install.log > install.log 2>&1 fi # # System / network preferences (from other volumes) # mount -t hfs | grep "/Volumes/" | sed -e 's:^.* on /Volumes/::' -e 's: ([^(]*$::' \ | while read volume do V_PATH="/Volumes/${volume}" if [ -h "${V_PATH}" ]; then # if the path is a symlink continue fi for f in \ /Library/Preferences/SystemConfiguration/Networkinterfaces.plist \ /Library/Preferences/SystemConfiguration/preferences.plist \ do if [ -f "${V_PATH}/${f}" ]; then mkdir -p "OtherPreferences/${volume}" b="`basename ${f}`" cat "${V_PATH}/${f}" > "OtherPreferences/${volume}/${b}" 2>&1 fi done done # # InternetSharing # if [ -e /etc/bootpd.plist ]; then cat /etc/bootpd.plist > bootpd.plist 2>&1 cat /etc/com.apple.named.proxy.conf > com.apple.named.proxy.conf 2>/dev/null elif [ -e /Library/Preferences/SystemConfiguration/bootpd.plist ]; then cat /Library/Preferences/SystemConfiguration/bootpd.plist > bootpd.plist 2>&1 cat /Library/Preferences/SystemConfiguration/com.apple.named.proxy.conf > com.apple.named.proxy.conf 2>/dev/null fi # # mounted filesystems # mount > mounted-filesystems 2>&1 ${PRIV} cat /etc/hosts > etc.hosts 2>/dev/null # # kernel extensions statistic # if [ -x /usr/sbin/kextstat ]; then /usr/sbin/kextstat > kextstat 2>&1 fi if [ -x /sbin/pfctl ]; then echo "#" > pf echo "# pfctl -s all" >> pf echo "#" >> pf ${PRIV} /sbin/pfctl -s all >> pf 2>&1 echo "==============================" >> pf echo "#" >> pf echo "# pfctl -s References" >> pf echo "#" >> pf ${PRIV} /sbin/pfctl -s References >> pf 2>&1 for ANCHOR in `${PRIV} pfctl -s Anchors -v 2>/dev/null` do echo "==============================" >> pf echo "#" >> pf echo "# pfctl -a ${ANCHOR} -s all" >> pf echo "#" >> pf ${PRIV} /sbin/pfctl -a ${ANCHOR} -s all >> pf 2>&1 done fi # # mach port info # if [ -x /usr/local/bin/lsmp ]; then ${PRIV} /usr/local/bin/lsmp -a -v > lsmp 2>&1 fi # # open files # if [ -x /usr/sbin/lsof ]; then ${PRIV} /usr/sbin/lsof -n -O -P -T q > lsof 2>&1 & LSOF_PID=$! # Init a watchdog for lsof ( WAIT_TIME=5 while [ $WAIT_TIME -gt 0 ] do ${PRIV} kill -0 ${LSOF_PID} 2>/dev/null if [ $? -eq 0 ]; then sleep 1 # lsof is gathering data.. WAIT_TIME=$((WAIT_TIME-1)) continue fi # lsof completed gathering data break done if [ $WAIT_TIME -eq 0 ]; then # lsof timed out ${PRIV} kill ${LSOF_PID} 2>/dev/null fi ) & fi # # [lib]dispatch info # if [ -x /usr/local/bin/ddt ]; then /bin/echo -n "" > dispatch-info for BIN in \ configd \ discoveryd \ do echo "#" >> dispatch-info echo "# ddt -vkp ${BIN}" >> dispatch-info echo "#" >> dispatch-info ${PRIV} /usr/local/bin/ddt -vkp ${BIN} >> dispatch-info 2>&1 done fi # # OpenDirectory info # if [ -x /usr/bin/odutil ]; then echo "#" > od-info echo "# odutil show all" >> od-info echo "#" >> od-info ${PRIV} /usr/bin/odutil show all >> od-info 2>&1 fi # # Kerberos configuration # if [ -x /usr/bin/klist ]; then echo "#" > kerberos echo "# klist --verbose --all-content" >> kerberos echo "#" >> kerberos klist --verbose --all-content >> kerberos 2>&1 echo "#" >> kerberos echo "# ktutil list" >> kerberos echo "#" >> kerberos ${PRIV} /usr/sbin/ktutil --verbose list >> kerberos 2>&1 echo "#" >> kerberos echo "# gsstool list --verbose" >> kerberos echo "#" >> kerberos /System/Library/PrivateFrameworks/Heimdal.framework/Helpers/gsstool list --verbose >> kerberos 2>&1 fi # # system profiler # if [ -x /usr/sbin/system_profiler ]; then system_profiler -xml SPEthernetDataType \ SPFibreChannelDataType \ SPFireWireDataType \ SPFirewallDataType \ SPModemDataType \ SPNetworkDataType \ SPThunderboltDataType \ SPWWANDataType \ SPAirPortDataType > system_profiler.spx 2>/dev/null fi # # system usage statistics # /bin/echo -n "" > system-statistics if [ -x /usr/bin/uptime ]; then echo "#" >> system-statistics echo "# uptime" >> system-statistics echo "#" >> system-statistics /usr/bin/uptime >> system-statistics 2>&1 fi if [ -x /usr/sbin/sysctl ]; then echo "#" >> system-statistics echo "# sysctl kern hw net debug" >> system-statistics echo "#" >> system-statistics /usr/sbin/sysctl kern hw net debug >> system-statistics 2>&1 fi if [ -x /usr/bin/zprint ]; then echo "#" >> system-statistics echo "# zprint" >> system-statistics echo "#" >> system-statistics ${PRIV} /usr/bin/zprint >> system-statistics 2>&1 fi if [ -x /usr/sbin/lsof -a -x /bin/ls ]; then N=0 /bin/ls -1 /Library/Preferences/SystemConfiguration/*-lock \ 2>/dev/null \ | while read lock do if [ ${N} -eq 0 ]; then echo "#" >> system-statistics echo "# lsof [SCPreferences lock files]" >> system-statistics fi N=`expr ${N} + 1` echo "#" >> system-statistics ${PRIV} /usr/sbin/lsof -- ${lock} >> system-statistics 2>&1 done fi # # collect executable and plugin info # report_binary_info() { if [ ! -f "${1}" ]; then return fi VERSION=`what "${1}"` echo "${VERSION}" >> versions 2>&1 SUM=`sum "${1}"` echo "\tsum: ${SUM}" >> versions 2>&1 LSINFO=`ls -lu "${1}"` echo "\tadditional info: ${LSINFO}" >> versions 2>&1 echo "" >> versions 2>&1 } get_binary_info() { for BIN in \ /usr/libexec/bootpd \ /usr/libexec/configd \ /usr/libexec/discoveryd \ /usr/sbin/awacsd \ /usr/sbin/mDNSResponder \ /usr/sbin/pppd \ /usr/sbin/racoon \ /usr/libexec/misd \ /usr/libexec/InternetSharing \ /System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration \ do report_binary_info "${BIN}" done if [ -x /usr/bin/xcode-select -a -x /usr/bin/xcodebuild -a -x /usr/bin/xcrun ]; then SDKPATH="`xcode-select --print-path 2>/dev/null`" if [ $? -eq 0 -a -n "${SDKPATH}" ]; then /usr/bin/xcodebuild -showsdks 2>/dev/null \ | grep iphone \ | awk '{ print $NF }' \ | while read SDK do SDKPATH="`xcrun --sdk $SDK --show-sdk-path`" for BIN in \ /usr/libexec/configd_sim \ /System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration \ do report_binary_info "${SDKPATH}${BIN}" done done else echo "*** NO SDKs ***" >> versions echo "" >> versions fi fi } get_plugins_info() { num=0 cd /System/Library/SystemConfiguration for PLUGIN in *.bundle do plugins[$num]="${PLUGIN}" num=$(( $num + 1 )) done cd "${WORKDIR}" for PLUGIN in "${plugins[@]}" do PLUGIN_DIR="/System/Library/SystemConfiguration/${PLUGIN}" PLUGIN_INF="${PLUGIN_DIR}/Contents/Info.plist" if [ ! -f "${PLUGIN_INF}" ]; then PLUGIN_INF="${PLUGIN_DIR}/Info.plist" if [ ! -f "${PLUGIN_INF}" ]; then echo "${PLUGIN_INF}: No Info.plist" >> versions 2>&1 fi fi echo "${PLUGIN}" >> versions 2>&1 ENABLED="Enabled" BOOL=`scutil --get "${PLUGIN_INF}" / Enabled 2>/dev/null` if [ $? -eq 0 ]; then if [ ${BOOL} = "TRUE" ]; then ENABLED="Enabled*" else ENABLED="Disabled" fi fi echo "\t${ENABLED}" >> versions 2>&1 VERBOSE="" BOOL=`scutil --get "${PLUGIN_INF}" / Verbose 2>/dev/null` if [ $? -eq 0 ]; then if [ ${BOOL} = "TRUE" ]; then VERBOSE="Verbose" fi fi if [ -n "${VERBOSE}" ]; then echo "\t${VERBOSE}" >> versions 2>&1 fi VERSION=`scutil --get "${PLUGIN_INF}" / CFBundleVersion 2>/dev/null` if [ $? -eq 1 ]; then VERSION=`scutil --get "${PLUGIN_INF}" / CFBundleShortVersionString 2>/dev/null` fi echo "\tVersion: ${VERSION}" >> versions 2>&1 if [ -f "${PLUGIN_DIR}/Contents/MacOS/${PLUGIN%.*}" ]; then SUM=`sum "${PLUGIN_DIR}/Contents/MacOS/${PLUGIN%.*}"` echo "\tsum: ${SUM}" >> versions 2>&1 LSINFO=`ls -lu "${PLUGIN_DIR}/Contents/MacOS/${PLUGIN%.*}"` echo "\tadditional info: ${LSINFO}" >> versions 2>&1 elif [ -f "${PLUGIN_DIR}/${PLUGIN%.*}" ]; then SUM=`sum "${PLUGIN_DIR}/${PLUGIN%.*}"` echo "\tsum: ${SUM}" >> versions 2>&1 LSINFO=`ls -lu "${PLUGIN_DIR}/${PLUGIN%.*}"` echo "\tadditional info: ${LSINFO}" >> versions 2>&1 fi echo "" >> versions 2>&1 done } if [ -x /usr/bin/what -a -x /usr/bin/sum -a -x /bin/ls ]; then get_binary_info get_plugins_info fi # # collect the logarchive # if [ -x /usr/bin/log ]; then LOGARCHIVE_START_TIME=`date -v -1d +"%Y-%m-%d %H:%M:%S"` LOGARCHIVE_OUTPUT="system_logs.logarchive" ${PRIV} /usr/bin/log collect --livedata --output "${LOGARCHIVE_OUTPUT}" --start "${LOGARCHIVE_START_TIME}" 2>/dev/null if [ -d ${LOGARCHIVE_OUTPUT} ]; then ${PRIV} chown -R ${UID} "${LOGARCHIVE_OUTPUT}" fi fi # # dmesg # if [ -x /sbin/dmesg ]; then ${PRIV} /sbin/dmesg > dmesg fi # # ppp log file(s) # scutil <<_END_OF_INPUT \ | awk -F' *: *' \ ' \ /Logfile : / { \ if (index($2, "/") == 1) { print $2 } \ else { print "/var/log/ppp/" $2 } \ } \ END { \ print "/tmp/pppotcp.log" \ } \ ' \ | sort -u \ | while read logFile open show Setup:/Network/Service/[^/]+/PPP pattern quit _END_OF_INPUT do if [ -f "${logFile}" ]; then b="`basename ${logFile}`" cat "${logFile}" > "${b}" 2>&1 fi done if [ -x /bin/ls ]; then # # collect crash reports # for daemon in \ InternetSharing \ SCHelper \ SCMonitor \ awacsd \ bootpd \ configd \ discoveryd \ discoveryd_helper \ eapolclient \ mDNSResponder \ mDNSResponderHelper \ pppd \ racoon \ socketfilterfw \ do /bin/ls -1 /Library/Logs/DiagnosticReports/${daemon}_*.crash \ /Library/Logs/DiagnosticReports/${daemon}_*.ips \ /Library/Logs/CrashReporter/${daemon}_*.crash \ /Library/Logs/CrashReporter/${daemon}_*.ips \ /Library/Logs/CrashReporter/${daemon}_*.plist \ 2>/dev/null \ | while read log do if [ -f "${log}" ]; then b="`basename ${log}`" ${PRIV} cat "${log}" > "${b}" 2>&1 fi done done fi # # stackshot # if [ -x /usr/local/bin/crstackshot ]; then /usr/local/bin/crstackshot 2>/dev/null fi # # wait for background activity (eg: lsof) # wait # # Stop the packet capture # stop_pcap if [ $NO_TAR -eq 0 ]; then # # collect everything into a single archive # cd "${WORKDIR}/.." tar -c ${GZ_OPT} -f "${ARCHIVE}" "${OUT}" rm -rf "${WORKDIR}" if [ ${UID} -eq 0 ]; then if [ -n "${SUDO_UID}" -a -n "${SUDO_GID}" ]; then if [ ${UID} -ne ${SUDO_UID} ]; then chown ${SUDO_UID}:${SUDO_GID} "${ARCHIVE}" fi fi fi echo "Network data collected to \"${ARCHIVE}\"" else mv "${WORKDIR}" "${OUTDIR}" if [ ${UID} -eq 0 ]; then if [ -n "${SUDO_UID}" -a -n "${SUDO_GID}" ]; then if [ ${UID} -ne ${SUDO_UID} ]; then chown -R ${SUDO_UID}:${SUDO_GID} "${OUTDIR}/${OUT}" fi fi fi echo "Network data collected to \"${OUTDIR}/${OUT}\"" fi