[
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n  pull_request:\n\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Install ShellCheck\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y shellcheck\n\n      - name: Bash syntax check\n        run: |\n          bash -n xsos\n          bash -n xsos-bash-completion.bash\n\n      - name: ShellCheck (errors only)\n        run: |\n          shellcheck -S error -x xsos xsos-bash-completion.bash\n"
  },
  {
    "path": "CONTRIB.md",
    "content": "# Contributing to xsos\n\nSome suggestions for contributors.\n\nThe upstream sos guidelines provide good git practice with branches and commits:\n\nhttps://github.com/sosreport/sos/wiki/Contribution-Guidelines\n\n## Style\n\nTry to keep roughly within the established bash/awk style.\n\n## Testing\n\n### Lint / static checks\n\nThe CI runs the following checks locally; please run them before opening a PR:\n\n```bash\nbash -n xsos\nbash -n xsos-bash-completion.bash\n\n# ShellCheck is optional locally but strongly recommended.\n# CI runs ShellCheck in \"errors only\" mode to catch real breakage while avoiding\n# a huge amount of warning-only churn.\nshellcheck -S error -x xsos xsos-bash-completion.bash\n```\n\n### Targets - what xsos is run against\n\nWhere possible, test against sosreports from the in-support versions of RHEL and Ubuntu LTS.\n\nsosreport 3.9 onwards needs to be run with `sosreport --allow-system-changes`\n\nFedora would also be nice.\n\n### Clients - what xsos is actually run on\n\nTest execution of the script on latest RHEL and Ubuntu LTS.\n\nFedora would also be nice.\n\n"
  },
  {
    "path": "README.md",
    "content": "xsos - Summarize system info from sosreports\n===================================================\n\n**Jump to ...**\n\n* [I'M LOOKING FOR RSAR](https://github.com/ryran/rsar)\n* [SCREEN SHOTS](#screen-shots)\n* [INTRO](#intro)\n* [INSTALLATION](#installation)\n* [EXAMPLES IN ACTION](#examples-in-action)\n* [REQUIREMENTS](#requirements)\n* [THINGS THAT MIGHT SURPRISE YOU](#things-that-might-surprise-you)\n* [AUTHORS](#authors)\n* [LICENSE](#license)\n\n\nSCREEN SHOTS\n-------\n\n**`xsos -om` OR `xsos --os --mem` would show something like the following:**\n\n![xsos parsing general os info and /proc/meminfo](http://b19.org/linux/xsos-osmem.png)\n\n**`xsos -cln` OR `xsos --cpu --lspci --net` could show this:**\n\n![xsos parsing /proc/cpuinfo, lspci, /proc/net/dev](http://b19.org/linux/xsos-cln.png)\n\n**`xsos -e` OR `xsos --ethtool` output looks like this:**\n\n![xsos parsing ethtool output](http://b19.org/linux/xsos-e.png)\n\n\nINTRO\n-------\n\nThe goal of `xsos` is to make it easy to instantaneously gather information about a system together in an easy-to-read-summary, whether that system is the localhost on which xsos is being run or a system for which you have an unpacked sosreport.\n\nThere is tons of useful amazing instructive data available to normal users (not to mention root) on a Linux system, but by design, this information is spread out across myriad files. Some of it even requires commands to parse through.\n\n`xsos` will attempt to make it easy, parsing and calculating and formatting data from dozens of files (and commands) to give you a detailed overview about a system, or -- if requested -- `xsos` will only parse one file (e.g. with `--mem` or `--cpu`) or output from one command (e.g. with `--ip` or `--ps`).\n\nNew features are being added all the time -- see [the tracker](https://github.com/ryran/xsos/issues) to have a look at some of the things that are already in line to be worked on.\n\n**[Why another tool? Why not add stuff to `sxconsole`?](https://github.com/ryran/xsos/issues/9)**\n\n\nINSTALLATION\n-------\n\n*\"I'm sold! How do I install xsos?\"*\n\nGet the latest version directly by downloading the main xsos file from [bit.ly/xsos-direct](http://bit.ly/xsos-direct) (which points to [raw.github.com/ryran/xsos/master/xsos](https://raw.github.com/ryran/xsos/master/xsos)). Updating will need to be done manually by re-downloading.\n\nFor a personal non-root install, run the following as your normal user:\n\n```\nmkdir -p ~/bin/\ncurl -Lo ~/bin/xsos bit.ly/xsos-direct\n```\n\nThen open a new terminal (your `~/.profile` should add `~/bin/` into `%PATH`).\n\nFor a system-wide install, run the following as root:\n   \n```\ncurl -Lo /usr/local/bin/xsos bit.ly/xsos-direct\nchmod +x /usr/local/bin/xsos\n```\n\nOnce xsos is installed, run `xsos -h` as a normal user to see the help page and get started.\n\nEXAMPLES IN ACTION\n-------\nThe lovely thing that isn't going to be captured here is all the coloring done to make things easier to read. There's actually quite a bit of color-logic to warn of various conditions...\n\n**Run on a sosreport with no options:**\n\n```\n[rsaw]$ xsos aczx998pinkle/\nOS\n  Hostname: aczx998pinkle\n  Distro:   [redhat-release] Red Hat Enterprise Linux Server release 5.5 (Carthage)\n            [enterprise-release] Enterprise Linux Enterprise Linux Server release 5.5 (Carthage)\n  RHN:      serverURL=https://linux-update.oracle.com/XMLRPC\n  Runlevel: N 3  (default 3)\n  SELinux:  permissive  (default enforcing)\n  Arch:     mach=x86_64  cpu=x86_64  platform=x86_64\n  Kernel:\n    Booted kernel:  2.6.18-238.12.2.0.2.el5\n    GRUB default:   2.6.18-238.12.2.0.2.el5\n    Build version:\n      Linux version 2.6.18-238.12.2.0.2.el5 (mockbuild@ca-build9.us.oracle.com) (gcc version 4.1.2\n      20080704 (Red Hat 4.1.2-50)) #1 SMP Tue Jun 28 05:21:19 EDT 2011\n    Booted kernel cmdline:\n      root=/dev/md6 ro bootarea=c0d0 loglevel=7 panic=60 debug rhgb numa=off console=ttyS0,115200n8\n      console=tty1 crashkernel=128M@16M bootfrom=CELLBOOT audit=1 processor.max_cstate=1 nomce\n    GRUB default kernel cmdline:\n      root=/dev/md6 ro bootarea=c0d0 loglevel=7 panic=60 debug rhgb numa=off console=ttyS0,115200n8\n      console=tty1 crashkernel=128M@16M bootfrom=BOOT audit=1 processor.max_cstate=1 nomce\n    Kernel taint-check: 536870912 512 64 16 1\n      Technology Preview code is loaded\n      Taint on warning\n      Userspace-defined naughtiness\n      System experienced a machine check exception\n      Proprietary module has been loaded\n    - - - - - - - - - - - - - - - - - - -\n  Sys time:  Mon Oct 29 10:55:02 CDT 2012\n  Boot time: Sat Apr 28 03:29:56 CDT 2012  (1335583796)\n  Uptime:    184 days, 12:25,  1 user\n  LoadAvg:   [24 CPU] 2.34 (10%), 1.27 (5%), 0.95 (4%)\n  /proc/stat:\n    procs_running: 4    procs_blocked: 1    processes: 248052571\n    cpu:  [Break-down of CPU time since boot]\n      us 1%, ni 0%, sys 1%, idle 96%, iowait 2%, irq 0%, sftirq 0%, steal 0%\n```\n\n\n**While xsos is always being improved, here's the current minimal help page (run `xsos -h`):**\n\n```\nUsage: xsos [DISPLAY OPTIONS] [-6abokcfmdtlerngispSFIN] [SOSREPORT ROOT]\n  or:  xsos [DISPLAY OPTIONS] {--B|--C|--F|--M|--D|--T|--L|--R|--N|--G|--I|--P FILE}...\n  or:  xsos [-?|-h|--help]\n\nDisplay system info from localhost or extracted sosreport\n\nContent options:\n -a, --all       show everything\n -b, --bios      show info from dmidecode\n -o, --os        show hostname, distro, SELinux, kernel info, uptime, etc\n -k, --kdump     inspect kdump configuration\n -c, --cpu       show info from /proc/cpuinfo\n -f, --intrupt   show info from /proc/interrupts\n -m, --mem       show info from /proc/meminfo\n -d, --disks     show info from /proc/partitions, dm-multipath, lsblk, df\n -t, --mpath     show info from dm-multipath\n -l, --lspci     show info from lspci\n -e, --ethtool   show info from ethtool\n -r, --softirq   show info from /proc/net/softnet_stat\n -n, --netdev    show info from /proc/net/dev\n -g, --bonding   show bonding and teaming info\n -i, --ip        show info from ip addr (BASH v4+ required)\n     --net       alias for: --lspci --ethtool --softirq --netdev --bonding --ip\n -s, --sysctl    show important kernel sysctls\n -p, --ps        inspect running processes via ps\n -S, --ss        inspect running processes via ss\n -F, --firewall  show firewall status\n -I, --ifcfg     show ifcfg files summary\n -N, --netstat   show info from /proc/net/netstat\n\nDisplay options:\n     --scrub        remove from output: IP/MAC addrs, hostnames, serial numbers,\n                    proxy user & passwords\n -6, --ipv6         parse ip addr output for IPv6 addresses instead of IPv4\n -q, --wwid=ID      restrict dm-multipath output to a particular mpath device,\n                    where ID is a wwid, friendly name, or LUN identifier\n -u, --unit=P       change byte display for /proc/meminfo & /proc/net/dev,\n                    where P is \"b\" for byte, or else \"k\", \"m\", \"g\", or \"t\"\n     --threads      make ps take threads into account (via `ps auxm`)\n -v, --verbose=NUM  specify ps verbosity level (0-4, default: 1)\n -w, --width=NUM    change fold-width, in columns (positive number, e.g., 80)\n                    \"0\" disables wrapping, \"w\" autodetects width (default)\n -x, --nocolor      disable output colorization\n -y, --less         send output to `less -SR`\n -z, --more         send output to `more`\n\nSpecial options (BASH v4+ required):\n --B=FILE  read from FILE containing `dmidecode` dump\n --C=FILE  read from FILE containing /proc/cpuinfo dump\n --F=FILE  read from FILE containing /proc/interrupts dump\n --M=FILE  read from FILE containing /proc/meminfo dump\n --D=FILE  read from FILE containing /proc/partitions dump\n --T=FILE  read from FILE containing `multipath -v4 -ll` dump\n --L=FILE  read from FILE containing `lspci` dump\n --R=FILE  read from FILE containing /proc/net/softnet_stat dump\n --N=FILE  read from FILE containing /proc/net/dev dump\n --G=FILE  read from FILE containing /proc/net/bonding/xxx dump\n --I=FILE  read from FILE containing `ip addr` dump\n --P=FILE  read from FILE containing `ps aux` dump\n\nRun with \"--help\" to see full help page\n\nVersion info: xsos v0.7.40 last mod 2025-12-01\nSee <github.com/ryran/xsos> to report bugs or suggestions\n```\n\n\n**Here it is run on my laptop as root, with specific options:**\n\n```\n[rsaw]$ sudo xsos --bios --ip --lspci --ethtool --net --ps  # would be same as 'xsos -bilenp'\nDMIDECODE\n  BIOS:\n    LENOVO, version 8CET50WW (1.30 ), 11/01/2011\n  System:\n    Mfr:  LENOVO\n    Prod: 4174AQ5\n    Vers: ThinkPad T420s\n    Ser:  R9XXXXXXXX\n    UUID: 56EABD01-XXXX-11CB-9DE6-XXXXXXXXXX\n  CPU:\n    1 of 1 CPU sockets populated, 2 cores/4 threads per CPU\n    2 total cores, 4 total threads\n    Mfr:  Intel(R) Corporation\n    Fam:  Core i5\n    Freq: 2600 MHz\n    Vers: Intel(R) Core(TM) i5-2540M CPU @ 2.60GHz\n  Memory:\n    8192 MB (8 GB) total\n    2 of 4 DIMMs populated (system max capacity 16 GB)\n\nLSPCI\n  Net/Storage:\n    (1) Intel Corporation Centrino Ultimate-N 6300 (rev 3e)\n    (1) Intel Corporation 82579LM Gigabit Network Connection (rev 04)\n  VGA:\n    Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller (rev 09)\n\nETHTOOL\n  Interface Status:\n    em1         link=up 1000Mb/s full (autoneg=Y)  drv e1000e v2.2.14-k / fw 0.13-3\n    tun0        link=up 10Mb/s full (autoneg=N)    drv tun v1.6\n    virbr0      link=DOWN                          drv bridge v2.3 / fw N/A\n    virbr0-nic  link=DOWN                          drv tun v1.6\n    wlan0       link=up                            drv iwlwifi v3.9.6-200.fc18.x86_64 / fw 9.221.4.1\n  Interface Errors:\n    em1  dropped_smbus: 267\n\n\nIP\n  Interface   Slave Of  IPv4 Address        State  MAC Address\n  =========   ========  ==================  =====  =================\n  lo          -         127.0.0.1/8         up     -\n  em1         -         192.168.0.20/24     up     f0:de:f1:ba:cf:c4\n  wlan0       -         10.7.7.111/24       up     24:77:03:41:41:18\n                        192.168.17.17/32\n  virbr0      -         192.168.122.1/24    up     52:54:00:97:e3:ee\n  virbr0-nic  -         -                   DOWN   52:54:00:97:e3:ee\n  tun0        -         10.10.49.81/32      up     -\n\nNETDEV\n  Interface   RxMiBytes  RxPackets  RxErrs  RxDrop  TxMiBytes  TxPackets  TxErrs  TxDrop  TxColls\n  =========   =========  =========  ======  ======  =========  =========  ======  ======  =======\n  em1         6715       6940 k     0       0       6715       1972 k     0       0       0\n  tun0        0          0 k        0       0       0          0 k        0       0       0\n  virbr0      8          41 k       0       0       8          37 k       0       0       0\n  virbr0-nic  0          0 k        0       0       0          0 k        0       0       0\n  wlan0       1902       1761 k     0       0       1902       1139 k     0       0       0\n\n\nPS CHECK\n  Total number of processes:\n    291\n  Top users of CPU & MEM:\n    USER  %CPU   %MEM   RSS\n    rsaw  34.1%  46.0%  3.81 GiB\n    qemu  27.4%  4.9%   0.38 GiB\n    root  2.7%   1.0%   0.20 GiB\n  Uninteruptible sleep & Defunct processes:\n    USER     PID    %CPU  %MEM  VSZ-MiB  RSS-MiB  TTY    STAT   START  TIME    COMMAND\n    rsaw     5287   0.0   0.0   0        0        pts/0  D+     17:19  0:00    [cat]\n    rsaw     5125   0.0   0.0   0        0        ?      Z      Dec16  0:48    [chromium-browse] <defunct>\n    rsaw     8307   0.2   0.0   0        0        ?      Z      Dec17  3:07    [chromium-browse] <defunct>\n    rsaw     8867   0.0   0.0   0        0        ?      Z      Dec17  1:20    [xchat] <defunct>\n    rsaw     9533   0.0   0.0   0        0        ?      Z      Dec17  0:32    [gedit] <defunct>\n  Top CPU-using processes:\n    USER     PID    %CPU  %MEM  VSZ-MiB  RSS-MiB  TTY    STAT   START  TIME    COMMAND\n    qemu     613    27.4  4.9   3094     393      ?      Sl     00:38  0:29    /usr/bin/qemu-kvm -S -M\n    rsaw     23059  13.7  2.3   1091     185      ?      Sl     Dec26  21:34   /proc/self/exe --type=plugin --plugin-path=/usr/lib64/flash-plugin/libflashplayer.so\n    rsaw     621    5.9   0.8   964      65       ?      Ss     00:38  0:06    python /usr/share/virt-manager/virt-manager.py\n    rsaw     2137   5.3   18.7  2705     1472     ?      Sl     Dec24  204:37  /usr/lib64/firefox/firefox\n    root     1226   2.2   0.5   135      42       tty1   Ss+    Dec24  87:57   /usr/bin/Xorg :0 -background\n    rsaw     11901  2.1   4.2   2319     335      ?      SLl    Dec24  74:54   /usr/bin/gnome-shell\n    rsaw     22866  2.0   1.6   898      128      ?      Sl     Dec26  3:11    /usr/lib64/chromium-browser/chromium-browser --enable-plugins --enable-extensions\n    rsaw     29408  1.3   0.5   1218     39       ?      Sl     Dec26  0:37    gedit\n    rsaw     23084  0.8   1.2   1140     99       ?      Sl     Dec26  1:18    /usr/lib64/chromium-browser/chromium-browser --type=renderer --lang=en-US\n    rsaw     22952  0.8   1.7   1168     141      ?      Sl     Dec26  1:22    /usr/lib64/chromium-browser/chromium-browser --type=renderer --lang=en-US\n  Top MEM-using processes:\n    USER     PID    %CPU  %MEM  VSZ-MiB  RSS-MiB  TTY    STAT   START  TIME    COMMAND\n    rsaw     2137   5.3   18.7  2705     1472     ?      Sl     Dec24  204:37  /usr/lib64/firefox/firefox\n    qemu     613    27.4  4.9   3094     393      ?      Sl     00:38  0:29    /usr/bin/qemu-kvm -S -M\n    rsaw     11901  2.1   4.2   2319     335      ?      SLl    Dec24  74:54   /usr/bin/gnome-shell\n    rsaw     23059  13.7  2.3   1091     185      ?      Sl     Dec26  21:34   /proc/self/exe --type=plugin --plugin-path=/usr/lib64/flash-plugin/libflashplayer.so\n    rsaw     22952  0.8   1.7   1168     141      ?      Sl     Dec26  1:22    /usr/lib64/chromium-browser/chromium-browser --type=renderer --lang=en-US\n    rsaw     22866  2.0   1.6   898      128      ?      Sl     Dec26  3:11    /usr/lib64/chromium-browser/chromium-browser --enable-plugins --enable-extensions\n    rsaw     23214  0.6   1.5   1141     121      ?      Sl     Dec26  0:59    /usr/lib64/chromium-browser/chromium-browser --type=renderer --lang=en-US\n    rsaw     23004  0.0   1.2   1130     100      ?      Sl     Dec26  0:06    /usr/lib64/chromium-browser/chromium-browser --type=renderer --lang=en-US\n    rsaw     22959  0.0   1.2   1127     100      ?      Sl     Dec26  0:05    /usr/lib64/chromium-browser/chromium-browser --type=renderer --lang=en-US\n    rsaw     23084  0.8   1.2   1140     99       ?      Sl     Dec26  1:18    /usr/lib64/chromium-browser/chromium-browser --type=renderer --lang=en-US\n```\n\n\n\n**Run on another sosreport with some options:**\n\n```\n[rsaw]$ xsos 8308201prodserv --disks --mem --unit=m\nMEMORY\n  Stats graphed as percent of MemTotal:\n    MemUsed    ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◇◇  96.0%\n    HugePages  ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇  60.5%\n    Buffers    ◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇   0.6%\n    Cached     ◆◆◆◆◆◆◆◆◆◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇  18.6%\n    Dirty      ◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇◇   0.0%\n  RAM:\n    64363 MiB total ram\n    61815 MiB (96%) used\n    49451 MiB (76.8%) used excluding Buffers/Cached\n    5 MiB (0%) dirty\n  HugePages:\n    38912 MiB pre-allocated to HugePages (60.5% of total ram)\n    38146 MiB of HugePages (98%) in-use by applications\n  LowMem/Slab/PageTables/Shmem:\n    61815 MiB (96%) of 64363 MiB LowMem in-use\n    1192 MiB (1.9%) of total ram used for Slab\n    349 MiB (0.5%) of total ram used for PageTables\n  Swap:\n    464 MiB (2.8%) used of 16381 MiB total\n\nSTORAGE\n  Multipath:\n    archive    2.0 T\n    dbbackup   850 G\n    dgspool    20 G\n    miscspool  100 G\n    proddb     200 G\n    prodstage  100 G\n    produpgdb  150 G\n    reportdb   30 G\n    tsttrndev  150 G\n  Disks:\n    (Multipath and/or software raid components hidden)\n    1 disks, totaling 272 GiB (0.27 TiB)\n    sda   271.9 G\n\n[rsaw]$ xsos --net --unit k 8308201prodserv\nNETDEV\n  Interface  RxKiBytes     RxPackets     RxErrs  RxDrop     TxKiBytes     TxPackets     TxErrs  TxDrop\n  =========  =========     =========     ======  ======     =========     =========     ======  ======\n  eth0       23569277      300080406     0       0          23569277      480926218     0       0\n  eth1       144484269105  342207919183  0       4494 (0%)  144484269105  357978804158  0       0\n  eth2       428438229206  392560553366  0       373 (0%)   428438229206  330736051661  0       0\n  eth4       37184228554   55232280858   0       2350 (0%)  37184228554   35535848225   0       0\n\n\n[rsaw]$ xsos -nug 8308201prodserv\nNETDEV\n  Interface  RxGiBytes  RxPackets  RxErrs  RxDrop     TxGiBytes  TxPackets  TxErrs  TxDrop\n  =========  =========  =========  ======  ======     =========  =========  ======  ======\n  eth0       22.5       300 M      0       0          22.5       481 M      0       0\n  eth1       137791     342208 M   0       4494 (0%)  137791     357979 M   0       0\n  eth2       408590     392561 M   0       373 (0%)   408590     330736 M   0       0\n  eth4       35461.6    55232 M    0       2350 (0%)  35461.6    35536 M    0       0\n```\n\n\n\n**Run on a sosreport again, showing sysctls:**\n\n```\n[rsaw]$ xsos --sysctl boomyaow/\nSYSCTLS\n  kernel.\n    hostname =  boomyaow03\n    osrelease =  2.6.32-220.13.1.el6.x86_64\n    tainted =  0  (kernel untainted)\n    random.boot_id =  defb55c5-c2bb-4e4e-86c3-745d80a6585d\n    random.entropy_avail [bits] =  154\n    hung_task_panic [bool] =  0\n    hung_task_timeout_secs =  120  (secs task must be D-state to trigger)\n    msgmax [bytes] =  65536\n    msgmnb [bytes] =  65536\n    msgmni [msg queues] =  32768\n    panic [secs] =  0  (no autoreboot on panic)\n    panic_on_oops [bool] =  1\n    panic_on_unrecovered_nmi [bool] =  0\n    pid_max =  32768\n    threads-max =  1029998\n    sem [array] =  250  32000  32  4096\n      SEMMSL (max semaphores per array) =  250\n      SEMMNS (max sems system-wide)     =  32000\n      SEMOPM (max ops per semop call)   =  32\n      SEMMNI (max number of sem arrays) =  4096\n    shmall [4-KiB pages] =  4294967296  (16384.0 GiB max total shared memory)\n    shmmax [bytes] =  68719476736  (64.00 GiB max segment size)\n    shmmni [segments] =  4096  (max number of segs)\n    sysrq [bitmask] =  0  (disallowed)\n  fs.\n    file-max [fds] =  6512672  (system-wide limit on nr open file descriptors)\n    file-nr [fds] =  2496  0  6512672  (nr allocated fds, N/A, nr free fds)\n    inode-nr [inodes] =  78574  1  (nr_inodes allocated, nr_free_inodes)\n  net.\n    core.rmem_max [bytes] =  131071  (127 KiB)\n    core.wmem_max [bytes] =  131071  (127 KiB)\n    core.rmem_default [bytes] =  124928  (122 KiB)\n    core.wmem_default [bytes] =  124928  (122 KiB)\n    ipv4.icmp_echo_ignore_all [bool] =  0\n    ipv4.ip_forward [bool] =  0\n    ipv4.tcp_max_orphans [sockets] =  65536  (4096 MiB @ max 64 KiB per orphan)\n    ipv4.tcp_mem [4-KiB pages] =  6179904  8239872  12359808  (23.57 GiB, 31.43 GiB, 47.15 GiB)\n    ipv4.udp_mem [4-KiB pages] =  6179904  8239872  12359808  (23.57 GiB, 31.43 GiB, 47.15 GiB)\n    ipv4.tcp_window_scaling [bool] =  1\n    ipv4.tcp_rmem [bytes] =  4096  87380  4194304  (4 KiB, 85 KiB, 4096 KiB)\n    ipv4.tcp_wmem [bytes] =  4096  16384  4194304  (4 KiB, 16 KiB, 4096 KiB)\n    ipv4.udp_rmem_min [bytes] =  4096  (4 KiB)\n    ipv4.udp_wmem_min [bytes] =  4096  (4 KiB)\n  vm.\n    dirty_ratio =  20  (% of total system memory)\n    dirty_bytes =  0  (disabled -- check dirty_ratio)\n    dirty_background_ratio =  10  (% of total system memory)\n    dirty_background_bytes =  0  (disabled -- check dirty_background_ratio)\n    dirty_expire_centisecs =  3000\n    dirty_writeback_centisecs =  500\n    nr_hugepages [2-MiB pages] =  0\n    overcommit_memory [0-2] =  0  (heuristic overcommit)\n    overcommit_ratio =  50\n    oom_kill_allocating_task [bool] =  0  (scan tasklist)\n    panic_on_oom [0-2] =  0  (no panic)\n    swappiness [0-100] =  60\n```\n\n\n**Finally, here's example of using some of the Special options, which allow you to specify a specific file instead of a full sosreport or having `xsos` run on your local system:**\n\n```\n[rsaw]$ xsos -v0 --B /tmp/dmidecode.txt --I=/tmp/ipaddr.dump --P /tmp/psaux.txt\nDMIDECODE\n  BIOS:\n    HP, version P66, 06/24/2011\n  System:\n    Mfr:  HP\n    Prod: ProLiant DL980 G7\n    Vers: Not Specified\n    Ser:  CZ3XXXXXXXX\n    UUID: 35344D41-XXXXXX-5A43-3331-XXXXXXXXXXX\n  CPU:\n    8 of 8 CPU sockets populated, 8 cores/16 threads per CPU\n    64 total cores, 128 total threads\n    Mfr:  Intel\n    Fam:  Xeon\n    Freq: 2133 MHz\n    Vers: Intel(R) Xeon(R) CPU E7- 2830 @ 2.13GHz\n  Memory:\n    262144 MB (256 GB) total\n    32 of 128 DIMMs populated (system max capacity 512 GB)\n\nIP\n  Interface  Slave Of  MAC Address        State  IPv4 Address\n  =========  ========  =================  =====  ==================\n  lo         -         -                  up     127.0.0.1/8\n  lo:0       -         -                  up     192.168.160.20/32\n  eth0       -         ZZ:xy:56:01:12:qr  up     192.168.160.11/24\n  eth1       -         ZZ:xy:9a:1a:19:qr  up     10.79.4.68/23\n  eth1:1     -         ZZ:xy:9a:1a:19:qr  up     10.79.4.70/23\n  eth2       -         ZZ:xy:28:fd:19:qr  up     10.10.10.8/28\n  eth4       -         ZZ:xy:9e:0b:19:qr  up     192.168.254.8/28\n  eth5       bond0     ZZ:xy:b5:0b:19:qq  up     -\n  eth6       bond0     ZZ:xy:b5:0b:1a:qq  up     -\n  eth7       -         ZZ:xy:35:00:99:qq  DOWN   -\n  bond0      -         ZZ:zz:ZZ:zz:ZZ:zz  up     10.180.162.22/24\n\nPS CHECK\n  Total number of processes:\n    1393\n  Top users of CPU & MEM:\n    USER    %CPU    %MEM      RSS\n    oracle  909.8%  60649.2%  38137.57 GiB\n    root    130.8%  2.7%      1.93 GiB\n  Uninteruptible sleep & Defunct processes:\n    USER     PID    %CPU  %MEM  VSZ-MiB  RSS-MiB  TTY    STAT  START  TIME      COMMAND  \n    oracle   7883   0.3   59.3  141      38177    ?      Ds    Jul31  2:33      oracleCRELSP4\n    oracle   11028  0.1   59.3  154      38170    ?      Ds    Jun30  49:08     ora_arc8_CRELSP4\n    oracle   13816  0.0   59.3  140      38171    ?      Ds    Jul31  0:12      oracleCRELSP4\n    oracle   15184  0.4   59.3  141      38176    ?      Ds    Jul31  3:01      oracleCRELSP4\n    oracle   15423  0.5   59.3  143      38179    ?      Ds    Jul31  3:32      oracleCRELSP4\n    oracle   17334  0.0   59.3  143      38176    ?      Ds    Jul31  0:14      oracleCRELSP4\n    oracle   18502  0.3   59.3  141      38176    ?      Ds    Jul31  2:39      oracleCRELSP4\n    root     18514  2.0   0.0   0        0        ?      D<    10:33  0:00      /bin/grep\n    oracle   20751  0.8   59.3  143      38178    ?      Ds    Jul31  5:21      oracleCRELSP4\n    oracle   24385  0.6   59.3  142      38175    ?      Ds    Jul31  4:05      oracleCRELSP4\n    oracle   24557  0.4   59.3  140      38173    ?      Ds    10:22  0:02      oracleCRELSP4\n    oracle   24718  1.3   59.3  143      38178    ?      Ds    Jul31  8:57      oracleCRELSP4\n    oracle   29008  2.8   59.3  143      38176    ?      Ds    09:38  1:34      oracleCRELSP4  \n  Top CPU-using processes:\n    USER     PID    %CPU  %MEM  VSZ-MiB  RSS-MiB  TTY    STAT  START  TIME      COMMAND  \n    root     18329  104   0.0   50       2        pts/6  R+    10:33  0:03      /bin/netstat\n    oracle   11160  19.7  59.3  146      38174    ?      Ss    Jun30  9012:36   oracleCRELSP4\n    oracle   14014  10.6  59.3  140      38173    ?      Ss    10:32  0:05      oracleCRELSP4\n    root     6455   5.9   0.1   415      83       ?      Sl    Jan25  16265:29  /space/java/jdk1.5.0_20/bin/java\n    root     6515   5.3   0.0   0        0        ?      R     Jan14  15483:17  [rpciod]\n  Top MEM-using processes:\n    USER     PID    %CPU  %MEM  VSZ-MiB  RSS-MiB  TTY    STAT  START  TIME      COMMAND  \n    oracle   7847   0.0   59.4  249      38257    ?      Ss    Jun30  0:52      ora_diag_CRELSP4\n    oracle   1912   0.0   59.3  160      38185    ?      Ss    Jul22  12:29     ora_j001_CRELSP4\n    oracle   10937  0.1   59.3  167      38185    ?      Ss    Jun30  53:14     ora_arc3_CRELSP4\n    oracle   10920  0.1   59.3  167      38185    ?      Ss    Jun30  58:05     ora_arc1_CRELSP4\n    oracle   11037  0.1   59.3  167      38184    ?      Ss    Jun30  53:33     ora_arc9_CRELSP4\n```\n\n\nREQUIREMENTS\n-------\n\n* As detailed in the help page, BASH version 4 (rhel 6+) is required for -i/--ip and for any of the \"Special options\" like `--C` or `--B`. Colorization is also not done unless BASH v4+ is detected.\n* Other than that, nothing special for command requirements -- `xsos` uses standard coreutils & util-linux commands, along with, of course ... `gawk` and `sed`.\n* No absolute paths used for commands.\n* When running on localhost (i.e. not a sosreport), `xsos` gracefully reports as much of what's requested as possible when running as non-root (`--bios` and `--ethtool` require root privileges; `--disks` won't be able to print dm-multipath output without root privs).\n\n\nTHINGS THAT MIGHT SURPRISE YOU\n-------\n\n* xsos does some pretty intensive color-formatting to make the output more easily-readable (can be disabled with `-x` or `--nocolor` and colors can be modified via environment variables).\n  * If you like the color but need to use a pager, use the `--less` (`-y`) or `--more` (`-z`) options to auto-pipe output to `less -SR` or `more`.\n* There are a bunch of environment variables that you can use to tweak behavior. See [the original commit comment](https://github.com/ryran/xsos/commit/0c05168d3729d44f4ddf07269b33105f85a306de#commitcomment-2133859) for documentation.\n* There's a bash autocompletion function defition available for xsos. Use it.\n* When printing disk info with `-d/--disks`, xsos automatically detects linux software raid (md) devices and hides their components. The `multipath` command is also consulted to print info about native multipathd devices. All LUNs that are part of a dm-multipath map are also hidden from the disk output.\n* You can use the `--unit` (`-u`) option to change how `/proc/meminfo` and `/proc/net/dev` are parsed -- displaying units in anything from bytes up to tebibytes. Note that this option does *not* affect display of the `VSZ` & `RSS` fields in the ps output. (For that, manually set the `XSOS_PS_UNIT` variable to `k`, `m`, or `g`.)\n\n\nAUTHORS\n-------\n\nAs far as direct contributions go, so far it's just me, [ryran](/ryran), aka rsaw, aka [Ryan Sawhill Aroha](http://people.redhat.com/rsawhill). That said, many folks have reported bugs and given suggestions for new features:\n\n- Patrick Talbert especially deserves a huge shout-out! Using xsos on sosreports while diagnosing networking issues, he's uncovered many an odd corner case and discussions with him have led to implementing new features and refining what the networking modules show.\n\n- Jamie Bainbridge has been so consistently kind and effusive in expressing his appreciation of xsos. The RFEs he has suggested (at least the ones we've implemented) have surely made xsos a more powerful tool.\n\n- Joe Wright was the first person to request a kdump module. Turned out to be a great idea!\n\nWhen I was clueless in how to further my awk career early on, two prolific users over on StackOverflow -- [Dennis Williamson](http://stackoverflow.com/users/26428/dennis-williamson) and [ghostdog74](http://stackoverflow.com/users/131527/ghostdog74) -- each provided answers (to two separate questions) with code that was brilliantly instructive. My awk skills have since evolved far beyond what I was trying to do back then, but thanks definitely goes to both of them for that early inspiration.\n\nPlease contact me if you have ideas, suggestions, questions, or want to collaborate on this or something similar. For specific bugs and feature-requests, you can [post a new issue on the tracker](/ryran/xsos/issues).\n\n\nLICENSE\n-------\n\nCopyright (C) 2012-2015 [Ryan Sawhill Aroha](http://people.redhat.com/rsawhill)\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\nGeneral Public License @[gnu.org/licenses/gpl.html](http://gnu.org/licenses/gpl.html>) for more details.\n"
  },
  {
    "path": "xsos",
    "content": "#!/bin/bash\n# xsos v0.7.40 last mod 2025-12-01\n# Latest version at <http://github.com/ryran/xsos>\n# Copyright 2012-2026 Ryan Sawhill Aroha <rsaw@redhat.com> and contributors\n#\n#    This program is free software: you can redistribute it and/or modify\n#    it under the terms of the GNU General Public License as published by\n#    the Free Software Foundation, either version 3 of the License, or\n#    (at your option) any later version.\n#\n#    This program is distributed in the hope that it will be useful,\n#    but WITHOUT ANY WARRANTY; without even the implied warranty of\n#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n#    General Public License <gnu.org/licenses/gpl.html> for more details.\n#-------------------------------------------------------------------------------\n\n# See https://github.com/ryran/xsos/issues/208\nexport LC_ALL=en_US.UTF-8\n\n# Get version from line #2\nversion=$(sed '2q;d' $0)\n\n# Colors and colors and colors oh my (but only for bash v4)\nif [[ $BASH_VERSINFO -ge 4 ]]; then\n  declare -A c\n  c[reset]='\\033[0;0m'   c[BOLD]='\\033[0;0m\\033[1;1m'\n  c[dgrey]='\\033[0;30m'  c[DGREY]='\\033[1;30m'  c[bg_DGREY]='\\033[40m'\n  c[red]='\\033[0;31m'    c[RED]='\\033[1;31m'    c[bg_RED]='\\033[41m'\n  c[green]='\\033[0;32m'  c[GREEN]='\\033[1;32m'  c[bg_GREEN]='\\033[42m'\n  c[orange]='\\033[0;33m' c[ORANGE]='\\033[1;33m' c[bg_ORANGE]='\\033[43m'\n  c[blue]='\\033[0;34m'   c[BLUE]='\\033[1;34m'   c[bg_BLUE]='\\033[44m'\n  c[purple]='\\033[0;35m' c[PURPLE]='\\033[1;35m' c[bg_PURPLE]='\\033[45m'\n  c[cyan]='\\033[0;36m'   c[CYAN]='\\033[1;36m'   c[bg_CYAN]='\\033[46m'\n  c[lgrey]='\\033[0;37m'  c[LGREY]='\\033[1;37m'  c[bg_LGREY]='\\033[47m'\nfi\n\n# ==============================================================================\n# ENVIRONMENT VARIABLES -- Modify these by setting them in your shell\n# environment, e.g. ~/.bash_profile or /etc/profile.d/xsos.sh\n\n# COLORS\n# The following configure defaults for various colors to enhance output\n\n#   XSOS_COLORS (bool: y/n)\n#     Controls whether color is enabled or disabled by default\n#     Can also be controlled by cmdline arg\n      : ${XSOS_COLORS:=\"y\"}\n\n#   XSOS_COLOR_RESET -- color to reset terminal to after using other colors\n      : ${XSOS_COLOR_RESET:=\"reset\"}\n\n#   XSOS_COLOR_H1 -- color for content modules' primary header\n      : ${XSOS_COLOR_H1:=\"RED\"}\n\n#   XSOS_COLOR_H2 -- color for content modules' secondary header\n      : ${XSOS_COLOR_H2:=\"PURPLE\"}\n\n#   XSOS_COLOR_H3 -- color for content modules' tertiary header\n      : ${XSOS_COLOR_H3:=\"BLUE\"}\n\n#   XSOS_COLOR_H4 -- color used only for SYSCTL() module\n      : ${XSOS_COLOR_H4:=\"reset\"}\n\n#   XSOS_COLOR_IMPORTANT -- color for drawing attention to important data\n      : ${XSOS_COLOR_IMPORTANT:=\"BOLD\"}\n\n#   XSOS_COLOR_WARN1 -- color for level-1 warnings\n      : ${XSOS_COLOR_WARN1:=\"orange\"}\n\n#   XSOS_COLOR_WARN2 -- color for level-2 warnings\n      : ${XSOS_COLOR_WARN2:=\"ORANGE\"}\n\n#   XSOS_COLOR_MEMGRAPH_MEMUSED -- color for MemUsed in MEMINFO() graph\n      : ${XSOS_COLOR_MEMGRAPH_MEMUSED:=\"green\"}\n\n#   XSOS_COLOR_MEMGRAPH_HUGEPAGES -- color for HugePages in MEMINFO() graph\n      : ${XSOS_COLOR_MEMGRAPH_HUGEPAGES:=\"cyan\"}\n\n#   XSOS_COLOR_MEMGRAPH_BUFFERS -- color for Buffers in MEMINFO() graph\n      : ${XSOS_COLOR_MEMGRAPH_BUFFERS:=\"purple\"}\n\n#   XSOS_COLOR_MEMGRAPH_CACHED -- color for Cached in MEMINFO() graph\n      : ${XSOS_COLOR_MEMGRAPH_CACHED:=\"blue\"}\n\n#   XSOS_COLOR_MEMGRAPH_DIRTY -- color for Dirty in MEMINFO() graph\n      : ${XSOS_COLOR_MEMGRAPH_DIRTY:=\"red\"}\n\n#   XSOS_COLOR_IFUP -- color for ethtool InterFace \"up\"\n      : ${XSOS_COLOR_IFUP:=\"green\"}\n\n#   XSOS_COLOR_IFDOWN -- color for ethtool InterFace \"down\"\n      : ${XSOS_COLOR_IFDOWN:=\"lgrey\"}\n\n# INDENTATION\n#   The following variables are not used universally and that might not change\n\n#   XSOS_INDENT_H1 -- 1st level of indentation\n      : ${XSOS_INDENT_H1:=\"  \"}\n\n#   XSOS_INDENT_H2 -- 2nd level of indentation\n      : ${XSOS_INDENT_H2:=\"    \"}\n\n#   XSOS_INDENT_H3 -- 3rd level of indentation\n      : ${XSOS_INDENT_H3:=\"      \"}\n\n# XSOS_FOLD_WIDTH (w, 0, or positive number)\n#   Some content modules print line of unpredictable length\n#   This setting controls the wrapping width for commands that use it\n#   Changing to w causes width of terminal to be used\n#   Changing to 0 causes 99999 to be used\n    : ${XSOS_FOLD_WIDTH:=\"w\"}\n\n# XSOS_HEADING_SEPARATOR (str)\n#   Acts as a separator between content modules\n#   Should include at least 1 trailing new-line\n    : ${XSOS_HEADING_SEPARATOR:=\"\\n\"}\n\n# XSOS_ALL_VIEW (str of variables, space-separated)\n#   Controls what content modules to run when -a/--all switch is used\n    : ${XSOS_ALL_VIEW:=\"bios os kdump cpu intrupt mem disks mpath lspci ethtool softirq bonding ip netdev sysctl ps ss firewall\"}\n\n# XSOS_DEFAULT_VIEW (str of variables, space-separated)\n#   Controls default content modules, i.e. what to run when none are specififed\n    : ${XSOS_DEFAULT_VIEW:=\"os\"}\n\n# XSOS_PS_THREADS (bool: y/n)\n#   Controls whether PSCHECK() function parses `ps aux` or `ps auxm` output\n    : ${XSOS_PS_THREADS:=\"n\"}\n\n# XSOS_PS_LEVEL (int: 0-4)\n#   Controls verbosity level (4 being highest) in PSCHECK() function\n    : ${XSOS_PS_LEVEL:=\"1\"}\n\n# XSOS_MULTIPATH_QUERY (string: arbitrary regex)\n#   Only a tenuous case can be made for statically setting this\n#   It's used by the MULTIPATH() function to restrict display to a particular mpath device\n#   Traditionally controled by -q/--wwid option\n    : ${XSOS_MULTIPATH_QUERY:=\"\"}\n\n# XSOS_MEM_UNIT (str: b, k, m, g, t)\n#   Sets unit used by MEMINFO() function for printing\n#   Can also be controlled by cmdline opt -u/--unit\n    : ${XSOS_MEM_UNIT:=\"g\"}\n\n# XSOS_NET_UNIT (str: b, k, m, g, t)\n#   Sets unit used by NETDEV() function for printing Rx & Tx Bytes\n#   Can also be controlled by cmdline opt -u/--unit\n    : ${XSOS_NET_UNIT:=\"m\"}\n\n# XSOS_PS_UNIT (str: k, m, g)\n#   Sets unit used by PSCHECK() function for printing VSZ & RSS\n#   Not affected by cmdline opt -u/--unit option\n    : ${XSOS_PS_UNIT:=\"m\"}\n\n# XSOS_OUTPUT_HANDLER (str: application name)\n#   Sets name of application to handle output\n    : ${XSOS_OUTPUT_HANDLER:=\"cat\"}\n\n# XSOS_OS_RHT_CENTRIC (bool: y/n)\n#   Configures whether OSINFO() focuses on Red Hat support issues\n    : ${XSOS_OS_RHT_CENTRIC:=\"n\"}\n\n# XSOS_IP_VERSION (int: 4/6)\n#   Configures whether IPADDR() shows ipv4 or ipv6 addresses\n    : ${XSOS_IP_VERSION:=\"4\"}\n\n# XSOS_SCRUB_IP_HN (bool: y/n)\n#   Configures whether IP addrs & hostnames should be removed from output\n    : ${XSOS_SCRUB_IP_HN:=\"n\"}\n\n# XSOS_SCRUB_MACADDR (bool: y/n)\n#   Configures whether HW MAC addresses should be removed from output\n    : ${XSOS_SCRUB_MACADDR:=\"n\"}\n\n# XSOS_SCRUB_SERIAL (bool: y/n)\n#   Configures whether serial numbers should be removed from output\n    : ${XSOS_SCRUB_SERIAL:=\"n\"}\n\n# XSOS_SCRUB_PROXYUSERPASS (bool: y/n)\n#   Configures whether RHN/RHSM proxy user/pass should be removed from output\n    : ${XSOS_SCRUB_PROXYUSERPASS:=\"n\"}\n\n# XSOS_ETHTOOL_ERR_REGEX (str: awk-syntax regular expression)\n#   Configures what ETHTOOL() uses to generate the data under the \"Interface Errors\" heading\n    : ${XSOS_ETHTOOL_ERR_REGEX:='/Missing ethtool_-S file|(drop|disc|err|fifo|buf|fail|miss|OOB|fcs|full|frags|hdr|tso|pause|lost|csum).*: [^0]/ && !/(cache_full|csum_(complete|none|partial|unchecked|unnecessary)|fdir_|steer_missed|tso_(bytes|packets)|veb\\.)/'}\n\n# XSOS_LSPCI_NET_REGEX (str: regular expression)\n#   Configures what LSPCI() uses to search for peripherals under the \"Net\" heading\n    : ${XSOS_LSPCI_NET_REGEX:=\"(Ethernet controller|Network controller|InfiniBand)( \\[[0-9]{4}\\])?:\"}\n\n# XSOS_LSPCI_STORAGE_REGEX (str: regular expression)\n#   Configures what LSPCI() uses to search for peripherals under the \"Storage\" heading\n    : ${XSOS_LSPCI_STORAGE_REGEX:=\"(Fibre Channel|RAID bus controller|Mass storage controller|SCSI storage controller|SATA controller|Serial Attached SCSI controller)( \\[[0-9]{4}\\])?:\"}\n\n# XSOS_SS_CHECK_FIELDS (str: pipe separated field names)\n#   Configures what SSCHECK() uses to filter fields whose value is > 0.\n    : ${XSOS_SS_CHECK_FIELDS:=\"sock_drop|app_limited|dsack_dups|lost|reord_seen|back_log|retrans_total|rq|tq\"}\n\n# XSOS_NETSTAT_FILTER_REGEX (str: bash-syntax regular expression)\n#   Configures what NETSTAT() keys will be printed if their value is > 0 \n    : ${XSOS_NETSTAT_FILTER_REGEX:=\"drop|err|reset|rst|delay|bad|fail|pause|time|miss|loss|listen|PAWS\"}\n\n# XSOS_NETSTAT_HIGHLIGHT_REGEX (str: bash-syntax regular expression)\n#   Configures what NETSTAT() keys will be highlighted.\n    #: ${XSOS_NETSTAT_HIGHLIGHT_REGEX:=\"drop|err|reset|rst|delay|bad|fail|pause|time|miss|loss\"}\n    : ${XSOS_NETSTAT_HIGHLIGHT_REGEX:=\"\"}\n\n# XSOS_NETSTAT_IGNORE_ZERO (bool: y/n)\n#   Configures whether or not NETSTAT() will ignore fields whose value is 0\n    : ${XSOS_NETSTAT_IGNORE_ZERO:=\"y\"}\n\n# ==============================================================================\n\n\nVERSINFO() {\n  echo \"Version info: ${version:2}\nSee <github.com/ryran/xsos> to report bugs or suggestions\"\n  exit\n}\n\nHELP_USAGE() {\n  echo \"Usage: xsos [DISPLAY OPTIONS] [-6abokcfmdtlerngispSFIN] [SOSREPORT ROOT]\n  or:  xsos [DISPLAY OPTIONS] {--B|--C|--F|--M|--D|--T|--L|--R|--N|--G|--I|--P FILE}...\n  or:  xsos [-?|-h|--help]\n\nDisplay system info from localhost or extracted sosreport\"\n}\n\nHELP_OPTS_CONTENT() {\n  echo \"\nContent options:\"\n  echo \"\n -a, --all❚show everything\n -b, --bios❚show info from dmidecode\n -o, --os❚show hostname, distro, SELinux, kernel info, uptime, etc\n -k, --kdump❚inspect kdump configuration\n -c, --cpu❚show info from /proc/cpuinfo\n -f, --intrupt❚show info from /proc/interrupts\n -m, --mem❚show info from /proc/meminfo\n -d, --disks❚show info from /proc/partitions, dm-multipath, lsblk, df\n -t, --mpath❚show info from dm-multipath\n -l, --lspci❚show info from lspci\n -e, --ethtool❚show info from ethtool\n -r, --softirq❚show info from /proc/net/softnet_stat\n -n, --netdev❚show info from /proc/net/dev\n -g, --bonding❚show bonding and teaming info\n -i, --ip❚show info from ip addr (BASH v4+ required)\n     --net❚alias for: --lspci --ethtool --softirq --netdev --bonding --ip\n -s, --sysctl❚show important kernel sysctls\n -p, --ps❚inspect running processes via ps\n -S, --ss❚inspect running processes via ss\n -F, --firewall❚show firewall status\n -I, --ifcfg❚show ifcfg files summary\n -N, --netstat❚show info from /proc/net/netstat\" | column -ts❚\n}\n\nHELP_OPTS_DISPLAY() {\n  echo \"\nDisplay options:\"\n# --rhsupport❚tweak os output to focus on RHEL-centric support issues\n  echo \"\n     --scrub❚remove from output: IP/MAC addrs, hostnames, serial numbers,\n            ❚proxy user & passwords\n -6, --ipv6❚parse ip addr output for IPv6 addresses instead of IPv4\n -q, --wwid=ID❚restrict dm-multipath output to a particular mpath device,\n              ❚where ID is a wwid, friendly name, or LUN identifier\n -u, --unit=P❚change byte display for /proc/meminfo & /proc/net/dev,\n             ❚where P is \\\"b\\\" for byte, or else \\\"k\\\", \\\"m\\\", \\\"g\\\", or \\\"t\\\"\n     --threads❚make ps take threads into account (via \\`ps auxm\\`)\n -v, --verbose=NUM❚specify ps verbosity level (0-4, default: 1)\n -w, --width=NUM❚change fold-width, in columns (positive number, e.g., 80)\n                ❚\\\"0\\\" disables wrapping, \\\"w\\\" autodetects width (default)\n -x, --nocolor❚disable output colorization\n -y, --less❚send output to \\`less -SR\\`\n -z, --more❚send output to \\`more\\`\" | column -ts❚\n}\n\nHELP_OPTS_SPECIAL() {\n  echo \"\nSpecial options (BASH v4+ required):\"\n  echo \"\n --B=FILE❚read from FILE containing \\`dmidecode\\` dump\n --C=FILE❚read from FILE containing /proc/cpuinfo dump\n --F=FILE❚read from FILE containing /proc/interrupts dump\n --M=FILE❚read from FILE containing /proc/meminfo dump\n --D=FILE❚read from FILE containing /proc/partitions dump\n --T=FILE❚read from FILE containing \\`multipath -v4 -ll\\` dump\n --L=FILE❚read from FILE containing \\`lspci\\` dump\n --R=FILE❚read from FILE containing /proc/net/softnet_stat dump\n --N=FILE❚read from FILE containing /proc/net/dev dump\n --G=FILE❚read from FILE containing /proc/net/bonding/xxx dump\n --I=FILE❚read from FILE containing \\`ip addr\\` dump\n --P=FILE❚read from FILE containing \\`ps aux\\` dump\n --S=FILE❚read from FILE containing \\`ss -peaonmi\\` dump\n --F=FILE❚read from FILE containing \\`systemctl_status_--all\\` dump\" | column -ts❚\n}\n\nHELP_SHORT() {\n  HELP_USAGE\n  HELP_OPTS_CONTENT\n  HELP_OPTS_DISPLAY\n  HELP_OPTS_SPECIAL\n  echo -e \"\\nRun with \\\"--help\\\" to see full help page\\n\"\n  VERSINFO\n}\n\nHELP_EXTENDED() {\n  HELP_USAGE\n  echo \"Run with \\\"-h\\\" to see simplified help page\"\n  HELP_OPTS_CONTENT\n  HELP_OPTS_DISPLAY\n  echo \"\nIf no content options are specified, xsos parses the environment variable\nXSOS_DEFAULT_VIEW to figure out what information to display. If this variable\nis unset at runtime, it is initialized internally as follows:\n\n   XSOS_DEFAULT_VIEW='os'\n\nTweak it to preference by adding additional space-separated MODULE statements,\nwhere MODULE is the same as the long option (e.g. mem, ethtool, netdev). Note\nthat the --net alias option cannot be used for this purpose. Also note that the\n-a / --all option has it's own environment variable: XSOS_ALL_VIEW\n\nIf SOSREPORT ROOT isn't provided, the data will be gathered from the localhost;\nhowever, bios, multipath, and ethtool output will only be displayed if running\nas root (UID 0). When executing in this manner as non-root, those modules will\nbe skipped, and a warning printed to stderr.\n\nSometimes a full sosreport isn't available; sometimes you simply have a\ndmidecode-dump or the contents of /proc/meminfo and you'd like a summary...\"\n  HELP_OPTS_SPECIAL\n  echo \"\nAs is hopefully clear, each of these options requires a filename as an\nargument. These options can be used together, but cannot be used in concert\nwith regular \\\"Content options\\\" -- Content opts are ignored if Special options\nare detected. Also note: the \\\"=\\\" can be replaced with a space if desired.\n\nRe BASH v4+:\n BASH associative arrays are used for various things. In short, if running\n xsos on earlier BASH versions (e.g. RHEL5), you get ...\n  * No output colorization\n  * No -i/--ip\n  * No parsing of \\\"Special options\\\"\n\nEnvironment variables:\n For details of all configurable env variables, view first page of xsos\n source. There are vars to change default colors as well as other settings.\n Each variable name is prefixed with \\\"XSOS_\\\" and the important ones follow.\n  COLORS  FOLD_WIDTH  ALL_VIEW  DEFAULT_VIEW  HEADING_SEPARATOR  IP_VERSION\n  MEM_UNIT  NET_UNIT  PS_UNIT  PS_LEVEL  PS_THREADS  OUTPUT_HANDLER\n  SCRUB_IP_HN  SCRUB_MACADDR  ETHTOOL_ERR_REGEX\n\"\n  VERSINFO\n}\n\nWARN_NO_UPDATE() {\n  echo \"Warning: v0.6.0 dropped the built-in update feature triggered by -U/--update\"\n  echo \"Future v1.x versions might repurpose the -U option\"\n  echo \"See https://github.com/ryran/xsos/issues/155 for more info\"\n  exit 64\n}\n\n# Help? Version?\ncase $1 in\n  -V|--vers|--version)  echo \"Version info: ${version:2}\"; exit ;;\n  -\\?|-h)               HELP_SHORT ;;\n  --help|help)          HELP_EXTENDED ;;\n  -U|--update)          WARN_NO_UPDATE >&2 ;;\nesac\n\n# GNU getopt short and long options:\nsopts='6q:u:v:w:xyzabokcfmdtlerngispSFIN'\nlopts='scrub,ipv6,rhsupport,wwid:,unit:,threads,verbose:,width:,nocolor,less,more,all,bios,os,kdump,cpu,intrupt,mem,disks,mpath,lspci,ethtool,softirq,netdev,bonding,ip,net,sysctl,ps,ss,firewall,ifcfg,netstat,B:,C:,F:,M:,D:,T:,L:,R:,N:,G:,I:,P:'\n\n# Check for bad switches\ngetopt -Q --name=xsos -o $sopts -l $lopts -- \"$@\" || { HELP_USAGE; exit 64; }\n\n# Setup assoc array for single-file options\nunset sfile\n[[ $BASH_VERSINFO -ge 4 ]] && declare -A sfile\n\n# Checker for cmdline options\n_OPT_CHECK() {\n  local option chosen_opt check_type valid_opts n s\n  option=$1\n  chosen_opt=$(tr '[:upper:]' '[:lower:]' <<<\"$2\")\n  check_type=$3\n  valid_opts=$4\n  if [[ $check_type == regex ]]; then\n    grep -E -qs \"$valid_opts\" <<<\"$chosen_opt\" && return\n    case $option in\n      width)\n        echo \"xsos: option '$option' expects a positive number or 'w' (auto-detect width) or '0' (disable wrapping)\"\n        ;;\n      *)\n       echo \"xsos: option '$option' expects other input, i.e., matching regex '$valid_opts'\"=\n    esac\n  \n  elif [[ $check_type == range ]]; then\n    for n in $(seq $valid_opts); do\n      [[ $n == $chosen_opt ]] && return\n    done\n    echo \"xsos: option '$option' expects number from range: { ${valid_opts// /-} }\"\n    \n  elif [[ $check_type == naturalnumber ]]; then\n    grep -E -qs '^[0-9]+$' <<<\"$chosen_opt\" && return\n    echo \"xsos: option '$option' expects any natural number, including zero\"\n    \n  elif [[ $check_type == string ]]; then\n    for s in $valid_opts; do\n      [[ $s == $chosen_opt ]] && return\n    done\n    echo \"xsos: option '$option' expects one of: { $valid_opts } \"\n  \n  elif [[ $check_type == anystring ]]; then\n    [[ -n $2 ]] && return\n    echo \"xsos: option '$option' expects a non-null string value\"\n  fi\n  \n  exit 64\n}\n\n\n# Parse command-line arguments\nPARSE() {\n  unset opts all bios os kdump cpu intrupt mem disks mpath lspci ethtool softirq netdev bonding ip net sysctl ps\n  until [[ $1 == -- ]]; do\n    case $1 in\n      --scrub)      XSOS_SCRUB_IP_HN=y XSOS_SCRUB_MACADDR=y XSOS_SCRUB_SERIAL=y XSOS_SCRUB_PROXYUSERPASS=y ;;\n      -6|--ipv6)    XSOS_IP_VERSION=6 ;;\n      -q|--wwid)    _OPT_CHECK \"wwid\" \"$2\" anystring\n                      XSOS_MULTIPATH_QUERY=$2; shift\n                    ;;\n      -u|--unit)    _OPT_CHECK \"unit\" \"$2\" string \"b k m g t\"\n                      XSOS_MEM_UNIT=$2; XSOS_NET_UNIT=$2; shift\n                    ;;\n      --threads)    XSOS_PS_THREADS=y ;;\n      -v|--verbose) _OPT_CHECK \"verbose\" \"$2\" range \"0 4\"\n                      XSOS_PS_LEVEL=$2; shift\n                    ;;\n      -w|--width)   _OPT_CHECK \"width\" \"$2\" regex '^[0-9]*$|^w$'\n                      XSOS_FOLD_WIDTH=$2; shift\n                    ;;\n      -x|--nocolor) XSOS_COLORS=n     ;;\n      -y|--less)    XSOS_OUTPUT_HANDLER='less -SR' ;;\n      -z|--more)    XSOS_OUTPUT_HANDLER='more'     ;;\n      --rhsupport)  XSOS_OS_RHT_CENTRIC=y          ;;\n      -a|--all)     opts=y all=y     ;;\n      -b|--bios)    opts=y bios=y    ;;\n      -o|--os)      opts=y os=y      ;;\n      -k|--kdump)   opts=y kdump=y   ;;\n      -c|--cpu)     opts=y cpu=y     ;;\n      -f|--intrupt) opts=y intrupt=y ;;\n      -m|--mem)     opts=y mem=y     ;;\n      -d|--disks)   opts=y disks=y   ;;\n      -t|--mpath)   opts=y mpath=y   ;;\n      -l|--lspci)   opts=y lspci=y   ;;\n      -e|--ethtool) opts=y ethtool=y ;;\n      -r|--softirq) opts=y softirq=y ;;\n      -n|--netdev)  opts=y netdev=y  ;;\n      -g|--bonding) opts=y bonding=y teaming=y ;;\n      -i|--ip)      opts=y ip=y      ;;\n      -s|--sysctl)  opts=y sysctl=y  ;;\n      -p|--ps)      opts=y ps=y      ;;\n      -S|--ss)      opts=y ss=y      ;;\n      -F|--firewall)opts=y firewall=y ;;\n      -I|--ifcfg)   opts=y ifcfg=y   ;;\n      -N|--netstat) opts=y netstat=y ;;\n      --net)        opts=y lspci=y ethtool=y softirq=y netdev=y ip=y firewall=y bonding=y teaming=y ss=y ifcfg=y netstat=y ;;\n      \n      --B)  sfile[B]=$2; shift ;;\n      --F)  sfile[F]=$2; shift ;;\n      --C)  sfile[C]=$2; shift ;;\n      --M)  sfile[M]=$2; shift ;;\n      --D)  sfile[D]=$2; shift ;;\n      --T)  sfile[T]=$2; shift ;;\n      --L)  sfile[L]=$2; shift ;;\n      --R)  sfile[R]=$2; shift ;;\n      --N)  sfile[N]=$2; shift ;;\n      --G)  sfile[G]=$2; shift ;;\n      --I)  sfile[I]=$2; shift ;;\n      --P)  sfile[P]=$2; shift ;;\n      --S)  sfile[S]=$2; shift ;;\n    esac\n    shift\n  done\n  shift #(to get rid of the '--')\n  # Set sosroot\n  sosroot=\"$@\"\n}\n\n# Call the parser\nPARSE $(getopt -u --name=xsos -o $sopts -l $lopts -- \"$@\")\n\n# If any special option was used appropriately with a file, do that instead of other opts\nif [[ $BASH_VERSINFO -ge 4 && -n ${sfile[*]} ]]; then\n  :\n# If BASH is not v4+ and special options were used, fail\nelif [[ $BASH_VERSINFO -lt 4 && -n $sfile ]]; then\n  echo \"Special options require use of BASH associative arrays\" >&2\n  echo \"i.e., BASH v4.0 or higher (RHEL6/Fedora11 and above)\" >&2\n  exit 32\n# Use default view if no content options specified\nelif [[ -z $opts ]]; then\n  for module in $XSOS_DEFAULT_VIEW; do eval $module=y; done\n# Else, if \"all\" option specified, set full view\nelif [[ -n $all ]]; then\n  for module in $XSOS_ALL_VIEW; do eval $module=y; done\nfi\n\n# If color should be enabled, taste the rainbow\nif [[ $XSOS_COLORS == y && $BASH_VERSINFO -ge 4 ]]; then\n  c[0]=${c[$XSOS_COLOR_RESET]}\n  c[H1]=${c[$XSOS_COLOR_H1]}\n  c[H2]=${c[$XSOS_COLOR_H2]}\n  c[H3]=${c[$XSOS_COLOR_H3]}\n  c[H4]=${c[$XSOS_COLOR_H4]}\n  c[Imp]=${c[$XSOS_COLOR_IMPORTANT]}\n  c[Warn1]=${c[$XSOS_COLOR_WARN1]}\n  c[Warn2]=${c[$XSOS_COLOR_WARN2]}\n  c[Up]=${c[$XSOS_COLOR_IFUP]}\n  c[Down]=${c[$XSOS_COLOR_IFDOWN]}\n  c[MemUsed]=${c[$XSOS_COLOR_MEMGRAPH_MEMUSED]}\n  c[HugePages]=${c[$XSOS_COLOR_MEMGRAPH_HUGEPAGES]}\n  c[Buffers]=${c[$XSOS_COLOR_MEMGRAPH_BUFFERS]}\n  c[Cached]=${c[$XSOS_COLOR_MEMGRAPH_CACHED]}\n  c[Dirty]=${c[$XSOS_COLOR_MEMGRAPH_DIRTY]}\nelse\n  unset c\nfi\n\n# Properly setup fold setting\nif [[ $XSOS_FOLD_WIDTH == w ]]; then\n  if tty &>/dev/null; then\n    XSOS_FOLD_WIDTH=$(( $(tput cols) - 8 ))\n  else\n    XSOS_FOLD_WIDTH=80\n  fi\nelif [[ $XSOS_FOLD_WIDTH == 0 ]]; then\n  XSOS_FOLD_WIDTH=99999\nfi\n\n\n\n# ON TO THE CONTENT MODULE FUNCTIONS!\n# -----------------------------------\n# ===================================\n\nDMIDECODE() {\n  # Local vars:\n  local dmidecode_input\n  \n  if [[ -z $1 ]]; then\n    dmidecode_input=$(dmidecode 2>/dev/null)\n  elif [[ -f $1 ]]; then\n    dmidecode_input=$(<\"$1\")\n  elif [[ -r $1/dmidecode ]]; then\n    dmidecode_input=$(<\"$1/dmidecode\")\n  elif [[ -r $1/sos_commands/kernel.dmidecode ]]; then\n    dmidecode_input=$(<\"$1/sos_commands/kernel.dmidecode\")\n  elif [[ -r $1/sos_commands/hardware/dmidecode ]]; then\n    dmidecode_input=$(<\"$1/sos_commands/hardware/dmidecode\")\n  fi\n  \n  # If bad dmidecode input, return\n  if head -n3 <<<\"$dmidecode_input\" | grep -E -qs 'No such file or directory|No SMBIOS nor DMI entry point found'; then\n    echo -e \"${c[Warn2]}Warning:${c[Warn1]} dmidecode input invalid; skipping bios check${c[0]}\" >&2\n    echo -en $XSOS_HEADING_SEPARATOR >&2\n    return 1\n  fi\n  \n  if [[ $XSOS_SCRUB_SERIAL == y ]]; then\n      dmidecode_input=$(\n        gawk -F: '\n          BEGIN { OFS = \":\" }\n          /^\\s+(UUID|Serial Number):/ {\n            gsub(/[^- ]/, \"⣿\", $2)\n          }\n          {print}\n        ' <<<\"$dmidecode_input\")\n  fi\n  \n  echo -e \"${c[H1]}DMIDECODE${c[0]}\"\n  \n  # Prints \"<BIOS Vendor>, <BIOS Version>, <BIOS Release Date>\"\n  echo -e \"${c[H2]}  BIOS:${c[0]}\"\n  gawk 'BEGIN { RS=\"\\nHandle\" } /BIOS Information/' <<<\"$dmidecode_input\" |\n    gawk -F: -vH3=\"${c[H3]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '\n      /Vendor:/            { Vendor  = $2; gsub(/  */, \" \", Vendor) }\n      /Version:/           { Version = $2; gsub(/  */, \" \", Version) }\n      /Release Date:/      { RelDate = $2; gsub(/  */, \" \", RelDate) }\n      /BIOS Revision:/     { BiosRev = $2; gsub(/  */, \" \", BiosRev) }\n      /Firmware Revision:/ { FirmRev = $2; gsub(/  */, \" \", FirmRev) }\n      END {\n        printf \"    %sVend:%s%s\\n\", H3, H0, Vendor\n        printf \"    %sVers:%s%s\\n\", H3, H0, Version\n        printf \"    %sDate:%s%s\\n\", H3, H0, RelDate\n        printf \"    %sBIOS Rev:%s%s\\n\", H3, H0, BiosRev\n        printf \"    %sFW Rev:%s  %s\\n\", H3, H0, FirmRev\n      }\n    '\n  # Prints <SYSTEM Manufacturer>, <SYSTEM Product Name>, <SYSTEM Version>, <SYSTEM Serial Number>, <SYSTEM UUID>\n  echo -e \"${c[H2]}  System:${c[0]}\"\n  gawk 'BEGIN { RS=\"\\nHandle\" } /System Information/' <<<\"$dmidecode_input\" |\n    gawk -F: -vH3=\"${c[H3]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '\n      /Manufacturer:/ { Mfr     = $2; gsub(/  */, \" \", Mfr) }\n      /Product Name:/ { Product = $2; gsub(/  */, \" \", Product) }\n      /Version:/      { Version = $2; gsub(/  */, \" \", Version) }\n      /Serial Number:/{ Serial  = $2 }\n      /UUID:/         { UUID    = $2 }\n      END {\n        printf \"    %sMfr:%s %s\\n\", H3, H0, Mfr\n        printf \"    %sProd:%s%s\\n\", H3, H0, Product\n        printf \"    %sVers:%s%s\\n\", H3, H0, Version\n        printf \"    %sSer:%s %s\\n\", H3, H0, Serial\n        printf \"    %sUUID:%s%s\\n\", H3, H0, UUID\n      }\n    '\n  # Prints <CPU Manufacturer>, <CPU Family>, <CPU Current Speed>, <CPU Version>\n  # Prints \"<N> of <N> CPU sockets populated, <N> cores/<N> threads per CPU\"\n  # Prints \"<N> total cores, <N> total threads\"\n  echo -e \"${c[H2]}  CPU:${c[0]}\"\n  gawk 'BEGIN { RS=\"\\nHandle\" } /Processor Information/' <<<\"$dmidecode_input\" |\n    gawk -F: -vH3=\"${c[H3]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '\n      /Status:/       { SumSockets ++; if ($2 ~ /Populated/) PopulatedSockets ++ }\n      /Core Count:/   { SumCores   += $2; CoresPerCpu = $2 }\n      /Thread Count:/ { SumThreads += $2; ThreadsPerCpu = $2 }\n      /Manufacturer:/ { if ($2 ~ /^ *$/)         next; Mfr      = $2; gsub(/  */, \" \", Mfr) }\n      /Family:/       { if ($2 ~ /^ *$|Other/)   next; Family   = $2; gsub(/  */, \" \", Family) }\n      /Current Speed:/{ if ($2 ~ /^ *$|Unknown/) next; CpuFreq  = $2; gsub(/  */, \" \", CpuFreq) }\n      /Version:/      { if ($2 ~ /^ *$/)         next; Version  = $2; gsub(/  */, \" \", Version) }\n      END {\n        printf \"    %s%d of %d CPU sockets populated, %d cores/%d threads per CPU\\n\",\n          H_IMP, PopulatedSockets, SumSockets, CoresPerCpu, ThreadsPerCpu\n        printf \"    %d total cores, %d total threads\\n\", SumCores, SumThreads, H0\n        printf \"    %sMfr:%s %s\\n\", H3, H0, Mfr\n        printf \"    %sFam:%s %s\\n\", H3, H0, Family\n        printf \"    %sFreq:%s%s\\n\", H3, H0, CpuFreq\n        printf \"    %sVers:%s%s\\n\", H3, H0, Version\n      }\n    '\n  # Prints \"<N> MB (<N> GB) total\"\n  # Prints \"<N> of <N> DIMMs populated (max capacity <N>)\"\n  echo -e \"${c[H2]}  Memory:${c[0]}\"\n  gawk 'BEGIN { RS=\"\\nHandle\" } /Physical Memory Array|Memory Device/' <<<\"$dmidecode_input\" |\n    gawk -vH3=\"${c[H3]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '\n      /Size:/ {\n        NumDimmSlots ++\n        if ($2 ~ /^[0-9]/) {\n          NumDimms ++\n          if ($3 ~ /^P/)\n            SumRam += $2 * 1024 * 1024 * 1024\n          else if ($3 ~ /^T/)\n            SumRam += $2 * 1024 * 1024\n          else if ($3 ~ /^G/)\n            SumRam += $2 * 1024\n          else if ($3 ~/^[kK]/)\n            SumRam += $2 / 1024\n          else if ($3 ~/^[bB]/)\n            SumRam += $2 / 1024 / 1024\n          else\n            SumRam += $2\n        }\n      }\n      /Maximum Capacity:/ {\n        if ($3 ~ /^[0-9]/) {\n          if ($4 ~ /^P/)\n            SumMaxRam += $3 * 1024 * 1024 * 1024\n          else if ($4 ~ /^T/)\n            SumMaxRam += $3 * 1024 * 1024\n          else if ($4 ~ /^G/)\n            SumMaxRam += $3 * 1024\n          else if ($4 ~/^[kK]/)\n            SumMaxRam += $3 / 1024\n          else if ($4 ~/^[bB]/)\n            SumMaxRam += $3 / 1024 / 1024\n          else\n            SumMaxRam += $3\n        }\n      }\n      END {\n        printf \"    %sTotal:%s %d MiB (%.0f GiB)\\n\", H3, H0, SumRam, SumRam/1024\n        printf \"    %sDIMMs:%s %d of %d populated\\n\", H3, H0, NumDimms, NumDimmSlots\n        printf \"    %sMaxCapacity:%s %d MiB (%.0f GiB / %.2f TiB)\\n\", H3, H0, SumMaxRam, SumMaxRam/1024, SumMaxRam/1024/1024\n      }\n    '\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\n_CHECK_DISTRO() {\n  # Local vars:\n  local OS_INDENT files file\n  \n  OS_INDENT=\"            \"\n  # Parse redhat-release if we have it\n  if [[ ! -r $1/etc/redhat-release ]]; then\n    distro_release=\"${c[Imp]}[redhat-release]${c[0]} ${c[RED]}(missing)${c[0]}\"\n    \n  else\n    # If release is RHEL 4,5,6,7,8 in standard expected format ...\n    if grep -E -e 'Red Hat Enterprise Linux (AS|ES|Desktop|WS) release 4 \\((Nahant|Nahant Update [1-9])\\)' \\\n             -e 'Red Hat Enterprise Linux (Client|Server) release 5\\.?[0-9]* \\(Tikanga\\)' \\\n             -e 'Red Hat Enterprise Linux (Client|Workstation|Server) release 6\\.?[0-9]* \\(Santiago\\)' \\\n             -e 'Red Hat Enterprise Linux (Client|Workstation|Server) release 7\\.[0-9] \\(Maipo\\)' \\\n             -e 'Red Hat Enterprise Linux release 8\\.[0-9] \\(Ootpa\\)' \\\n             -qs \"$1/etc/redhat-release\"; then\n    \n      # ... And if redhat-release file has more than 1 line ...\n      [[ $(wc -l <\"$1/etc/redhat-release\") -gt 1 ]] &&\n      \n        # ... Then print it in orange\n        distro_release=${c[ORANGE]}$(sed \"1!s/^/$OS_INDENT/\" <\"$1/etc/redhat-release\") ||\n        \n          # Otherwise, if only 1 line, all is well -- print it normally\n          distro_release=$(sed \"1!s/^/$OS_INDENT/\" <\"$1/etc/redhat-release\")\n          \n    # If release is not RHEL 4,5,6,7 in standard expected format, freak out\n    else\n      distro_release=$(sed \"1!s/^/$OS_INDENT/\" \"$1/etc/redhat-release\" 2>/dev/null)\n      \n      if grep -qi fedora <<<\"$distro_release\"; then\n        distro_release=${c[bg_BLUE]}$distro_release\n      \n      elif grep -E -qi 'alpha|beta' <<<\"$distro_release\"; then\n        distro_release=${c[bg_RED]}${c[ORANGE]}$distro_release\n        \n      else\n        distro_release=${c[bg_DGREY]}${c[RED]}$distro_release\n      fi\n    fi\n    # Prepend the distro information with \"[redhat-release] \" and do a little color fun\n    distro_release=\"${c[Imp]}[redhat-release]${c[0]} $distro_release${c[0]}\"\n  fi\n\n  # Check for any /etc/*-release or /etc/*_version files and add their content to the distro_release variable\n  files=$(ls \"$1\"/etc/*{-release,_version} 2>/dev/null | grep -E -sv '/etc/(os|redhat|system|lsb)-release')\n  if [[ -n $files ]]; then\n    for file in $files; do\n      if [[ -r $file ]]; then\n        distro_release=\"$distro_release\\n$OS_INDENT${c[Imp]}[${file##*/}]${c[0]} $(sed \"1!s/^/$OS_INDENT/\" <\"$file\")\"\n      elif [[ -L $file ]]; then\n        distro_release=\"$distro_release\\n$OS_INDENT${c[Imp]}[${file##*/}]${c[0]} ${c[RED]}(error: broken link)${c[0]}\"\n      else\n        distro_release=\"$distro_release\\n$OS_INDENT${c[Imp]}[${file##*/}]${c[0]} ${c[RED]}(error: file exists, but cannot read it)${c[0]}\"\n      fi\n    done\n  fi\n  \n  # I don't like blindly sourcing a file -- that provides a vector to screw with this script...\n  # But in modern Linux boxen this file is standard\n  # If able to source the new standard /etc/os-release, list it out\n  if source \"$1/etc/os-release\" 2>/dev/null; then\n    distro_release=\"$distro_release\\n$OS_INDENT${c[Imp]}[os-release]${c[0]} $PRETTY_NAME $VERSION\"\n  fi\n}\n\n\n_CHECK_KERNELBUILD() {\n  # Get kernel build version somehow or another, making sure not to use build offered by rescue mode kernel\n  \n  # if localhost: get it from the best place, yay\n  if [[ $1 == / ]]; then\n    kernel_build=$(</proc/version)\n  \n  # sosreport: sosreports don't normally contain this.. yet\n  elif [[ -r \"$1/proc/version\" ]] && ! grep -qsw rescue \"$1/proc/cmdline\"; then\n    kernel_build=$(<\"$1/proc/version\")\n  \n  # sosreport: if find it via `dmesg` output file, great\n  elif ! grep -qsw rescue \"$1/proc/cmdline\" && kernel_build=$(cat \"$1/sos_commands/general/dmesg\" \"$1/sos_commands/kernel/dmesg\" 2>/dev/null | grep -as 'Linux version'); then\n    :\n    \n  # sosreport: if find it in var/log/dmesg, woo hoo\n  elif grep -qs 'Linux version' \"$1/var/log/dmesg\"; then\n    kernel_build=$(grep -a 'Linux version' \"$1/var/log/dmesg\" | tail -n1)\n  \n  # sosreport: if find it in var/log/messages, lovely\n  elif grep -qs 'kernel: Linux version' \"$1/var/log/messages\"; then\n    kernel_build=$(grep 'kernel: Linux version' \"$1/var/log/messages\" | tail -n1)\n  \n  # sosreport: final option: search in all old messages files -- this might be a bad idea\n  else\n    # To explain this last one: The goal is to find the most recent instance of \"Linux version\"\n    # So this reverse-sorts by filename, searches through all files ending with the most recent file\n    # This is obviously not very efficient, but it's the only way I've thought of to do it so far\n    kernel_build=$(find \"$1/var/log\" -name 'messages?*' 2>/dev/null | sort -r | xargs zgrep -sh 'kernel: Linux version' 2>/dev/null | tail -n1)\n  fi\n  \n  # Fix format if necessary\n  if [[ -n $kernel_build ]]; then\n    kernel_build=$(sed -e 's,^\\[.*\\] Linux,Linux,' -e 's,^.*kernel: Linux,Linux,' <<<\"$kernel_build\")\n    kernel_buildhost=$(gawk '{print $4}' <<<\"$kernel_build\")\n  fi\n}\n\n\n_CHECK_SELINUX() {\n  # Local vars:\n  local input_sestatus have_dmesg input_seconfig selinux enforcing selinux_dmesg sestatus_status sestatus_mode sestatus_cfgmode sestatus_policy seconfig_cfgmode seconfig_policy\n  \n  __cond_print_cfgmode() {\n    [[ -n $seconfig_cfgmode ]] &&\n      printf \"  (default $seconfig_cfgmode)\" || printf \"  (default unknown)\"\n  }\n  \n  # Grab input from sestatus command if localhost\n  if [[ $1 == / ]]; then\n    input_sestatus=$(sestatus 2>/dev/null)\n    \n  # Else, from $sosroot/sestatus or $sosroot/sos_commands/selinux/sestatus_-b & dmesg\n  else\n    input_sestatus=$(gawk '!/\\/.*bin/ && NF!=0' \"$1/sestatus\" 2>/dev/null; gawk '!/\\/.*bin/ && NF!=0' \"$1/sos_commands/selinux/sestatus_-b\" 2>/dev/null)\n    cat \"$1\"/var/log/dmesg \"$1\"/sos_commands/general/dmesg* \"$1\"/sos_commands/kernel/dmesg 2>/dev/null | grep -E -qis '^SELinux: *Disabled at (boot|runtime)' && selinux_dmesg=disabled\n    # Could also check /var/log/messages, but it would be too expensive and complicated\n    # to ensure any hits were for the current boot-cycle\n  fi\n  \n  # Read in /etc/selinux/config from sosroot or localhost\n  input_seconfig=$(cat \"$1\"/etc/selinux/config 2>/dev/null)\n  \n  # Set \"selinux\" and \"enforcing\" variables per kernel args\n  eval $(grep -E -ios 'selinux=.|enforcing=.' \"$1\"/proc/cmdline | tr '[:upper:]' '[:lower:]')\n  \n  # Check /etc/selinux/config input\n  if [[ -n $input_seconfig ]]; then\n    eval $(gawk -F= '\n      /^SELINUX=/     { cfgmode = $2 }\n      /^SELINUXTYPE=/ { policy  = $2 }\n      END {\n        printf \"seconfig_cfgmode=%s; seconfig_policy=%s\", cfgmode, policy\n      }\n    ' <<<\"$input_seconfig\")\n  fi\n  \n  # Check sestatus input\n  if [[ -n $input_sestatus ]]; then\n    eval $(gawk '\n      /SELinux status/                    { status  = $NF }\n      /Current mode/                      { mode    = $NF }\n      /Mode from config file/             { cfgmode = $NF }\n      /Loaded policy|Policy from config/  { policy  = $NF }\n      END {\n        printf \"sestatus_status=%s; sestatus_mode=%s; sestatus_cfgmode=%s; sestatus_policy=%s\",\n          status, mode, cfgmode, policy\n      }\n    ' <<<\"$input_sestatus\")\n    \n    # Since we have sestatus input, primarily rely on that\n    if [[ $sestatus_status == disabled ]]; then\n      # If sestatus says disabled, need to rely on config file for default mode\n      printf \"disabled\"; __cond_print_cfgmode\n    else\n      # Otherwise, just use sestatus output\n      printf \"$sestatus_mode  (default $sestatus_cfgmode)\"\n    fi\n  \n  # If we don't have sestatus input, things are more complicated...\n  else\n  \n    # If we have selinux/enforcing kernel args, use those for current status\n    if [[ -n $selinux || -n $enforcing ]]; then\n      case $selinux in\n        0)  printf \"disabled\"   ;;\n        1)  printf \"enforcing\"  ;;\n      esac\n      case $enforcing in\n        0)  printf \"permissive\" ;;\n        1)  printf \"enforcing\"  ;;\n      esac\n      __cond_print_cfgmode\n      \n    # If dmesg from sosreport says disabled, print it out\n    elif [[ $selinux_dmesg == disabled ]]; then\n      printf \"dmesg says disabled\"; __cond_print_cfgmode\n      \n    # If we only have stuff from /etc/selinux/config\n    elif [[ -n $seconfig_cfgmode ]]; then\n      printf \"${c[Warn1]}status unknown${c[0]} (default $seconfig_cfgmode)\"\n    \n    # Otherwise, we have no clue ... :(\n    else\n      printf \"${c[Warn1]}status unknown (default unknown)${c[0]}\"\n    fi\n  fi\n}\n\n\n_CHECK_GRUB() {\n  # Local vars:\n  local grubcfg default\n  \n  # Other vars that we want to be global, so no local here and no local in modules that call them:\n  ## bad_grubcfg default_missing grub_kernel grub_cmdline\n  \n  # Find the grub config file\n  if [[ -f $1/boot/grub/grub.conf ]]; then\n    # Set grubcfg for grub1\n    grubcfg=$1/boot/grub/grub.conf\n  elif [[ -f $1/boot/efi/EFI/redhat/grub.conf ]]; then\n    # Set grubcfg for rhel UEFI grub1\n    grubcfg=$1/boot/efi/EFI/redhat/grub.conf\n  elif [[ -f $1/boot/grub2/grub.cfg ]]; then\n    # Set grubcfg for rhel grub2\n    grubcfg=$1/boot/grub2/grub.cfg\n  elif [[ -f $1/boot/efi/EFI/redhat/grub.cfg ]]; then\n    # Set grubcfg for rhel UEFI grub2\n    grubcfg=$1/boot/efi/EFI/redhat/grub.cfg\n  elif [[ -f $1/boot/grub/grub.cfg ]]; then\n    # Set grubcfg for debian grub2\n    grubcfg=$1/boot/grub/grub.cfg\n  else\n    # Else, we have nothing\n    bad_grubcfg=\"${c[Warn1]}unknown  (no grub config file)${c[0]}\"\n    return 1\n  fi\n  \n  # Check for read permission\n  if [[ ! -r $grubcfg ]]; then\n    # Set a message for later and stop here\n    bad_grubcfg=\"${c[Warn1]}unknown (no read permission on ${grubcfg##*/})${c[0]}\"\n    return 1\n  fi\n  \n  case \"${grubcfg##*/}\" in\n    grub.conf)\n      # If we have grub.conf, use that\n      default=$(gawk -F= '/^default=/{print$2}' \"$grubcfg\" 2>/dev/null)\n      [[ -z $default ]] && {\n        default=0; default_missing=\"${c[Warn1]}(Warning: grub.conf lacks \\\"default=\\\"; showing title 0)${c[0]}\"\n      }\n      # Get the full kernel line for the default title statement\n      grub_cmdline=$(gawk /^title/,G \"$grubcfg\" | grep -E -v '^#|^ *#' | sed '1!s/^title.*/\\n&/' | gawk -vDEFAULT=$((default+1)) -vRS=\"\\n\\n\" 'NR==DEFAULT' | grep -o '/vmlinuz-.*')\n      ;;\n    grub.cfg)\n      # Otherwise, if we have a grub2 config (grub.cfg), use that\n      default=$(gawk -F\\\" '/^set default=/{print$2}' \"$grubcfg\")\n      grub_cmdline=$(gawk '/^menuentry.*{/,/^}/' \"$grubcfg\" | gawk -vRS=\"\\n}\\n\" -vDEFAULT=\"$((default+1))\" 'NR==DEFAULT' | grep -o '/vmlinuz-.*')\n  esac\n  \n  grub_kernel=$(gawk {print\\$1} <<<\"${grub_cmdline#/vmlinuz-}\" 2>/dev/null)\n  grub_cmdline=$(cut -d' ' -f2- <<<\"$grub_cmdline\")\n}\n\n\nOSINFO() {\n  # Local vars:\n  local distro_release kernel_build kernel_buildhost num_cpu btime hostname hntmp kernel total_plugins yum_plugins num_enabled f rhn_serverURL sURLtmp a rhn_enableProxy rhn_httpProxy rhn_enableProxyAuth rhn_proxyUser rhn_proxyPassword rhnProxyStuff rhsm_hostname rhsm_proxy_hostname rhsm_proxy_port rhsm_proxy_user rhsm_proxy_password rhsmProxyStuff uname systime boottime uptime_input runlevel initdefault timezone\n  \n  # These functions populate variables for later use\n  _CHECK_DISTRO \"$1\"\n  _CHECK_KERNELBUILD \"$1\"\n  _CHECK_GRUB \"$1\"\n  \n  # Grab number of cpus from proc/stat\n  num_cpu=$(gawk '/^cpu[[:graph:]]+/{n++} END{print n}' \"$1/proc/stat\" 2>/dev/null)\n  \n  # Grab btime (in seconds since U.Epoch) from proc/stat\n  btime=$(gawk '/^btime/{print $2}' \"$1/proc/stat\" 2>/dev/null)\n  \n  # Grab system hostname & kernel version from /proc first\n  hostname=$(cat \"$1/proc/sys/kernel/hostname\" 2>/dev/null)\n  kernel=$(cat \"$1/proc/sys/kernel/osrelease\" 2>/dev/null)\n  \n  # Grab yum plugin stuff\n  if total_plugins=$(ls \"$1\"/etc/yum/pluginconf.d/*.conf 2>/dev/null); then\n    total_plugins=$(wc -l <<<\"$total_plugins\")\n    yum_plugins=$(\n      cd \"$1\"/etc/yum/pluginconf.d/\n      gawk -F= '\n        /^enabled *= */ {\n          sub(\" \", \"\")\n          if ($2==1) printf FILENAME\" \"\n        }\n      ' *.conf\n    )\n    if [[ -n $yum_plugins ]]; then\n      num_enabled=$(wc -w <<<\"$yum_plugins\")\n      yum_plugins=$(sed 's/\\.conf /, /g' <<<\"$yum_plugins\")\n      yum_plugins=${yum_plugins%, }\n      yum_plugins=\"$num_enabled enabled plugins: $yum_plugins\"\n    else\n      yum_plugins=\"0 enabled plugins\"\n    fi\n  else\n    yum_plugins=\"${c[Warn1]}No yum plugin info (missing etc/yum/pluginconf.d/*.conf)${c[0]}\"\n  fi\n  \n  # Grab RHN settings\n  _get_rhn_cfg() {\n    local directive=$1 file=\"$2/etc/sysconfig/rhn/up2date\" result=\n    result=$(gawk -F= \"/^$directive *=/{print\\$2}\" \"$file\" 2>/dev/null)\n    result=${result/ /}\n    if [[ -n $result ]]; then\n      echo \"$directive = $result\"\n    else\n      return 1\n    fi\n  }\n  a=\"\\n            \"\n  if rhn_serverURL=$(_get_rhn_cfg serverURL \"$1\"); then\n    sURLtmp=$(grep -E --color=always -si 'oracle' <<<\"$serverURL\") && rhn_serverURL=$sURLtmp\n    [[ $XSOS_SCRUB_IP_HN == y ]] && rhn_serverURL=\"serverURL = ${c[Warn2]}SCRUBBED${c[0]}\"\n    if rhn_enableProxy=$(_get_rhn_cfg enableProxy \"$1\") && [[ $rhn_enableProxy -eq 1 ]]; then\n      rhnProxyStuff=\"${a}$rhn_enableProxy\"\n      if rhn_httpProxy=$(_get_rhn_cfg httpProxy \"$1\"); then\n        [[ $XSOS_SCRUB_IP_HN == y ]] && rhnProxyStuff+=\"${a}httpProxy = ${c[Warn2]}SCRUBBED${c[0]}\" || rhnProxyStuff+=\"${a}$rhn_httpProxy\"\n        if rhn_enableProxyAuth=$(_get_rhn_cfg enableProxyAuth \"$1\") && [[ $rhn_enableProxyAuth -eq 1 ]]; then\n          rhnProxyStuff+=\"${a}$rhn_enableProxyAuth\"\n          if rhn_proxyUser=$(_get_rhn_cfg proxyUser \"$1\"); then\n            [[ $XSOS_SCRUB_PROXYUSERPASS == y ]] && rhnProxyStuff+=\"${a}proxyUser = ${c[Warn2]}SCRUBBED${c[0]}\" || rhnProxyStuff+=\"${a}$rhn_proxyUser\"\n          fi\n          if rhn_proxyPassword=$(_get_rhn_cfg proxyPassword \"$1\"); then\n            [[ $XSOS_SCRUB_PROXYUSERPASS == y ]] && rhnProxyStuff+=\"${a}proxyPassword = ${c[Warn2]}SCRUBBED${c[0]}\" || rhnProxyStuff+=\"${a}$rhn_proxyPassword\"\n          fi\n        else\n          rhnProxyStuff+=\"${a}$rhn_enableProxyAuth\"\n        fi\n      else\n        rhnProxyStuff+=\"${a}httpProxy =\"\n      fi\n    else\n      rhnProxyStuff=\"${a}$rhn_enableProxy\"\n    fi\n  else\n    rhn_serverURL=\"${c[red]}(missing)${c[0]}\"\n  fi\n  \n  # Grab RHSM settings\n  _get_rhsm_cfg() {\n    local directive=$1 file=\"$2/etc/rhsm/rhsm.conf\" result=\n    result=$(gawk -F= \"/^$directive *=/{print\\$2}\" \"$file\" 2>/dev/null)\n    result=${result/ /}\n    if [[ -n $result ]]; then\n      echo \"$directive = $result\"\n    else\n      return 1\n    fi\n  }\n  a=\"\\n            \"\n  if rhsm_hostname=$(_get_rhsm_cfg hostname \"$1\"); then\n    [[ $XSOS_SCRUB_IP_HN == y ]] && rhsm_hostname=\"hostname = ${c[Warn2]}SCRUBBED${c[0]}\"\n    if rhsm_proxy_hostname=$(_get_rhsm_cfg proxy_hostname \"$1\"); then\n      [[ $XSOS_SCRUB_IP_HN == y ]] && rhsmProxyStuff+=\"${a}proxy_hostname = ${c[Warn2]}SCRUBBED${c[0]}\" || rhsmProxyStuff=\"${a}$rhsm_proxy_hostname\"\n      if rhsm_proxy_port=$(_get_rhsm_cfg proxy_port \"$1\"); then\n        [[ $XSOS_SCRUB_IP_HN == y ]] && rhsmProxyStuff+=\"${a}proxy_port = ${c[Warn2]}SCRUBBED${c[0]}\" || rhsmProxyStuff+=\"${a}$rhsm_proxy_port\"\n      fi\n      if rhsm_proxy_user=$(_get_rhsm_cfg proxy_user \"$1\"); then\n        [[ $XSOS_SCRUB_PROXYUSERPASS == y ]] && rhsmProxyStuff+=\"${a}proxy_user = ${c[Warn2]}SCRUBBED${c[0]}\" || rhsmProxyStuff+=\"${a}$rhsm_proxy_user\"\n      fi\n      if rhsm_proxy_password=$(_get_rhsm_cfg proxy_password \"$1\"); then\n        [[ $XSOS_SCRUB_PROXYUSERPASS == y ]] && rhsmProxyStuff+=\"${a}proxy_password = ${c[Warn2]}SCRUBBED${c[0]}\" || rhsmProxyStuff+=\"${a}$rhsm_proxy_password\"\n      fi\n    else\n      rhsmProxyStuff=\"${a}proxy_hostname =\"\n    fi\n  else\n    rhsm_hostname=\"${c[red]}(missing)${c[0]}\"\n  fi\n\n  # If running on localhost\n  if [[ $1 == / ]]; then\n    uname=$(uname -a | gawk '{printf \"mach=%s  cpu=%s  platform=%s\\n\", $(NF-3), $(NF-2), $(NF-1)}')\n    systime=$(date)\n    [[ $(wc -w <<<\"$systime\") == 6 ]] &&\n      systime=$(gawk -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '{if ($3 < 10) space=\" \"; printf \"%s %s %s%s %s %s%s%s %s\\n\", $1,$2,space,$3,$4,H_IMP,$5,H0,$6}' <<<\"$systime\")\n    boottime=$(date --date=@$btime 2>/dev/null)\n    [[ $(wc -w <<<\"$boottime\") == 6 ]] &&\n      boottime=$(gawk -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" -vbtime=$btime '{if ($3 < 10) space=\" \"; printf \"%s %s %s%s %s %s%s%s %s  (epoch: %s)\\n\", $1,$2,space,$3,$4,H_IMP,$5,H0,$6,btime}' <<<\"$boottime\")\n    [[ -r /etc/sysconfig/clock ]] &&\n      timezone=$(gawk -F= '/^ZONE=/{print $2}' \"/etc/sysconfig/clock\" 2>/dev/null | tr -d \\\")\n    [[ -x $(which timedatectl 2>/dev/null) ]] &&\n      timezone=$(timedatectl | gawk '/Time zone/ {print $3}' 2>/dev/null)\n    uptime_input=$(uptime)\n    runlevel=$(runlevel)\n    initdefault=$(basename $(readlink -q /etc/systemd/system/default.target) 2>/dev/null) &&\n      initdefault=${initdefault%.target} ||\n        [[ -r /etc/inittab ]] && initdefault=$(gawk -F: '/^id.*initdefault/ {print $2}' </etc/inittab)\n    \n  # Otherwise, running on sosreport\n  else\n    # If sosreport ran in rescue mode, try to get good hostname\n    if grep -qsw rescue \"$1/proc/cmdline\"; then\n      hostname=$(gawk -F= /^HOSTNAME=/{print\\$2}  \"$1/etc/sysconfig/network\" 2>/dev/null) ||\n        hostname=\"${c[Warn1]}unknown${c[0]}  (sosreport collected from rescue mode)\"\n    # Otherwise, if no hostname from proc/, try to get from sosroot/hostname or sosroot/uname\n    else\n      [[ -z $hostname ]] && {\n        hostname=$(gawk '!/\\/.*bin/ && NF!=0' \"$1/hostname\" 2>/dev/null) ||\n          hostname=$(gawk '!/\\/.*bin/ && NF!=0 {print $2}' \"$1/uname\" 2>/dev/null) ||\n            hostname=\"${c[Warn1]}unknown${c[0]}\"\n      }\n    fi\n    # If sosreport ran in rescue mode, leave it to the kernel-build funness\n    if grep -qsw rescue \"$1/proc/cmdline\"; then\n      kernel=\"$kernel  ${c[Warn1]}(Rescue mode kernel version)${c[0]}\"\n    # Otherwise, if no kernel version from proc/, try to get from sosroot/uname\n    else\n      [[ -z $kernel ]] && {\n        kernel=$(gawk '!/\\/.*bin/ && NF!=0 {print $3}' \"$1/uname\" 2>/dev/null) ||\n          kernel=\"${c[Warn1]}unknown${c[0]}\"\n      }\n    fi\n    uname=$(gawk '!/\\/.*bin/ && NF!=0 {printf \"mach=%s  cpu=%s  platform=%s\\n\", $(NF-3), $(NF-2), $(NF-1)}' \"$1/uname\" 2>/dev/null) ||\n      uname=\"${c[Warn1]}unknown${c[0]}\"\n    # Check kernel for uek\n    grep -qsi uek <<<\"$kernel\" && kernel=$(grep --color=always -i uek <<<\"$kernel\")\n    grep -qsi uek <<<\"$grub_kernel\" && grub_kernel=$(grep --color=always -i uek <<<\"$grub_kernel\")\n    \n    systime=$(gawk '!/\\/.*bin/ && NF!=0' \"$1/date\" 2>/dev/null)\n    [[ $(wc -w <<<\"$systime\") == 6 ]] &&\n      systime=$(gawk -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '{if ($3 < 10) space=\" \"; printf \"%s %s %s%s %s %s%s%s %s\\n\", $1,$2,space,$3,$4,H_IMP,$5,H0,$6}' <<<\"$systime\")\n   \n    [[ -r \"$1/etc/sysconfig/clock\" ]] && \n      timezone=$(gawk -F= '/^ZONE=/{print $2}' \"$1/etc/sysconfig/clock\" 2>/dev/null | tr -d \\\")\n    [[ -r \"$1/sos_commands/systemd/timedatectl\" ]] &&\n      timezone=$(gawk '/Time zone/ {print $3}' \"$1/sos_commands/systemd/timedatectl\" 2>/dev/null)\n\n    [[ -n $timezone && -f /usr/share/zoneinfo/$timezone ]] &&\n      boottime=$(echo -n $(TZ=$timezone date --date=@$btime 2>/dev/null)) ||\n        boottime=$(echo -n $(TZ= date --date=@$btime 2>/dev/null))\n    \n    [[ $(wc -w <<<\"$boottime\") == 6 ]] &&\n      boottime=$(gawk -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" -vbtime=$btime '{if ($3 < 10) space=\" \"; printf \"%s %s %s%s %s %s%s%s %s  (epoch: %s)\\n\", $1,$2,space,$3,$4,H_IMP,$5,H0,$6,btime}' <<<\"$boottime\")\n    \n    uptime_input=$(gawk '!/\\/.*bin/ && NF!=0' \"$1/uptime\" 2>/dev/null) ||\n      uptime_input=$(gawk '!/\\/.*bin/ && NF!=0' \"$1/sos_commands/general/uptime\" 2>/dev/null) ||\n        uptime_input=$(gawk '!/\\/.*bin/ && NF!=0' \"$1/sos_commands/host/uptime\" 2>/dev/null)\n\n    [[ -r $1/sos_commands/startup/runlevel ]] && runlevel=$(<\"$1/sos_commands/startup/runlevel\")\n    [[ -r $1/etc/inittab ]] &&\n      initdefault=$(gawk -F: '/^id.*initdefault/ {print $2}' <\"$1/etc/inittab\") ||\n        initdefault=unknown\n  fi\n  \n  [[ $XSOS_SCRUB_IP_HN == y ]] && hostname=\"${c[Warn2]}SCRUBBED${c[0]}\"\n  \n  # Start printing stuff\n  echo -e \"${c[H1]}OS${c[0]}\"\n  echo -e \"  ${c[H2]}Hostname:${c[0]} $hostname\"\n  echo -e \"  ${c[H2]}Distro:${c[0]}   $distro_release\"\n  echo -e \"  ${c[H2]}RHN:${c[0]}      $rhn_serverURL$rhnProxyStuff\"\n  echo -e \"  ${c[H2]}RHSM:${c[0]}     $rhsm_hostname$rhsmProxyStuff\"\n  echo -e \"  ${c[H2]}YUM:${c[0]}      $yum_plugins\"\n  [[ -n $runlevel ]] &&\n  echo -e \"  ${c[H2]}Runlevel:${c[0]} $runlevel  (default $initdefault)\"\n  echo -e \"  ${c[H2]}SELinux:${c[0]}  $(_CHECK_SELINUX \"$1\")\"\n  echo -e \"  ${c[H2]}Arch:${c[0]}     $uname\"\n  echo -e \"  ${c[H2]}Kernel:${c[0]}\"\n  echo -e \"    ${c[H3]}Booted kernel:${c[0]}  $kernel\"\n  echo -e \"    ${c[H3]}GRUB default:${c[0]}   $bad_grubcfg$grub_kernel  $default_missing\"\n  \n  # Print and format kernel version\n  echo -e \"    ${c[H3]}Build version:${c[0]}\"\n  # If kernel build was detected ...\n  if [[ -n $kernel_build ]]; then\n    # Print a notice if rescue mode\n    grep -qsw rescue \"$1/proc/cmdline\" &&\n      echo -e \"${c[Warn1]}     (Rescue mode detected; build info captured from logs of last boot)${c[0]}\"\n    # Format it to fit properly\n    kernel_build=$(fold -sw$XSOS_FOLD_WIDTH <<<\"$kernel_build\" | sed 's,^,      ,')\n    # Change color to warning color (orange) if can't find \"build.redhat.com\"\n    grep -qe '\\.z900\\.redhat\\.com' -e '\\.build\\.redhat\\.com' -e '\\.bos\\.redhat\\.com' -e '\\.perf\\.redhat\\.com' <<<\"$kernel_buildhost\" ||\n      kernel_build=\"${c[Warn1]}$kernel_build${c[0]}\"\n    echo -e \"$kernel_build\"\n  else\n    echo -e \"$XSOS_INDENT_H3${c[Warn1]}unknown${c[0]}\"\n  fi\n  \n  # Print kernel cmdline from proc/cmdline\n  echo -e \"    ${c[H3]}Booted kernel cmdline:${c[0]}\"\n  # If rescue mode detected, print a warning\n  grep -qsw rescue \"$1/proc/cmdline\" &&\n    echo -e \"     ${c[Warn1]}(Rescue mode detected)${c[0]}\"\n  if [[ -r $1/proc/cmdline ]]; then\n    proc_cmdline=$(sed -r 's,^BOOT_IMAGE=/[[:graph:]]+ ,,' \"$1\"/proc/cmdline)\n    [[ $XSOS_SCRUB_IP_HN == y ]] && proc_cmdline=$(sed \"s/${hostname%%.*}/HOSTNAME/g\" <<<\"$proc_cmdline\")\n    fold -sw$XSOS_FOLD_WIDTH <<<\"$proc_cmdline\" 2>/dev/null | sed -e \"s,^,$XSOS_INDENT_H3,\"\n  else\n    echo -e \"$XSOS_INDENT_H3${c[Warn1]}unknown${c[0]}\"\n  fi\n\n  echo -e \"    ${c[H3]}GRUB default kernel cmdline:${c[0]}  $default_missing\"\n  if [[ -n $bad_grubcfg ]]; then\n    echo -e \"      $bad_grubcfg\"\n  else\n    if grep -qs 'unknown.*rescue mode' <<<\"$grub_cmdline\"; then\n      echo -e \"$XSOS_INDENT_H3$grub_cmdline\"\n    else\n      [[ $XSOS_SCRUB_IP_HN == y ]] && grub_cmdline=${grub_cmdline//${hostname%%.*}/HOSTNAME}\n      fold -sw$XSOS_FOLD_WIDTH <<<\"$grub_cmdline\" 2>/dev/null | sed -e \"s,^,$XSOS_INDENT_H3,\"\n    fi\n  fi\n    \n  # Print kernel tainted-status\n  echo -e \"    ${c[H3]}Taint-check:${c[0]} $(CHECK_TAINTED --noquote \"$1\" H3)\"\n  # End the kernel section\n  echo -e \"    ${c[lgrey]}- - - - - - - - - - - - - - - - - - -${c[0]}\"\n  \n  ##echo -e \"  ${c[H2]}Supportability:${c[0]}\"\n  \n  [[ -n $systime ]] &&\n  echo -e \"  ${c[H2]}Sys time:${c[0]}  $systime\"\n\n  # Assuming have uptime input and detected num of cpus, print uptime, loadavg, etc\n  [[ -n $uptime_input && -n $num_cpu ]] &&\n  gawk -vSYSTIME=\"$systime\" -vTIMEZONE=\"$timezone\" -vBTIME=\"$boottime\" -vNUM_CPU=\"$num_cpu\" -vREDBOLD=\"${c[RED]}\" -vRED=\"${c[red]}\" -vORANGE=\"${c[orange]}\" -vGREEN=\"${c[green]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '\n      !/load average/ { next }\n      {\n      Time = $1\n      \n      Uptime = gensub(/^ *[[:graph:]]+ up +(.+users?),.+/, \"\\\\1\", 1)\n      \n      Load[15] = $(NF)\n      Load[5]  = $(NF-1)\n      Load[1]  = $(NF-2)\n      for (i in Load) {\n        sub(/,/, \"\", Load[i])\n        LP[i] = Load[i] * 100 / NUM_CPU\n      }\n      for (i in LP) {\n        if (LP[i] < 70) Color[i] = GREEN\n        if (LP[i] > 69) Color[i] = ORANGE\n        if (LP[i] > 89) Color[i] = RED\n        if (LP[i] > 99) Color[i] = REDBOLD\n      }\n      \n      if (SYSTIME == \"\")\n        printf \"  %sSys time:%s  %s\\n\", H2, H0, Time\n      printf   \"  %sBoot time:%s %s\\n\", H2, H0, BTIME\n      if (TIMEZONE != \"\")\n        printf \"  %sTime Zone:%s %s\\n\", H2, H0, TIMEZONE\n      printf   \"  %sUptime:%s    %s\\n\", H2, H0, Uptime\n      printf   \"  %sLoadAvg:%s   %s[%d CPU]%s %s (%s%.0f%%%s), %s (%s%.0f%%%s), %s (%s%.0f%%%s)\\n\",\n        H2, H0, H_IMP, NUM_CPU, H0, Load[1], Color[1], LP[1], H0, Load[5], Color[5], LP[5], H0, Load[15], Color[15], LP[15], H0\n    }' <<<\"$uptime_input\"\n    \n  # Print info from proc/stat\n  [[ -n $btime ]] &&\n  gawk -vH3=\"${c[H3]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" -vH_IMP=\"${c[Imp]}\" '\n    /^cpu / {\n      TotalTime = $2 + $3 + $4 + $5 + $6 + $7 + $8 + $9 + $10 + $11\n      user    = $2 * 100 / TotalTime\n      nice    = $3 * 100 / TotalTime\n      sys     = $4 * 100 / TotalTime\n      idle    = $5 * 100 / TotalTime\n      iowait  = $6 * 100 / TotalTime\n      irq     = $7 * 100 / TotalTime\n      softirq = $8 * 100 / TotalTime\n      steal   = $9 * 100 / TotalTime\n     #guest      = $10\n     #guest_nice = $11\n    }\n    /^cpu[[:graph:]]+/ { num_cpu++ }\n    /procs_running/    { procs_running = $2 }\n    /procs_blocked/    { procs_blocked = $2 }\n    /processes/        { processes = $2 }\n    \n    END {\n      printf \"  %s/proc/stat:%s\\n\",\n        H2, H0\n      printf \"    %sprocs_running:%s %d   %sprocs_blocked:%s %d\", H3, H0, procs_running, H3, H0, procs_blocked\n      printf \"    %sprocesses [Since boot]:%s %d\\n\", H3, H0, processes\n      printf \"    %scpu [Utilization since boot]:%s\\n      us %.0f%%, ni %.0f%%, sys %.0f%%, idle %.0f%%, iowait %.0f%%, irq %.0f%%, sftirq %.0f%%, steal %.0f%%\\n\",\n        H3, H0, user, nice, sys, idle, iowait, irq, softirq, steal\n    }\n  ' <\"$1/proc/stat\"\n  \n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nKDUMP() {\n  # Local vars\n  local kexec_tools_vers kdump_initrd path kdump_cfg target MemTotal PathAvailableSpace ColorAvailable lsbootfile dfalfile\n  \n  # If the os module was called, grub config was already inspected; otherwise, we need to do it\n  [[ -n $os ]] || _CHECK_GRUB \"$1\"\n        \n  # If running on localhost ....\n  if [[ $1 == / ]]; then\n    __rpm_check_kexec() {\n      kexec_tools_vers=$(rpm -q kexec-tools) \\\n        && echo $kexec_tools_vers \\\n        || echo -e \"${c[Warn1]}$kexec_tools_vers${c[0]}\"\n    }\n    __svc_check_kdump() {\n      if command -v systemctl >/dev/null; then\n        if systemctl list-unit-files | grep -qs kdump.service; then\n          systemctl list-unit-files | gawk '/kdump.service/ { printf \"UNIT STATE\\n\" $0 }' | column -t | gawk -vH0=\"${c[0]}\" -vgreen=\"${c[green]}\" -vwarn=\"${c[Warn1]}\" '\n            { gsub(\".*disabled\", warn \"&\" H0)\n              gsub(\".*enabled\", green \"&\" H0)\n              print\n            }'\n        else\n          echo -e \"${c[Warn1]}Unit kdump.service not-found (Reason: No such file or directory)${c[0]}\"\n        fi\n      else\n        if chkconfig --list kdump &>/dev/null; then\n          chkconfig --list kdump | column -t | gawk -vH0=\"${c[0]}\" -vgreen=\"${c[green]}\" -vwarn=\"${c[Warn1]}\" '\n            { for (i=3; i<6; i++) {\n                gsub(i \":on\", i \":\" green \"on\" H0)\n                gsub(i \":off\", i \":\" warn \"off\" H0)\n              }\n              print\n            }'\n        else\n          echo -e \"${c[Warn1]}$(chkconfig --list kdump 2>&1)${c[0]}\"\n        fi\n      fi\n    }\n    __initrd_file_check() {\n      ls /boot/initr*kdump.img &>/dev/null \\\n        && ls -l /boot/initr*kdump.img | sed -r 's@^........... +[0-9]+ \\w+ *\\w+ *([0-9]+ .*)@\\1@' | sed -r 's,/+boot/,,' \\\n        || echo -e \"${c[Warn1]}missing '/boot/initr*kdump.img'${c[0]}\"\n    }\n    __get_df_for_parent_fs_of_path() {\n      df_output=$(df \"$path\" | gawk '{if (NF==1) {dev=$1; getline; print dev $0} else if (NR==2) print}')\n    }\n    \n      \n  # If running on sosreport ....\n  else\n    __rpm_check_kexec() {\n      if [[ -r \"$sosroot\"/installed-rpms ]]; then\n        grep -q kexec-tools \"$sosroot\"/installed-rpms \\\n          && gawk '/kexec-tools/{print$1}' \"$sosroot\"/installed-rpms \\\n          || echo -e \"${c[Warn1]}package kexec-tools is not installed${c[0]}\"\n      else\n        echo -e \"${c[Warn1]}missing '$sosroot/installed-rpms'${c[0]}\"\n      fi\n    }\n    __svc_check_kdump() {\n      if [[ -r \"$sosroot\"/sos_commands/systemd/systemctl_list-unit-files ]]; then\n        if grep -qs kdump.service \"$sosroot\"/sos_commands/systemd/systemctl_list-unit-files; then\n          gawk '/kdump.service/ { printf \"UNIT STATE\\n\" $0 }' \"$sosroot\"/sos_commands/systemd/systemctl_list-unit-files | column -t | gawk -vH0=\"${c[0]}\" -vgreen=\"${c[green]}\" -vwarn=\"${c[Warn1]}\" '\n            { gsub(\".*disabled\", warn \"&\" H0)\n              gsub(\".*enabled\", green \"&\" H0)\n              print\n            }'\n        else\n          echo -e \"${c[Warn1]}Unit kdump.service not-found (Reason: No such file or directory)${c[0]}\"\n        fi\n      else\n        if [[ -r \"$sosroot\"/chkconfig ]]; then\n          if grep -q ^kdump \"$sosroot\"/chkconfig; then\n            grep ^kdump \"$sosroot\"/chkconfig | column -t | gawk -vH0=\"${c[0]}\" -vgreen=\"${c[green]}\" -vwarn=\"${c[Warn1]}\" '\n              { for (i=3; i<6; i++) {\n                  gsub(i \":on\", i \":\" green \"on\" H0)\n                  gsub(i \":off\", i \":\" warn \"off\" H0)\n                }\n                print\n              }'\n          else\n            echo -e \"${c[Warn1]}kdump not present in chkconfig output${c[0]}\"\n          fi\n        else\n          echo -e \"${c[Warn1]}missing '$sosroot/chkconfig'${c[0]}\"\n        fi\n      fi\n    }\n    __initrd_file_check() {\n      [[ -r \"$sosroot\"/sos_commands/bootloader/ls_-laR_.boot ]] && lsbootfile=\"$sosroot\"/sos_commands/bootloader/ls_-laR_.boot\n      [[ -r \"$sosroot\"/sos_commands/boot/ls_-lanR_.boot ]] && lsbootfile=\"$sosroot\"/sos_commands/boot/ls_-lanR_.boot\n      [[ -r \"$sosroot\"/sos_commands/grub2/ls_-lanR_.boot ]] && lsbootfile=\"$sosroot\"/sos_commands/grub2/ls_-lanR_.boot\n      if [[ -z $lsbootfile ]]; then\n        echo -e \"${c[Warn1]}missing '$sosroot/sos_commands/bootloader/ls_-laR_.boot' & '$sosroot/sos_commands/boot/ls_-lanR_.boot' & '$sosroot/sos_commands/grub2/ls_-lanR_.boot'${c[0]}\"\n      else\n        kdump_initrd=$(grep 'initr.*kdump.img$' \"$lsbootfile\") \\\n          && sed -r 's@^........... +[0-9]+ \\w+ *\\w+ *([0-9]+ .*)@\\1@' <<<\"$kdump_initrd\" | sed -r 's,/+boot/,,' \\\n          || echo -e \"${c[Warn1]}missing '/boot/initr*kdump.img' according to '$lsbootfile'${c[0]}\"\n      fi\n    }\n    __get_df_for_parent_fs_of_path() {\n      local dfpath lastloop\n      dfpath=$path\n      [[ -r \"$sosroot\"/sos_commands/filesys/df_-al ]] && dfalfile=\"$sosroot\"/sos_commands/filesys/df_-al\n      [[ -r \"$sosroot\"/sos_commands/filesys/df_-al_-x_autofs ]] && dfalfile=\"$sosroot\"/sos_commands/filesys/df_-al_-x_autofs\n\n      while [[ $(grep -v ^rootfs \"$dfalfile\" 2>/dev/null | gawk -vP=$dfpath '{if ($6==P || $5==P) n+=1} END{if (n>0) print 0; else print 255}') -eq 255 ]]; do\n        if [[ $lastloop == y ]]; then\n          echo \"DEBUG: This should never happen unless the df_-al file is missing an entry for '/'\"\n          return 2\n        fi\n        dfpath=${dfpath%/*}\n        if [[ -z $dfpath ]]; then\n          dfpath=/\n          lastloop=y\n        fi\n      done\n      df_output=$(grep -v ^rootfs \"$dfalfile\" | gawk -vP=$dfpath '{if (NF==6 && $6==P) print; else if (NF==1) {dev=$1; getline; if ($5==P) print dev $0} }')\n    }\n  fi\n  \n  # A couple functions that work regardless of localhost/sosreport\n  __get_crashkernel_proc_cmdline() {\n    local out\n    if [[ -r \"$sosroot\"/proc/cmdline ]]; then\n      out=$(grep -E -o 'crashkernel=[[:graph:]]+' \"$sosroot\"/proc/cmdline)\n    else\n      out=\"${c[Warn1]}file missing${c[0]}\"\n    fi\n    [[ -n $out ]] && echo -e \"$out\" || echo -e \"${c[Warn1]}crashkernel param not present${c[0]}\"\n  }\n  __get_crashkernel_grub_cmdline() {\n    local out\n    if [[ -n $bad_grubcfg ]]; then\n      out=\"$bad_grubcfg\"\n    else\n      out=$(grep -E -o 'crashkernel=[[:graph:]]+' <<<\"$grub_cmdline\")\n    fi\n    [[ -n $out ]] && echo -e \"$out\" || echo -e \"${c[Warn1]}crashkernel param not present${c[0]}\"\n  }\n  __P() {\n    echo -e \"$XSOS_INDENT_H2${c[H3]}${1} =  $(gawk -vW=\"${c[Warn1]}\" -vG=\"${c[green]}\" '{ if ($1==0) print W 0; else print G $1 }' \"$sosroot\"/proc/sys/${1//.//} 2>/dev/null)${c[0]}\"\n  }\n  __Pa() {\n    echo -e \"$XSOS_INDENT_H2${c[H3]}${1} ${c[H4]}$2${c[H3]}=  $(gawk -vW=\"${c[Warn1]}\" -vG=\"${c[green]}\" -vH0=\"${c[0]}\" \"$3\" \"$4\" \"$sosroot\"/proc/sys/${1//.//} 2>/dev/null)${c[0]}\"\n  }\n  __get_proc_iomem() {\n    local out\n    if [[ ! -r \"$sosroot\"/proc/iomem ]]; then\n      echo -e \"$XSOS_INDENT_H2${c[Warn1]}Missing $sosroot/proc/iomem${c[0]}\"\n      return\n    fi\n    if out=$(grep Crash.kernel \"$sosroot\"/proc/iomem); then\n      echo -e \"$XSOS_INDENT_H2${c[green]}${out}${c[0]}\"\n    else\n      echo -e \"$XSOS_INDENT_H2${c[Warn1]}Memory IS NOT reserved, according to $sosroot/proc/iomem${c[0]}\"\n    fi\n  }\n  \n  echo -e \"${c[H1]}KDUMP CONFIG${c[0]}\"\n  echo -e \"$XSOS_INDENT_H1${c[H2]}kexec-tools rpm version:${c[0]}\"\n    __rpm_check_kexec | sed \"s,^,$XSOS_INDENT_H2,\"\n  echo -e \"$XSOS_INDENT_H1${c[H2]}Service enablement:${c[0]}\"\n    __svc_check_kdump | sed \"s,^,$XSOS_INDENT_H2,\"\n  echo -e \"$XSOS_INDENT_H1${c[H2]}kdump initrd/initramfs:${c[0]}\"\n    __initrd_file_check | gawk '{ print gensub(/^([0-9]+) *([[:upper:]][[:lower:]]+) *([0-9]{1,2}) *([0-9]{4}) *(initrd.*)$/, \"\\\\1  \\\\2 \\\\3 \\\\4  \\\\5\", 1) }' | sed \"s,^,$XSOS_INDENT_H2,\"\n    # The extra gawk command above reformats spacing in the ls -l output\n  echo -e \"$XSOS_INDENT_H1${c[H2]}Memory reservation config:${c[0]}\"\n    grep -qsw rescue \"$1/proc/cmdline\" && echo -e \"$XSOS_INDENT_H1 ${c[Warn2]}(Rescue mode detected)${c[0]}\"\n    echo -e \"$XSOS_INDENT_H2${c[H3]}/proc/cmdline {${c[0]} $(__get_crashkernel_proc_cmdline) ${c[H3]}}${c[0]}\"\n    echo -e \"$XSOS_INDENT_H2${c[H3]}GRUB default  {${c[0]} $(__get_crashkernel_grub_cmdline) ${c[H3]}}${c[0]}\"\n  echo -e \"$XSOS_INDENT_H1${c[H2]}Actual memory reservation per /proc/iomem:${c[0]}\"\n    __get_proc_iomem\n  echo -e \"$XSOS_INDENT_H1${c[H2]}kdump.conf:${c[0]}\"\n  \n    if [[ -r \"$sosroot\"/etc/kdump.conf ]]; then\n      kdump_cfg=$(grep -E -v '^[[:space:]]*$|^#' \"$sosroot\"/etc/kdump.conf)\n      if [[ -n $kdump_cfg ]]; then\n        sed \"s,^,$XSOS_INDENT_H2,\" <<<\"$kdump_cfg\"\n        path=$(gawk '/^path / {print$2}' <<<\"$kdump_cfg\" | tail -n1)\n        [[ -z $path ]] && path=/var/crash\n        \n        for target in raw net nfs nfs4 ssh minix ext2 ext3 ext4 btrfs xfs; do\n          if grep -q ^$target <<<\"$kdump_cfg\"; then\n            path=\n            break\n          fi\n        done\n        \n      else\n        echo -e \"$XSOS_INDENT_H2${c[lgrey]}[All commented]${c[0]}\"\n        path=/var/crash\n      fi\n      \n      if [[ -n $path ]]; then\n        __get_df_for_parent_fs_of_path\n        if [[ -n $df_output ]]; then\n          echo -e \"$XSOS_INDENT_H1${c[H2]}kdump.conf \\\"path\\\" available space:${c[0]}\"\n          MemTotal=$(gawk '/^MemTotal/{printf \"%.2f\\n\", $2/1024/1024}' \"$sosroot\"/proc/meminfo)\n          PathAvailableSpace=$(gawk '{printf \"%.2f\\n\", $4/1024/1024}' <<<\"$df_output\")\n          ColorAvailable=$(gawk -vP=$path -vMemtotal=$(gawk /MemTotal/{print\\$2} \"$sosroot\"/proc/meminfo) '\n                            { if ($4 > Memtotal) print \"green\"; else print \"orange\" }\n                           '  <<<\"$df_output\")\n          echo -e \"$XSOS_INDENT_H2${c[H3]}System MemTotal (uncompressed core size) {${c[0]} $MemTotal GiB ${c[H3]}}${c[0]}\"\n          echo -e \"$XSOS_INDENT_H2${c[H3]}Available free space on target path's fs {${c[0]} ${c[$ColorAvailable]}$PathAvailableSpace GiB ${c[H3]}}${c[0]}  (fs=$(gawk '{print$6}' <<<\"$df_output\"))\"\n        else\n          echo \"DEBUG: no df_output .. shouldn't happen\"\n        fi\n      fi\n      \n    else\n      echo -e \"$XSOS_INDENT_H2${c[Warn1]}missing '$1/etc/kdump.conf'${c[0]}\"\n    fi\n\n  echo -e \"$XSOS_INDENT_H1${c[H2]}Panic sysctls:${c[0]}\"\n  if grep -qsw rescue \"$sosroot/proc/cmdline\"; then\n    echo -e \"$XSOS_INDENT_H1${c[Warn2]}  WARNING: RESCUE MODE DETECTED${c[0]}\"\n    echo -e \"$XSOS_INDENT_H1${c[Warn1]}  sysctls below reflect rescue env; inspect sysctl.conf manually${c[0]}\"\n  fi\n  __Pa kernel.sysrq \"[bitmask] \"  '{if ($1==0) printf \"\\\"0\\\"%s  (disallowed)\", H0; else if ($1==1) printf \"\\\"1\\\"%s  (all SysRqs allowed)\", H0; else printf \"\\\"%s\\\"%s  (see proc man page)\", $1, H0}'\n  __Pa kernel.panic \"[secs] \"  '{if ($1>0) printf \"%s%s%s  (secs til autoreboot after panic)\", W, $1, H0; else printf \"%s0%s  (no autoreboot on panic)\", G, H0}'\n  __P kernel.hung_task_panic\n  __P kernel.panic_on_oops\n  __P kernel.panic_on_io_nmi\n  __P kernel.panic_on_unrecovered_nmi\n  __P kernel.panic_on_stackoverflow\n  __P kernel.panic_on_warn\n  __P kernel.softlockup_panic\n  __P kernel.unknown_nmi_panic\n  __P kernel.nmi_watchdog\n  __Pa vm.panic_on_oom \"[0-2] \"  '{if ($1==0) printf \"%s0%s  (no panic)\", W, H0; else if ($1==1) printf \"%s1%s  (no panic if OOM-triggering task limited by mbind/cpuset)\", G, H0; else if ($1==2) printf \"%s2%s  (always panic)\", G, H0}'\n  \n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nCPUINFO() {\n  # Local vars:\n  local cpuinfo_input model_cpu vendor family num_cpu num_cpu_phys num_threads_per_cpu cpu_cores core_id num_cores_per_cpu cores1 cores2 coresNthreads cpu_flags\n  \n  [[ -f $1 ]] && cpuinfo_input=$1 || cpuinfo_input=$1/proc/cpuinfo\n  \n  # Get model of cpu\n  model_cpu=$(gawk -F: '/^model name/{print $2; exit}' <\"$cpuinfo_input\")\n  \n  # If no model detected (e.g. on Itanium), try to use vendor+family\n  [[ -z $model_cpu ]] && {\n    vendor=$(gawk -F: '/^vendor /{print $2; exit}' <\"$cpuinfo_input\")\n    family=$(gawk -F: '/^family /{print $2; exit}' <\"$cpuinfo_input\")\n    model_cpu=\"$vendor$family\"\n  }\n  \n  # Clean up cpu model string\n  model_cpu=$(sed -e 's,(R),,g' -e 's,(TM),,g' -e 's,  *, ,g' -e 's,^ ,,' <<<\"$model_cpu\")\n  \n  # Get number of logical processors\n  num_cpu=$(gawk '/^processor/{n++} END{print n}' <\"$cpuinfo_input\")\n  \n  # Get number of physical processors\n  num_cpu_phys=$(grep '^physical id' <\"$cpuinfo_input\" | sort -u | wc -l)\n  \n  # If \"physical id\" not found, we cannot make any assumptions (Virtualization--)\n  # But still, multiplying by 0 in some crazy corner case is bad, so set it to 1\n  # If num of physical *was* detected, add it to the beginning of the model string\n  [[ $num_cpu_phys == 0 ]] && num_cpu_phys=1 || model_cpu=\"$num_cpu_phys $model_cpu\"\n  \n  # If number of logical != number of physical, try to get info on cores & threads\n  if [[ $num_cpu != $num_cpu_phys ]]; then\n    \n    # Detect number of threads (logical) per cpu\n    num_threads_per_cpu=$(gawk '/^siblings/{print $3; exit}' <\"$cpuinfo_input\")\n    \n    # Two possibile ways to detect number of cores\n    cpu_cores=$(gawk '/^cpu cores/{print $4; exit}' <\"$cpuinfo_input\")\n    core_id=$(grep '^core id' <\"$cpuinfo_input\" | sort -u | wc -l)\n    \n    # The first is the most accurate, if it works\n    if [[ -n $cpu_cores ]]; then\n      num_cores_per_cpu=$cpu_cores\n    \n    # If \"cpu cores\" doesn't work, \"core id\" method might (e.g. Itanium)\n    elif [[ $core_id -gt 0 ]]; then\n      num_cores_per_cpu=$core_id\n    fi\n    \n    # If found info on cores, setup core variables for printing\n    if [[ -n $num_cores_per_cpu ]]; then\n      cores1=\"($((num_cpu_phys*num_cores_per_cpu)) CPU cores)\"\n      cores2=\" / $num_cores_per_cpu cores\"\n    # If didn't find info on cores, assume single-core cpu(s)\n    else\n      cores2=\" / 1 core\"\n    fi\n    \n    # If found siblings (threads), setup the variable for the final line\n    [[ -n $num_threads_per_cpu ]] &&\n      coresNthreads=\"\\n  └─$num_threads_per_cpu threads${cores2} each\"\n  fi\n  \n  # Check important cpu flags\n  # pae=physical address extensions  *  lm=64-bit  *  vmx=Intel hw-virt  *  svm=AMD hw-virt\n  # ht=hyper-threading  *  aes=AES-NI  *  constant_tsc=Constant Time Stamp Counter\n  cpu_flags=$(grep -E -o \"pae|lm|vmx|svm|ht|aes|constant_tsc|rdrand|nx\" <\"$cpuinfo_input\" | sort -u | sed ':a;N;$!ba;s/\\n/,/g')\n  [[ -n $cpu_flags ]] && cpu_flags=\"(flags: $cpu_flags)\"\n  \n  # Print it all out\n  echo -e \"${c[H1]}CPU${c[0]}\"\n  echo -e \"  ${c[Imp]}${num_cpu} logical processors${c[0]} ${cores1}\"\n  echo -e \"  ${model_cpu} ${cpu_flags} ${coresNthreads}\"\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nINTERRUPT() {\n  # Local vars:\n  local interrupts_input longest_len_interupt_field_one indent\n  [[ -f $1 ]] && interrupts_input=$1 || interrupts_input=$1/proc/interrupts\n  longest_len_interupt_field_one=$(gawk 'NR > 1 {print length($1)}' $interrupts_input | sort -nr | head -1)\n  indent=$(( longest_len_interupt_field_one + $(printf \"$XSOS_INDENT_H1\" | wc -m) ))\n  echo -e \"${c[H1]}INTERRUPTS${c[0]}\"\n  gawk '\n    NR > 1 {\n      printf \"%'$indent's \", $1\n      for (i=2; i <= NF; i++) {\n        if ($i ~ \"[^0-9]\")\n          printf \" %s\", $i\n        else if($i > 0)\n          printf \"▊\"\n        else\n          printf \".\"\n      }\n      printf \"\\n\"\n    }\n  ' <\"$interrupts_input\"\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nMEMINFO() {\n  # Local vars:\n  local meminfo_input\n  \n  [[ -f $1 ]] && meminfo_input=$1 || meminfo_input=$1/proc/meminfo\n  \n  echo -e \"${c[H1]}MEMORY${c[0]}\"\n  if grep -qsw rescue \"$1/proc/cmdline\"; then\n    echo -e \"${c[Warn2]}  WARNING: RESCUE MODE DETECTED${c[0]}\"\n    echo -e \"${c[Warn1]}  meminfo reflects rescue env; inspect sysctl.conf manually for HugePages${c[0]}\"\n  fi\n  \n  gawk -vu=$(tr '[:lower:]' '[:upper:]' <<<$XSOS_MEM_UNIT) -vcolor_MemUsed=\"${c[MemUsed]}\" -vcolor_HugePages=\"${c[HugePages]}\" -vcolor_Buffers=\"${c[Buffers]}\" -vcolor_Cached=\"${c[Cached]}\" -vcolor_Dirty=\"${c[Dirty]}\" -vcolor_warn=\"${c[Warn1]}\" -vH_IMP=\"${c[Imp]}\" -vH3=\"${c[H3]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" '\n    # These will come in handy\n    \n    function round(num, places) {\n      places = 10 ^ places\n      return int(num * places + .5) / places\n    }\n          \n    function memgraph_special(PercentA, PercentB, Color, PrettyName) {\n      PercentTotal = PercentA + PercentB\n      printf \"    %s%s \", Color, PrettyName\n      for (i=0; i <    round(PercentA/2, 0); i++) printf \"▊\"\n      for (i=0; i <    round(PercentB/2, 0); i++) printf \".\"\n      printf H0\n      for (i=0; i < 50-round(PercentTotal/2, 0); i++) printf \".\"\n      if      (round(PercentTotal,1) > 99.9) j=\" \"\n      else if (round(PercentTotal,1) > 9)    j=\"  \"\n      else                                   j=\"   \"\n      printf \"%s%s%.1f%%%s\\n\", j, Color, PercentTotal, H0\n    }\n    \n    function memgraph(Percent, Color, PrettyName) {\n      printf \"    %s%s \", Color, PrettyName\n      for (i=0; i <    round(Percent/2, 0); i++) printf \"▊\"\n      printf H0\n      for (i=0; i < 50-round(Percent/2, 0); i++) printf \".\"\n      if      (round(Percent,1) > 99.9) j=\" \"\n      else if (round(Percent,1) > 9)    j=\"  \"\n      else                          j=\"   \"\n      printf \"%s%s%.1f%%%s\\n\", j, Color, Percent, H0\n    }\n        \n    # Grab variables from meminfo\n    \n    /^MemTotal:/        { MemTotal  = $2 }\n    /^MemFree:/         { MemFree   = $2 }\n    /^Buffers:/         { Buffers   = $2 }\n    /^Cached:/          { Cached   += $2 }\n    /^SwapCached:/      { Cached   += $2 }\n    /^LowTotal:/        { LowTotal  = $2 }\n    /^LowFree:/         { LowFree   = $2 }\n    /^SwapTotal:/       { SwapTotal = $2 }\n    /^SwapFree:/        { SwapFree  = $2 }\n    /^Dirty:/           { Dirty     = $2 }\n    /^Shmem:/           { Shmem     = $2 }\n    /^Slab:/            { Slab      = $2 }\n    /^PageTables:/      { PageTables     = $2 }\n    /^Hugepagesize:/    { Hugepagesize   = $2 }\n    /^HugePages_Total:/ { HugepagesTotal = $2 }\n    /^HugePages_Free:/  { HugepagesFree  = $2 }\n    /^HugePages_Rsvd:/  { HugepagesRsvd  = $2 }\n    /^AnonHugePages:/   { THP_Used       = $2 }\n    /^Percpu:/          { Percpu         = $2 }\n    \n    END {\n      \n      # Compute additional variables\n      \n      MemUsed         = MemTotal - MemFree\n      Mem_Percent     = MemUsed * 100 / MemTotal\n      Buffers_Percent = Buffers * 100 / MemTotal\n      Cached_Percent  = Cached * 100 / MemTotal\n      MemUsedNoBC     = MemUsed - Buffers - Cached\n      MemNoBC_Percent = MemUsedNoBC * 100 / MemTotal\n      Dirty_Percent   = Dirty * 100 / MemTotal\n      Shmem_Percent   = Shmem * 100 / MemTotal\n      Percpu_Percent  = Percpu * 100 / MemTotal\n      Slab_Percent    = Slab * 100 / MemTotal\n      PT_Percent      = PageTables * 100 / MemTotal\n      HP              = Hugepagesize * HugepagesTotal\n      HP_PercentRam   = HP * 100 / MemTotal\n      \n      # If have hugepages, calculate in-use\n      \n      if (HugepagesTotal > 0) {\n        HP_Used         = (HugepagesTotal - HugepagesFree - HugepagesRsvd) * Hugepagesize\n        HP_Used_Percent = (HugepagesTotal - HugepagesFree - HugepagesRsvd) * 100 / HugepagesTotal\n        HP_Rsvd         = (HugepagesRsvd) * Hugepagesize\n        HP_Rsvd_Percent = (HugepagesRsvd) * 100 / HugepagesTotal\n        HP_Free         = (HugepagesFree) * Hugepagesize\n        HP_Free_Percent = (HugepagesFree) * 100 / HugepagesTotal\n      }\n      \n      # Else, need to avoid divide-by-zero errors\n      \n      else {\n        HP_Used         = 0\n        HP_Used_Percent = 0\n        HP_Rsvd         = 0\n        HP_Rsvd_Percent = 0\n        HP_Free         = 0\n        HP_Free_Percent = 0\n      }\n      \n      # If meminfo has LowTotal (modern x86_64 boxes do not)...\n      \n      if (LowTotal ~ /[0-9]+/) {\n        SHOW_Lowmem=1\n        LowUsed         = LowTotal - LowFree\n        LowUsed_Percent = LowUsed * 100 / LowTotal\n      }\n      \n      # Else, avoid divide-by-zero and hide it\n      \n      else {\n        SHOW_Lowmem=0\n        LowTotal        = 0\n        LowUsed         = 0\n        LowUsed_Percent = 0\n      }\n      \n      # If have swap-space...\n      \n      if (SwapTotal > 0) {\n        SwapUsed      = SwapTotal - SwapFree\n        Swap_Percent  = SwapUsed * 100 / SwapTotal\n      }\n      \n      # Else, avoid divide-by-zero errors\n      \n      else {\n        SwapUsed      = 0\n        Swap_Percent  = 0\n      }\n      \n      # If meminfo has Shmem, we show it; otherwise not\n      \n      if (Shmem ~ /[0-9]+/)\n        SHOW_Shmem=1\n      else\n        SHOW_Shmem=0\n      \n      # If unit is set to B, convert native KiB to bytes\n      \n      if (u == \"B\") {\n        MemUsed     *= 1024\n        MemTotal    *= 1024\n        MemUsedNoBC *= 1024\n        Dirty       *= 1024\n        Shmem       *= 1024\n        Slab        *= 1024\n        PageTables  *= 1024\n        HP          *= 1024\n        THP_Used    *= 1024\n        Percpu      *= 1024\n        if (HugepagesTotal > 0) { HP_Used *= 1024; HP_Rsvd *= 1024; HP_Free *= 1024 }\n        if (LowTotal > 0) { LowUsed *= 1024; LowTotal *= 1024 }\n        if (SwapTotal > 0) { SwapUsed *= 1024; SwapTotal *= 1024 }\n      }\n      \n      # Figure out what number to divide by to end up with MiB, GiB, or TiB\n      \n      if      (u == \"M\") divisor = 1024\n      else if (u == \"G\") divisor = 1024 ** 2\n      else if (u == \"T\") divisor = 1024 ** 3\n      \n      # If unit is set to M or G or T, do the division to convert from native KiB\n      \n      if (u == \"M\" || u == \"G\" || u == \"T\") {\n        MemUsed     /= divisor\n        MemTotal    /= divisor\n        MemUsedNoBC /= divisor\n        Dirty       /= divisor\n        Shmem       /= divisor\n        Slab        /= divisor\n        PageTables  /= divisor\n        HP          /= divisor\n        THP_Used    /= divisor\n        Percpu      /= divisor\n        if (HugepagesTotal > 0) { HP_Used /= divisor; HP_Rsvd /= divisor ; HP_Free /=divisor }\n        if (LowTotal > 0)  { LowUsed  /= divisor; LowTotal  /= divisor }\n        if (SwapTotal > 0) { SwapUsed /= divisor; SwapTotal /= divisor }\n      }\n      \n      # The unit string used just for printing\n      \n      if (u == \"B\")\n        Unit = \" \"u\n      else\n        Unit = \" \"u\"iB\"\n      \n      \n      # ASCII-ART fun\n      \n      printf \"  %sStats graphed as percent of MemTotal:%s\\n\", H2, H0\n      # The following line is disabled because it would kinda suck for people that run with NOCOLOR\n      # Or people that run with color and then copy the output to text -- uncomment it to see what I mean\n      #memgraph_special(MemNoBC_Percent, Buffers_Percent+Cached_Percent, color_MemUsed, \"MemUsed   \")\n      memgraph(Mem_Percent,     color_MemUsed,   \"MemUsed   \")\n      memgraph(Buffers_Percent, color_Buffers,   \"Buffers   \")\n      memgraph(Cached_Percent,  color_Cached,    \"Cached    \")\n      memgraph(HP_PercentRam,   color_HugePages, \"HugePages \")\n      memgraph(Dirty_Percent,   color_Dirty,     \"Dirty     \")\n\n      \n      # If unit is T, print percentages with no decimal & byteunits with 2-3 decimal-points of precision\n      \n      if (u == \"T\") {\n        Prec_Percent = 0\n        Prec_BytesLo = 2\n        Prec_BytesHi = 3\n      }\n      \n      # If unit is G, print percentages with no decimal & byteunits with 1-2 decimal-points of precision\n      \n      else if (u == \"G\") {\n        Prec_Percent = 0\n        Prec_BytesLo = 1\n        Prec_BytesHi = 2\n      }\n      \n      # If unit is B or K or M, print percentages with 1 decimal-point of precision & byteunits with no decimal\n      \n      else {\n        Prec_Percent = 1\n        Prec_BytesLo = 0\n        Prec_BytesHi = 0\n      }\n      \n      # Now time to round off the numbers\n      \n      Mem_Percent     = round(Mem_Percent,     Prec_Percent)\n      MemNoBC_Percent = round(MemNoBC_Percent, Prec_Percent)\n      Dirty_Percent   = round(Dirty_Percent,   Prec_Percent)\n      HP_PercentRam   = round(HP_PercentRam,   Prec_Percent)\n      HP_Used_Percent = round(HP_Used_Percent, Prec_Percent)\n      HP_Rsvd_Percent = round(HP_Rsvd_Percent, Prec_Percent)\n      HP_Free_Percent = round(HP_Free_Percent, Prec_Percent)\n      LowUsed_Percent = round(LowUsed_Percent, Prec_Percent)\n      Slab_Percent    = round(Slab_Percent,    Prec_Percent)\n      PT_Percent      = round(PT_Percent,      Prec_Percent)\n      Shmem_Percent   = round(Shmem_Percent,   Prec_Percent)\n      Percpu_Percent  = round(Percpu_Percent,  Prec_Percent)\n      Swap_Percent    = round(Swap_Percent,    Prec_Percent)\n      \n      MemTotal    = round(MemTotal,    Prec_BytesLo)\n      MemUsed     = round(MemUsed,     Prec_BytesLo)\n      MemUsedNoBC = round(MemUsedNoBC, Prec_BytesLo)\n      Dirty       = round(Dirty,       Prec_BytesHi)\n      HP          = round(HP,          Prec_BytesLo)\n      HP_Used     = round(HP_Used,     Prec_BytesLo)\n      HP_Rsvd     = round(HP_Rsvd,     Prec_BytesLo)\n      HP_Free     = round(HP_Free,     Prec_BytesLo)\n      LowUsed     = round(LowUsed,     Prec_BytesLo)\n      LowTotal    = round(LowTotal,    Prec_BytesLo)\n      Slab        = round(Slab,        Prec_BytesHi)\n      PageTables  = round(PageTables,  Prec_BytesHi)\n      Shmem       = round(Shmem,       Prec_BytesHi)\n      SwapUsed    = round(SwapUsed,    Prec_BytesLo)\n      SwapTotal   = round(SwapTotal,   Prec_BytesLo)\n      THP_Used    = round(THP_Used,    Prec_BytesHi)\n      Percpu      = round(Percpu,      Prec_BytesHi)\n              \n      printf    \"  %sRAM:%s\\n\", H2, H0\n      printf    \"    %s%s%s total ram%s\\n\", H_IMP, MemTotal, Unit, H0\n      printf    \"    %s%s (%s%%) used\\n\", MemUsed, Unit, Mem_Percent\n      printf    \"    %s%s%s (%s%%) used excluding Buffers/Cached%s\\n\", H_IMP, MemUsedNoBC, Unit, MemNoBC_Percent, H0\n      if (Dirty_Percent > 10)\n        printf  \"    %s%s%s (%s%%) dirty%s\\n\", color_warn, Dirty, Unit, Dirty_Percent, H0\n      else\n        printf  \"    %s%s (%s%%) dirty\\n\", Dirty, Unit, Dirty_Percent\n      \n      printf    \"  %sHugePages:%s\\n\", H2, H0\n      if (HugepagesTotal == 0)\n        printf  \"    No ram pre-allocated to HugePages\\n\"\n      else {\n        printf  \"    %s%s%s pre-allocated to HugePages (%s%% of total ram)%s\\n\", H_IMP, HP, Unit, HP_PercentRam, H0\n        printf  \"    In-use: %s%s (%s%%) / Reserved: %s%s (%s%%) / Free: %s%s (%s%%)\\n\", HP_Used, Unit, HP_Used_Percent, HP_Rsvd, Unit, HP_Rsvd_Percent, HP_Free, Unit, HP_Free_Percent\n      }\n      \n      printf    \"  %sTHP:%s\\n\", H2, H0\n      if (THP_Used == 0)\n        printf  \"    No ram allocated to THP\\n\"\n      else {\n        printf  \"    %s%s allocated to THP %s\\n\", THP_Used, Unit, H0\n      }\n\n      printf    \"  %sLowMem/Slab/PageTables/Shmem/Percpu:%s\\n\", H2, H0\n      if (SHOW_Lowmem == 1)\n        printf  \"    %s%s (%s%%) of %s%s LowMem in-use\\n\", LowUsed, Unit, LowUsed_Percent, LowTotal, Unit\n      printf    \"    %s%s (%s%%) of total ram used for Slab\\n\", Slab, Unit, Slab_Percent\n      printf    \"    %s%s (%s%%) of total ram used for PageTables\\n\", PageTables, Unit, PT_Percent\n\n      if (SHOW_Shmem == 1)\n        printf  \"    %s%s (%s%%) of total ram used for Shmem\\n\", Shmem, Unit, Shmem_Percent\n\tprintf  \"    %s%s (%s%%) of total ram used for Percpu\\n\", Percpu, Unit, Percpu_Percent\n      \n      printf    \"  %sSwap:%s\\n\", H2, H0\n      if (SwapTotal == 0)\n        printf  \"    %sNo system swap space configured%s\\n\", color_warn, H0\n      else\n        printf  \"    %s%s (%s%%) used of %s%s total\\n\", SwapUsed, Unit, Swap_Percent, SwapTotal, Unit\n     \n    }\n  ' <\"$meminfo_input\"\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nSTORAGE() {\n  # Local vars:\n  local mpath_input scsi_blacklist bl partitions_input lsblk_input df_input\n  \n  echo -e \"${c[H1]}STORAGE${c[0]}\"\n  \n  # Get mpath input if necessary\n  if [[ $2 != --no-mpath ]]; then\n    if [[ $1 == / && $UID -eq 0 ]]; then\n      # Get multipath input from command, because $1 is system\n      mpath_input=$(multipath -v4 -ll 2>/dev/null)\n    elif [[ -r $1/sos_commands/devicemapper/multipath_-v4_-ll || -r $1/sos_commands/multipath/multipath_-v4_-ll ]]; then\n      # Get multipath input from sosreport file, if present\n      mpath_input=$(cat \"$1\"/sos_commands/{devicemapper,multipath}/multipath_-v4_-ll 2>/dev/null)\n    fi\n  fi\n  \n  # If have good mpath data ..\n  if [[ -n $mpath_input ]] && ! grep -E -q 'no.paths|multipath.conf.*not.exist' <<<\"$mpath_input\"; then\n    echo -e \"${c[H2]}  Multipath:${c[0]}\"\n    \n    # Print out names & sizes of each multipath map\n    grep -E -B1 '^\\[?size=' <<<\"$mpath_input\" |\n      gawk -vRS=\"--\" '\n        {\n          printf \"    %s;%s\\n\",\n            $1, gensub(/.*size=([0-9]+\\.?[0-9]*) ?([MGT]).*/, \"\\\\1  \\\\2iB\", 1)\n        }\n      ' | sort | column -ts\\;\n    \n    # Also, create a blacklist containing all paths to LUNS used for multipath\n    # This will be used to hide certain devices in the plain \"whole disk\" output\n    scsi_blacklist=$(gawk '\n      # The beginning of this regex is quite odd .. we are matching lines starting with:\n      #   \\_  OR  |-  OR  `-\n      \n      /(\\\\_|\\|-|`-) [0-9]+:[0-9]+:[0-9]+:[0-9]+ +[[:graph:]]+ +[0-9]+:/ {\n        printf gensub(/.*:[0-9]+ +([[:graph:]]+) +[0-9].*/, \"\\\\1|\", 1)\n      }\n    ' <<<\"$mpath_input\")\n  fi\n  \n  # If we have linux swraid info, let's use it to expand our blacklist\n  if [[ -r $1/proc/mdstat ]]; then\n    # Append software raid component disks to the blacklist\n    scsi_blacklist=$scsi_blacklist$(grep -s ^md \"$1/proc/mdstat\" | cut -d\\  -f5- | grep -E -o '[[:alpha:]]+' | sort -u | gawk '{printf \"%s|\", $1}')\n  fi\n\n  # If localhost, grab output from lsblk\n  if [[ $1 == / ]]; then\n    lsblk_input=$(lsblk 2>/dev/null)\n  # If directory, assume sosreport and look for lsblk output\n  elif [[ -d $1 ]]; then\n    lsblk_input=$(cat \"$1\"/sos_commands/block/lsblk 2>/dev/null)\n  fi\n\n  # If localhost, grab output from df, exclude autofs as sos does\n  if [[ $1 == / ]]; then\n    df_input=$(df -al -x autofs 2>/dev/null)\n  # If directory, assume sosreport and look for df output\n  elif [[ -d $1 ]]; then\n    df_input=$(cat \"$1\"/sos_commands/filesys/df_-al{,_-x_autofs} 2>/dev/null)\n  fi\n\n  # Yay, let's go.\n  [[ -n $scsi_blacklist ]] && bl=y || { bl=n; scsi_blacklist=NULL; }\n  [[ -f $1 ]] && partitions_input=$1 || partitions_input=$1/proc/partitions\n  echo -e \"  ${c[H2]}Whole Disks from /proc/partitions:${c[0]}\"\n  grep -E -v \"${scsi_blacklist%?}\" \"$partitions_input\" |\n    gawk -vblacklisted=$bl -vblacklist_devcount=$(wc -w <<<\"${scsi_blacklist//|/ }\") -vcolor_grey=\"${c[lgrey]}\" -vH_IMP=\"${c[Imp]}\" -vH3=\"${c[H3]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" '\n      # For starters, we search /proc/partitions for certain types of devices\n      # These block types are from devices.txt in the linux kernel documentation\n      # Updated 2015/08/18 from kernel-doc-3.10.0-229.7.2.el7\n      BEGIN {\n        blkdevs = \"^(\"  \\\n                  \"(vd|hd|sd|mfm|ad|ftl|pd|i2o/hd|nftl|dasd|inftl|ubd|cbd/|iseries/vd|ub|xvd|rfd|ssfdc)[[:alpha:]]+\"  \\\n                  \"|\"  \\\n                  \"(ramdisk|ram|loop|md|rr?om|r?flash|nb|ppdd|amiraid/ar|ataraid/d|nwfs/v|umem/d|drbd|etherd/|emd/|carmel/|mmcblk|blockrom)[0-9]+\"  \\\n                  \"|\"  \\\n                  \"(rd|ida|cciss)/c[0-9]+d[0-9]+\"  \\\n                  \"|\"  \\\n                  \"vx/dsk/.*/.*|vx/dmp/.*\"  \\\n                  \")$\"\n      }\n      $4 ~ blkdevs {\n        \n        # For each thing found, increment the total number of disks\n        numdisks ++\n        \n        # Name a key in the array after the disk and then store its size in GiB there\n        disk[$4] = $3/1024/1024\n        \n        # Also, add to the total sum of disk-storage\n        sum_gb  += disk[$4]\n      }\n      \n      END {\n        # All done with the data-gathering; so print out a summary\n        printf   \"    %s%d disks, totaling %.0f GiB (%.2f TiB)%s\\n\", H_IMP, numdisks, sum_gb, sum_gb/1024, H0\n        \n        # Print a notice if devices were hidden due to blacklist\n        if (blacklisted == \"y\")\n          printf \"    %s(%d multipath/mdraid components hidden)%s\\n\", H_IMP, blacklist_devcount, H0\n        \n        # Some pretty header-fun\n        printf   \"    %s- - - - - - - - - - - - - - - - - - - - -%s\\n\", color_grey, H0\n        printf   \"    %sDisk \\tSize in GiB\\n\", H3\n        printf   \"    ----\\t-----------%s\\n\", H0\n        \n        # Finally, print all the disks & their sizes\n        n = asorti(disk, disk_sorted)\n        for (i = 1; i <= n; i++)\n          printf \"    %s \\t%.0f\\n\", disk_sorted[i], disk[disk_sorted[i]]\n      }\n    '\n\n    if [[ -n $lsblk_input ]]; then\n      echo -e \"\\n  ${c[H2]}Disk layout from lsblk:${c[0]}\"\n      echo -en \"$lsblk_input\" | gawk -vH_IMP=\"${c[Imp]}\" -vH0=\"${c[0]}\" '\n                                  # for lines after the first, print normal output \n                                  (NR > 1) {print}\n                                  # print bold header on the first line\n                                  (NR == 1) {printf \"%s%s%s\\n\", H_IMP, $0, H0}\n                                ' | sed \"s,^,$XSOS_INDENT_H2,\"\n    fi\n    if [[ -n $df_input ]]; then\n      echo -e \"\\n  ${c[H2]}Filesystem usage from df:${c[0]}\"\n      echo -en \"$df_input\" | gawk -vH_IMP=\"${c[Imp]}\" -vH0=\"${c[0]}\" '\n                               # for lines after the first, print normal output \n                               # match filesystems with a \"/\" in the name to avoid noise like tmpfs, cgroup, proc, sysfs, etc\n                               (NR > 1) && ($1 ~ /\\//) {print}\n                               # print bold header on the first line\n                               (NR == 1) {printf \"%s%s%s\\n\", H_IMP, $0, H0}\n                             ' | sed \"s,^,$XSOS_INDENT_H2,\"\n    fi\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nMULTIPATH() {\n  # Local vars:\n  local mpath_input search_cmd mpath_output\n  \n  # If localhost, grab output from multipath\n  if [[ -z $1 ]]; then\n    mpath_input=$(multipath -v4 -ll 2>/dev/null)\n\n  # If directory, assume sosreport and look for multipath output\n  elif [[ -d $1 ]]; then\n    mpath_input=$(cat \"$1\"/sos_commands/{devicemapper,multipath}/multipath_-v4_-ll 2>/dev/null)\n\n  # Otherwise grab file\n  elif [[ -f $1 ]]; then\n    mpath_input=$(<$1)\n  fi\n\n  echo -e \"${c[H1]}DM-MULTIPATH${c[0]}\"\n  \n  # If we have a specific query, we'll use gawk for post-processing\n  # Otherwise simply use cat\n  if [[ -n $XSOS_MULTIPATH_QUERY ]]; then\n    search_cmd=\"gawk -vRS=\\n\\n /$XSOS_MULTIPATH_QUERY/\"\n  else\n    search_cmd=cat\n  fi\n  \n  # Need to parse through `multipath -v4 -ll` output from multiple version of rhel\n  mpath_output=$(gawk '\n    /^[[:graph:]]+ \\([[:alnum:][:punct:]]+\\) *dm-/\n    /^[[:graph:]]+ *dm-/\n    /^\\[?size=/\n    /(\\\\_|\\|-|`-)/\n  ' <<<\"$mpath_input\")\n  \n  if [[ -n $mpath_output ]]; then\n    sed '1!s,^[[:alnum:]].*dm-,\\n&,' <<<\"$mpath_output\" | $search_cmd | sed \"s/^/$XSOS_INDENT_H1/\"\n  else\n    echo -e \"${XSOS_INDENT_H1}${c[lgrey]}[No paths detected]${c[0]}\"\n  fi\n  \n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nLSPCI() {\n  # Local vars:\n  local lspci_input\n  \n  if [[ -z $1 ]]; then\n    lspci_input=$(lspci)\n  elif [[ -f $1 ]]; then\n    lspci_input=$(gawk '{print} /^lspci -n/{exit}' \"$1\" 2>/dev/null)\n  else\n    lspci_input=$(gawk '{print} /^lspci -n/{exit}' \"$1/lspci\" 2>/dev/null)\n  fi\n  \n  _parse_periphs() {\n    local regex=${1}\n    gawk -vH_IMP=\"${c[Imp]}\" -vH2=\"${c[H2]}\" -vH0=\"${c[0]}\" \"\n      /${regex}/\"'{\n        # Save\n        split($1, slot, \":\")\n        $1 = \"\"\n        sub(\" \", \"\")\n        split($0, type, \": \")\n        dev[type[2]] ++\n        if (!(slot[1] SUBSEP type[2] in slots)) {\n          slots[slot[1], type[2]]\n          slotcount[type[2]] ++\n        }\n      }\n      END {\n        for (devtype in dev) {\n          slotc = slotcount[devtype]\n          typec = dev[devtype]\n          ports = \"\"\n          if (typec > 1) {\n            numports = typec/slotc\n            if      (numports == 1) numports = \"single\"\n            else if (numports == 2) numports = \"dual\"\n            else if (numports == 3) numports = \"triple\"\n            else if (numports == 4) numports = \"quad\"\n            ports = \" \"slotc \" \" numports \"-port\"\n          }\n          printf \"   %s%s (%s) %s%s\\n\", H_IMP, ports, typec, H0, devtype\n        }\n      }\n    ' <<<\"$lspci_input\"\n  }\n  \n  echo -e \"${c[H1]}LSPCI${c[0]}\"\n  \n  echo -e \"${c[H2]}  Net:${c[0]}\"\n  _parse_periphs \"${XSOS_LSPCI_NET_REGEX}\"\n  \n  echo -e \"${c[H2]}  Storage:${c[0]}\"\n  _parse_periphs \"${XSOS_LSPCI_STORAGE_REGEX}\"\n  \n  echo -e \"${c[H2]}  VGA:${c[0]}\"\n  gawk '/VGA compatible controller( \\[[0-9]{4}\\])?:/ {$1=$2=$3=$4=\"\"; gsub(/ \\[[0-9]{4}\\]:/,\"\"); print}' <<<\"$lspci_input\"\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\nTEAMING() {\n  # Local vars:\n  local files netscriptsdir teamdevs team_input team_config runner mode active master ports port f s\n\n  # If localhost, find team interfaces...\n  if [[ -z $1 ]]; then\n    teamdevs=$(ip link show type team 2>/dev/null | awk -F ': ' '($1 ~ \"^[0-9]\") {print $2}')\n\n  # If an sosreport, look for sos_commands/teamd/ output...\n  else\n    files=(\"$1\"/sos_commands/teamd/teamdctl_*_state_dump)\n    if [[ ! -r \"${files[0]}\" ]]; then\n      echo -e \"${c[Warn2]}Warning:${c[Warn1]} '/sos_commands/teamd/teamdctl_*_state_dump' files unreadable; skipping teaming check${c[0]}\" >&2\n      echo -en $XSOS_HEADING_SEPARATOR >&2\n      return\n    fi\n    [[ -d \"$1\"/etc/sysconfig/network-scripts ]] && netscriptsdir=\"$1\"/etc/sysconfig/network-scripts\n  fi\n\n  if [[ $XSOS_SCRUB_MACADDR == y ]]; then\n    __scrub_mac() { sed -r 's/[0-9abcdef]/⣿/g' ; }\n  else\n    __scrub_mac() { cat ; }\n  fi\n  \n  echo -e \"${c[H1]}TEAMING${c[0]}\"\n    \n  # The bracket here is like using parens to make a subshell -- allows to capture all stdout\n  {\n    # Header info (\"❚\" is used later by `column` to columnize the output)\n    echo \"  Device❚Runner (mode) ❚ifcfg-File TEAM_CONFIG❚Partner MAC Addr❚Ports (*=active; [n]=AggID)\"\n    echo \"  ========❚=================❚========================❚==================❚===============================\"\n    \n    f=0; for team_input in \"${files[@]}\"; do\n      \n      team_name=$(gawk -F '\"' '/team_device/,/^$/ {if ($2 == \"ifname\") {print $4}}' $team_input)\n      echo -n \"  $team_name❚\"\n      \n      runner=$(gawk -F '\"' '($2 ~ \"runner_name\") {print $4}' $team_input)\n      mode=$(gawk -F '\"' '($2 ~ \"kernel_team_mode_name\") {print $4}' $team_input)\n      echo -n \"$runner ($mode)❚\"\n      \n      team_config=$(gawk '/^TEAM_CONFIG=/' \"$netscriptsdir/ifcfg-${team_name}\" 2>/dev/null | tail -n1 | sed s/TEAM_INPUT=// | tr -d \\\"\\')\n      # Remove backslashes to make the string human-readable\n      team_config=${team_config//\\\\/}\n      [[ -z $team_config ]] && team_config=-\n      echo -n \"$team_config❚\"\n      \n      if [[ ${runner} == \"lacp\" ]]; then\n        # The agg id of the first 'selected' port should be the id of the active aggregation\n        active=$(gawk '/aggregator/,/\\}/ {gsub(/,$/, \"\", $0); if ($0 ~ \"id\" ) {getline selected; if (selected ~ \"true\") {print $NF; exit}}}' $team_input)\n        # The partner mac of the first selected port is the switch mac for the active aggregation \n        partner_mac=$(gawk '/aggregator/,/system/' $team_input | gawk '/\"selected\": true/,/system/' | gawk -F '\"' '($2 ~ \"system\") {print $4; exit}' | __scrub_mac)\n        echo -n \"${partner_mac:--}❚\"\n      else\n        echo -n \"-❚\"\n        active=$(gawk -F '\"' '($2 ~ \"active_port\") {print $4}' $team_input)\n      fi\n      \n      ports=( $(gawk -F '\"' '/ports/,/team_device/ {if ($2 == \"ifname\") {print $4}}' $team_input) )\n      \n      [[ ${#ports[@]} -eq 0 ]] && echo \"[None]\"\n      \n      s=0; until [[ $s -eq ${#ports[@]} ]]; do\n        if [[ ${runner} == \"lacp\" ]]; then\n         agg_id=$(gawk '/'\"${ports[s]}\"'/,/selected}/ {gsub(/,$/, \"\", $0); if ($0 ~ \"id\" ) {print $NF; exit}}' $team_input)\n        fi\n        # First line\n        if [[ $s -eq 0 ]]; then\n          if [[ ${runner} == \"lacp\" ]]; then\n            if [[ $active == $agg_id ]]; then\n              echo -n \"* [$agg_id] ${ports[s]}\"\n            else\n              echo -n \"  [$agg_id] ${ports[s]}\"\n            fi\n          elif [[ $active == ${ports[s]} ]]; then\n            echo -n \"* ${ports[s]}\"\n          else\n            echo -n \"  ${ports[s]}\"\n          fi\n        # Not first line\n        else\n          if [[ ${runner} == \"lacp\" ]]; then\n            if [[ $active == $agg_id ]]; then\n              echo -n \" ❚ ❚ ❚ ❚* [$agg_id] ${ports[s]}\"\n            else\n              echo -n \" ❚ ❚ ❚ ❚  [$agg_id] ${ports[s]}\"\n            fi\n          elif [[ $active == ${ports[s]} ]]; then\n            echo -n \" ❚ ❚ ❚ ❚* ${ports[s]}\"\n          else\n            echo -n \" ❚ ❚ ❚ ❚  ${ports[s]}\"\n          fi\n        fi\n        \n        # There is nothing in an SOS Report which shows the original MAC of a team port :(. But if it did it could go here...\n        # echo \" ($port_mac)\"\n        s=$((s+1))\n        echo\n      done\n    f=$((f+1))\n    [[ $f -lt ${#files[@]} ]] && echo \" ❚ ❚ ❚ ❚- - - - - - - - - - - - - - - -\"\n    done\n  } |\n    column -ts❚ |\n    \n      # And then we need to do some color funness!\n      # This colorizes the first 2 lines with the H2 color and the interfaces with H3\n      gawk -vH0=\"${c[0]}\" -vH2=\"${c[H2]}\" -vH3=\"${c[H3]}\" '\n        {\n          if (NR <= 2) print H2 $0 H0\n          else printf gensub(/(^  [[:graph:]]+ )/,   H3\"\\\\1\"H0, 1)\"\\n\"\n        }' |\n          gawk -vU=\"${c[Up]}\" -vH0=\"${c[0]}\" -vgrey=\"${c[DGREY]}\" '\n            {\n              if (NR <= 2) print\n              else if ($1 == \"-\") print grey $0 H0\n              else printf gensub(/( \\*.*)/,   U\"\\\\1\"H0, 1)\"\\n\"\n            }'\n        \n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\nBONDING() {\n  # Local vars:\n  local files netscriptsdir bond_input f mode bonding_opts active slaves slave s\n  \n  # If passed a file (i.e. xsos --G <file>), use that\n  if [[ -f $1 ]]; then\n    files=($1)\n  # If localhost or sosreport, use that\n  else\n    files=(\"$1\"/proc/net/bonding/*)\n    if [[ ! -r \"${files[0]}\" ]]; then\n      echo -e \"${c[Warn2]}Warning:${c[Warn1]} '/proc/net/bonding/' files unreadable; skipping bonding check${c[0]}\" >&2\n      echo -en $XSOS_HEADING_SEPARATOR >&2\n      return\n    fi\n    [[ -d \"$1\"/etc/sysconfig/network-scripts ]] && netscriptsdir=\"$1\"/etc/sysconfig/network-scripts\n  fi\n  \n  __transform_mode() {\n    # Could be vastly improved by using bashV4 associative array, but KISS for rhel5 peeps\n    if grep -q \"load balancing (round-robin)\" <<<\"$1\"; then\n      mode=\"0 (balance-rr)\"\n    \n    elif grep -q \"fault-tolerance (active-backup)\" <<<\"$1\"; then\n      mode=\"1 (active-backup)\"\n    \n    elif grep -q \"load balancing (xor)\" <<<\"$1\"; then\n      mode=\"2 (balance-xor)\"\n    \n    elif grep -q \"fault-tolerance (broadcast)\" <<<\"$1\"; then\n      mode=\"3 (broadcast)\"\n    \n    elif grep -q \"IEEE 802.3ad Dynamic link aggregation\" <<<\"$1\"; then\n      mode=\"4 (802.3ad)\"\n    \n    elif grep -q \"transmit load balancing\" <<<\"$1\"; then\n      mode=\"5 (balance-tlb)\"\n    \n    elif grep -q \"adaptive load balancing\" <<<\"$1\"; then\n      mode=\"6 (balance-alb)\"\n    \n    else\n      mode=\"unrecognized: $1\"\n    fi\n  }\n  \n  if [[ $XSOS_SCRUB_MACADDR == y ]]; then\n    __scrub_mac() { sed -r 's/[0-9abcdef]/⣿/g' ; }\n  else\n    __scrub_mac() { cat ; }\n  fi\n  \n  echo -e \"${c[H1]}BONDING${c[0]}\"\n    \n  # The bracket here is like using parens to make a subshell -- allows to capture all stdout\n  {\n    # Header info (\"❚\" is used later by `column` to columnize the output)\n    echo \"  Device❚Mode❚ifcfg-File BONDING_OPTS❚Partner MAC Addr❚Slaves (*=active; [n]=AggID)\"\n    echo \"  ========❚=================❚========================❚==================❚===============================\"\n    \n    f=0; for bond_input in \"${files[@]}\"; do\n      \n      echo -n \"  ${bond_input##*/}❚\"\n      \n      __transform_mode \"$(gawk -F: '/Bonding Mode/ {printf $2}' $bond_input | sed -e 's/^ //')\"\n      echo -n \"$mode❚\"\n      \n      bonding_opts=$(gawk '/^BONDING_OPTS=/' \"$netscriptsdir/ifcfg-${bond_input##*/}\" 2>/dev/null | tail -n1 | sed s/BONDING_OPTS=// | tr -d \\\"\\')\n      [[ -z $bonding_opts ]] && bonding_opts=-\n      echo -n \"$bonding_opts❚\"\n      \n      if [[ ${mode::1} == 4 ]]; then\n        active_agg_info=$(gawk 'BEGIN{RS=\"\\n\\n\"} /Active Aggregator Info:/ {print}' $bond_input)\n        partner_mac=$(gawk '/Partner Mac Address:/ {print $4}' <<<\"$active_agg_info\" | __scrub_mac)\n        echo -n \"${partner_mac:--}❚\"\n        active=$(gawk '/Aggregator ID:/ {print $3}' <<<\"$active_agg_info\")\n      else\n        echo -n \"-❚\"\n        active=$(gawk '/Active Slave/ {printf $4}' $bond_input)\n      fi\n      \n      slaves=( $(gawk '/^Slave Interface:/ {print $3}' $bond_input) )\n      \n      [[ ${#slaves[@]} -eq 0 ]] && echo \"[None]\"\n      \n      s=0; until [[ $s -eq ${#slaves[@]} ]]; do\n        if [[ ${mode::1} == 4 ]]; then\n          agg_id=$(gawk 'BEGIN{RS=\"\\n\\n\"} /Slave Interface: '\"${slaves[s]}/\" $bond_input | gawk '/Aggregator ID:/ {print $3}')\n        fi\n        # First line\n        if [[ $s -eq 0 ]]; then\n          if [[ ${mode::1} == 4 ]]; then\n            if [[ $active == $agg_id ]]; then\n              echo -n \"* [$agg_id] ${slaves[s]}\"\n            else\n              echo -n \"  [$agg_id] ${slaves[s]}\"\n            fi\n          elif [[ $active == ${slaves[s]} ]]; then\n            echo -n \"* ${slaves[s]}\"\n          else\n            echo -n \"  ${slaves[s]}\"\n          fi\n        # Not first line\n        else\n          if [[ ${mode::1} == 4 ]]; then\n            if [[ $active == $agg_id ]]; then\n              echo -n \" ❚ ❚ ❚ ❚* [$agg_id] ${slaves[s]}\"\n            else\n              echo -n \" ❚ ❚ ❚ ❚  [$agg_id] ${slaves[s]}\"\n            fi\n          elif [[ $active == ${slaves[s]} ]]; then\n            echo -n \" ❚ ❚ ❚ ❚* ${slaves[s]}\"\n          else\n            echo -n \" ❚ ❚ ❚ ❚  ${slaves[s]}\"\n          fi\n        fi\n        \n        gawk 'BEGIN { RS=\"\\n\\n\" } /Slave Interface: '${slaves[s]}'\\>/' $bond_input |\n          gawk '/Permanent HW addr/ {printf \" (%s)\", $4}' | __scrub_mac\n        s=$((s+1))\n        echo\n      done\n    f=$((f+1))\n    [[ $f -lt ${#files[@]} ]] && echo \" ❚ ❚ ❚ ❚- - - - - - - - - - - - - - - -\"\n    done\n  } |\n    column -ts❚ |\n    \n      # And then we need to do some color funness!\n      # This colorizes the first 2 lines with the H2 color and the interfaces with H3\n      gawk -vH0=\"${c[0]}\" -vH2=\"${c[H2]}\" -vH3=\"${c[H3]}\" '\n        {\n          if (NR <= 2) print H2 $0 H0\n          else printf gensub(/(^  [[:graph:]]+ )/,   H3\"\\\\1\"H0, 1)\"\\n\"\n        }' |\n          gawk -vU=\"${c[Up]}\" -vH0=\"${c[0]}\" -vgrey=\"${c[lgrey]}\" '\n            {\n              if (NR <= 2) print\n              else if ($1 == \"-\") print grey $0 H0\n              else printf gensub(/( \\*.*)/,   U\"\\\\1\"H0, 1)\"\\n\"\n            }'\n        \n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nIPADDR() {\n# I spent a long time wondering how I would end up implementing ip-addr functionality\n# I couldn't think of a lovely elegant gawk-way and in the end I wrote this in 2 hours\n# (And later added brctl, ipv6, scrubbing, MTU)\n# This is probably one of the most expensive of the functions and the one most ripe for\n# being rewritten in Python\n\n  # Require BASH v4\n  if [[ -z ${BASH_VERSINFO} || ${BASH_VERSINFO} -lt 4 ]]; then\n    echo \"The -i/--ip option requires use of BASH associative arrays\" >&2\n    echo \"i.e., BASH v4.0 or higher (RHEL6/Fedora11 and above)\" >&2\n    echo -en ${XSOS_HEADING_SEPARATOR} >&2\n    return\n  fi\n  \n  # Local vars:\n  local ip_a_input brctl_show_input bridge_link_show bridge_list ipdevs bridge interface i i_substr n ipaddr scope alias\n  \n  # Declare our 7 associative arrays:\n  local -A lookup_bridge iface_input slaveof state ipv4 ipv4_alias mtu mac\n  \n  # If localhost, use ip addr\n  if [[ -z $1 ]]; then\n    ip_a_input=$(ip a)\n    bridge_link_show=$(bridge -s -s -d link show 2>/dev/null)\n    brctl_show_input=$(brctl show 2>/dev/null)\n  # If passed a file (i.e. xsos --I <file>), use that\n  elif [[ -f $1 ]]; then\n    ip_a_input=$(<\"${1}\")\n  # Otherwise, use file from $sosroot\n  else\n    ip_a_input=$(cat \"${1}/sos_commands/networking/ip_address\" 2>/dev/null || cat \"${1}/sos_commands/networking/ip_-d_address\" 2>/dev/null)\n    bridge_link_show=$(cat \"${1}/sos_commands/networking/bridge_-s_-s_d_link_show\" 2>/dev/null)\n    brctl_show_input=$(cat \"${1}/sos_commands/networking/brctl_show\" 2>/dev/null)\n  fi\n  \n  # Prepare ip addr input for gawk by separating each interface block\n  ip_a_input=$(sed -e 's,^[0-9]*: ,\\n&,' -e '1s,^,\\n,' <<<\"${ip_a_input}\")\n  \n  # Grab a list of the interface names\n  ipdevs=$(gawk -F: 'BEGIN {RS=\"\\n\\n\"} {print $2}' <<<\"${ip_a_input}\" | grep -E -v 'sit0')\n  \n  # Prepare the list of bridges, using either bridge, or brctl input for gawk by separating each bridge block & filling in empty columns\n  if [[ -n $bridge_link_show ]]; then\n    bridge_list=$(awk '($9 == \"master\") {print $10}' <<<\"${bridge_link_show}\" | sort -u)\n  else\n    brctl_show_input=$(sed -e 1d -e 's,^[[:graph:]],\\n&,' <<<\"${brctl_show_input}\" | sed -r 's,^[[:space:]]+[[:graph:]]+,1 2 3&,')\n    bridge_list=$(gawk 'BEGIN {RS=\"\\n\\n\"} {print $1}' <<<\"${brctl_show_input}\")\n  fi\n  \n  # Populate a dict where each slave interface is key & value is the controlling bridge\n  for bridge in $bridge_list; do\n    if [[ -n $bridge_link_show ]]; then\n      for interface in $(awk '($1 ~ \"^[0-9]\") {print $2}' <<<\"${bridge_link_show}\"); do\n        lookup_bridge[$interface]=${bridge}\n      done\n    else\n      for interface in $(gawk 'BEGIN {RS=\"\\n\\n\"} $1==\"'${bridge}'\"' <<<\"${brctl_show_input}\" | gawk  '{print $4}'); do\n        lookup_bridge[$interface]=${bridge}\n      done\n    fi\n  done\n    \n  # Begin ...\n  echo -e \"${c[H1]}IP$XSOS_IP_VERSION${c[0]}\"\n  \n  # The bracket here is like using parens to make a subshell -- allows to capture all stdout\n  {\n    # Header info (\"❚\" is used later by `column` to columnize the output)\n    if [[ $XSOS_IP_VERSION -eq 6 ]]; then\n      echo \"  Interface❚Master IF❚MAC Address❚MTU❚State❚IPv6 Address❚Scope\"\n      echo \"  =========❚=========❚=================❚======❚=====❚===========================================❚=====\"\n    else\n      echo \"  Interface❚Master IF❚MAC Address❚MTU❚State❚IPv4 Address\"\n      echo \"  =========❚=========❚=================❚======❚=====❚==================\"\n    fi\n    \n    # For each interface ($i) found in ip addr output\n    for i in ${ipdevs}; do\n      \n      # Pull out input for specific interface and save to interface key in array\n      iface_input[$i]=$(gawk \"BEGIN {RS=\\\"\\n\\n\\\"} /^[0-9]+: ${i}:/\" <<<\"${ip_a_input}\")\n\n      # Store a substr of $i with any @<master> removed\n      i_substr=$(expr match \"$i\" '\\([^@]*\\)')\n\n      # Figure out if $i_substr is a slave of some bond / bridge device\n      slaveof[$i]=$(\n        if grep -E -q 'SLAVE|master' <<<\"${iface_input[$i]}\"; then\n          grep -E -o 'master [[:graph:]]+' <<<\"${iface_input[$i]}\" | gawk '{print $2}'\n        elif [[ -n ${lookup_bridge[$i_substr]} ]]; then\n          echo ${lookup_bridge[$i_substr]}\n        else\n          echo \"-\"\n        fi\n      )\n      \n      # Get MTU for $i\n      mtu[$i]=$(grep -E -o ' mtu [0-9]+' <<<\"${iface_input[$i]}\" | gawk '{print $2}')\n      \n      # Get up/down state for $i\n      state[$i]=$(grep -q \"${i}: <.*,UP.*>\"  <<<\"${iface_input[$i]}\" && echo up || echo DOWN)\n      \n      # Get macaddr for $i (don't show if all zeros)\n      mac[$i]=$(grep -E -q 'link/[[:graph:]]+ ..:..:..:..:..:..' <<<\"${iface_input[$i]}\" &&\n                gawk -v scrub=\"${XSOS_SCRUB_MACADDR}\" '\n                    /link\\/[[:graph:]]+ ..:..:..:..:..:../ {\n                        if ($2 == \"00:00:00:00:00:00\") print \"-\"\n                        else if (scrub == \"y\") print \"⣿⣿:⣿⣿:⣿⣿:⣿⣿:⣿⣿:⣿⣿\"\n                        else print $2\n                    }\n                ' <<<\"${iface_input[$i]}\" || echo \"-\")\n      \n      if [[ ${XSOS_IP_VERSION} -eq 6 ]]; then\n        \n        # If $i has an ipv6 address, time to figure out what it is\n        if grep -q \"inet6\" <<<\"${iface_input[$i]}\"; then\n          \n          # We could have more than one ipv6addr...\n          # So we need to set up a counter and do a loop\n          n=0; while read ipaddr scope; do\n            if [[ $n -eq 0 ]]; then\n              echo \"  ${i}❚${slaveof[$i]}❚${mac[$i]}❚${mtu[$i]}❚${state[$i]}❚${ipaddr}❚${scope}\"\n            else\n              echo \"   ❚ ❚ ❚ ❚ ❚${ipaddr}❚${scope}\"\n            fi\n            ((n++))\n          done < <(gawk -v scrub=\"${XSOS_SCRUB_IP_HN}\" '\n                       /inet6/ {\n                           if (scrub == \"y\") print \"⣿⣿⣿⣿:⣿⣿⣿⣿:⣿⣿⣿⣿:⣿⣿⣿⣿:⣿⣿⣿⣿:⣿⣿⣿⣿:⣿⣿⣿⣿:⣿⣿⣿⣿/⣿⣿⣿ \" $4\n                           else print $2,$4\n                       }\n                   ' <<<\"${iface_input[$i]}\")\n        \n        # Otherwise, print out all info with ipaddr set to \"-\"\n        else\n          echo \"  ${i}❚${slaveof[$i]}❚${mac[$i]}❚${mtu[$i]}❚${state[$i]}❚-❚-\"\n        fi\n        \n      else\n      \n        # If $i has an ipv4 address, time to figure out what it is\n        if grep -q \"inet .* ${i%@*}\\$\" <<<\"${iface_input[$i]}\"; then\n          \n          # We could have more than one non-alias ip4addr...\n          # So we need to set up a counter and do a loop\n          n=0; while read ipaddr; do\n            if [[ ${n} -eq 0 ]]; then\n              echo \"  ${i}❚${slaveof[$i]}❚${mac[$i]}❚${mtu[$i]}❚${state[$i]}❚${ipaddr}\"\n            else\n              echo \"   ❚ ❚ ❚ ❚ ❚${ipaddr}\"\n            fi\n            ((n++))\n          done < <(gawk -v scrub=\"${XSOS_SCRUB_IP_HN}\" \"\n                        /inet .* ${i%@*}\\$/ {\n                            if (scrub == \\\"y\\\") print \\\"⣿⣿⣿.⣿⣿⣿.⣿⣿⣿.⣿⣿⣿/⣿⣿\\\"\n                            else print \\$2\n                        }\n                   \" <<<\"${iface_input[$i]}\")\n        \n        # Otherwise, print out all info with ipaddr set to \"-\"\n        else\n          echo \"  ${i}❚${slaveof[$i]}❚${mac[$i]}❚${mtu[$i]}❚${state[$i]}❚-\"\n          # ... And Continue on to the next interface, i.e., skip looking for aliases\n          continue\n        fi\n\n        # If $i had an ipv4 addr, it's ALIAS time!\n        if grep -q \"inet .* ${i}:\" <<<\"${iface_input[$i]}\"; then\n        \n          # For each \"alias\" (additional address) found ...\n          for alias in $(gawk \"/inet .* ${i}:/ {print \\$NF}\" <<<\"${iface_input[$i]}\" | sort -u); do\n            ipv4_alias[$alias]=$(gawk -v scrub=\"${XSOS_SCRUB_IP_HN}\" \"\n                                    /inet .* ${alias}\\$/ {\n                                        if (scrub == \\\"y\\\") print \\\"⣿⣿⣿.⣿⣿⣿.⣿⣿⣿.⣿⣿⣿/⣿⣿\\\"\n                                        else print \\$2\n                                    }\n                                 \" <<<\"${iface_input[$i]}\" | sed -e '1!s/.*/   ❚ ❚ ❚ ❚ ❚&/')\n            # The sed nonsense at the end of the above line allows for multiple new-style global addresses on top of an old-style alias (https://github.com/ryran/xsos/issues/103)\n            # Thankfully we don't need to do a while loop like above because in the case of aliases we don't need to display mtu, state, mac\n\n            # ... Print out a new line with its ipv4 addr\n            # No extra columns at the end needed because they're added by sed in above line\n            echo \"  ${alias}❚ ❚ ❚ ❚ ❚${ipv4_alias[$alias]}\"\n          done\n        fi\n      \n      fi\n      \n    done\n  } |\n  \n    # All output from above needs to be columnized\n    column -ts❚ |\n    \n      # And then we need to do some color funness!\n      # This colorizes the first 2 lines with the H2 color and the interfaces with H3\n      # Plus DOWN interfaces with Down color and up interfaces with Up color\n      gawk -vH0=\"${c[0]}\" -vH2=\"${c[H2]}\" -vH3=\"${c[H3]}\" -vU=\"${c[Up]}\" -vD=\"${c[Down]}\" '\n        {\n          if (NR <= 2) printf H2 $0\n          else {\n            if ($5 == \"DOWN\") printf D $0\n            else if ($0 ~ /^  [[:graph:]]/) printf gensub(/(^  [[:graph:]]+ )/,  H3\"\\\\1\"U, 1)\n            else printf U $0\n          }\n          print H0\n        }'\n  echo -en ${XSOS_HEADING_SEPARATOR}\n}\n\n\nETHTOOL() {\n  # Local vars:\n  local changedir ethdevs i errsfound count ethindent multiqueue_header\n  \n  # If localhost, grab interfaces from /sys\n  if [[ -z $1 ]]; then\n    ethdevs=$(ls /sys/class/net | grep -E -v 'lo|sit0|bonding_masters')\n    # Setup local functions for ethtool & ethtool -i & ethtool -S\n    __ethtool()   { ethtool $1; }\n    __ethtool_i() { ethtool -i $1; }\n    __ethtool_S() { ethtool -S $1 2>&1; }\n    __ethtool_g() { ethtool -g $1 2>&1; }\n    \n  # If sosreport, determine interfaces from ethtool_<iface> files\n  else\n    changedir=1\n    pushd \"$1\"/sos_commands/networking &>/dev/null\n    ethdevs=$(ls ethtool_[[:alpha:]]* | cut -d_ -f2-)\n    # Setup local functions for ethtool & ethtool -i & ethtool -S\n    __ethtool()   { cat ethtool_$1; }\n    __ethtool_i() { [[ -r ethtool_-i_$1 ]] && cat ethtool_-i_$1; }\n    __ethtool_S() { [[ -r ethtool_-S_$1 ]] && cat ethtool_-S_$1 || echo \"     Missing ethtool_-S file\"; }\n    __ethtool_g() { [[ -r ethtool_-g_$1 ]] && cat ethtool_-g_$1; }\n  fi\n  \n  # If have ethdevs to work on ...\n  if [[ -n $ethdevs ]]; then\n    echo -e \"${c[H1]}ETHTOOL${c[0]}\"\n    echo -e \"${c[H2]}${XSOS_INDENT_H1}Interface Status:${c[0]}\"\n    for i in $ethdevs; do\n      echo -e \"${XSOS_INDENT_H2}$i❚$(__ethtool_i $i |\n      gawk '\n        BEGIN { pci = \"PCI UNKNOWN\" }\n        /^bus-info:/ { pci = $2 }\n        END { printf pci }\n      '\n      )❚$(__ethtool $i |\n      gawk '\n        /Link detected:/    { link = $3; sub(/yes/, \"up\", link); sub(/no/, \"DOWN\", link) }\n        /Speed:/            { spd = $2 }\n        /Duplex:/           { dup = tolower($2) }\n        /Auto-negotiation:/ { aneg = $2; sub(/on/, \"Y\", aneg); sub(/off/, \"N\", aneg) }\n        END {\n          if (link == \"up\" && spd != \"\")\n            linkdetails = \" \"spd\" \"dup\" (autoneg=\"aneg\")\"\n          else if (link == \"\")\n            link = \"UNKNOWN\"\n          printf \"link=%s%s\", link, linkdetails\n        }\n      '\n      )❚$(__ethtool_g $i |\n      gawk '\n        /Pre-set maximums:/          { getline; if ($1 == \"RX:\") rx_max=$2 }\n        /Current hardware settings:/ { getline; if ($1 == \"RX:\") rx_now=$2 }\n        END {\n          if (rx_now == \"\" && rx_max == \"\") {\n            print \"rx ring UNKNOWN\"\n            exit\n          }\n          else if (rx_now == \"\")\n            rx_now = \"?\"\n          else if (rx_max == \"\")\n            rx_max = \"?\"\n          printf \"rx ring %s/%s\\n\", rx_now, rx_max\n        }\n      '\n      )❚$(__ethtool_i $i |\n      gawk -F: '\n        BEGIN { driver=\"UNKNOWN\"; drv_vers=\"\"; fw_vers=\"UNKNOWN\" }\n        /^driver:/           { if ($2 !~ /^ *$/) driver=$2;   sub(/^ /, \"\", driver) }\n        /^version:/          { if ($2 !~ /^ *$/) drv_vers=$2; sub(/^ /, \" v\", drv_vers) }\n        /^firmware-version:/ { if ($2 !~ /^ *$/) fw_vers=$2;  sub(/^ /, \"\", fw_vers) }\n        END { printf \"drv %s%s / fw %s\", driver, drv_vers, fw_vers }\n      '\n      )\"\n    done | column -ts❚ |\n      gawk -vH0=\"${c[0]}\" -vU=\"${c[Up]}\" -vD=\"${c[Down]}\" -vE=\"${c[Warn1]}\" '\n        /link=DOWN/     { print D $0 H0 }\n        /link=up/       { print U $0 H0 }\n        /link=UNKNOWN/  { print E $0 H0 }\n      '\n      \n    echo -e \"${c[H2]}${XSOS_INDENT_H1}Interface Errors:${c[0]}\"\n    echo -en \"${c[Warn1]}\"\n    multiqueue_header='^[[:space:]]+[RT]x.Queue#:'\n    for i in $ethdevs; do\n      errsfound=\n      ethindent=$(tr '[[:graph:]]'   ' ' <<<\"$i \")\n      if __ethtool_S $i | [[ $(gawk \"$XSOS_ETHTOOL_ERR_REGEX\" | wc -l) -gt 0 ]]; then\n        [[ -n $count ]] && echo -e \"${XSOS_INDENT_H2}${c[lgrey]}- - - - - - - - - - - - - - - - - - -\"\n        echo -en \"${c[Warn1]}\"\n        errsfound=$(__ethtool_S $i |\n          tac |\n            gawk \"\n              BEGIN { found = 0 }\n              $XSOS_ETHTOOL_ERR_REGEX {\n                print ; found = 1\n              }\n              /$multiqueue_header/ {\n                if (found == 1) {\n                  print ; found = 0\n                }\n              }\n            \" |\n              tac\n        )\n        sed -e \"1s/[[:space:]][[:graph:]]/$i &/\" -e \"1!s/^/$ethindent/\" <<<\"$errsfound\"\n        count+=1\n      fi\n    done\n    [[ -z $count ]] && echo -e \"${XSOS_INDENT_H2}${c[lgrey]}[None]\"\n    echo -en \"${c[0]}\"\n    \n    [[ -n $changedir ]] && popd &>/dev/null\n  fi\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nSOFTIRQ() {\n  # Local vars:\n  local softirq_input_file suffix= backlog= budget=\n  \n  if [[ -f $1 ]]; then\n    softirq_input_file=$1\n  else\n    softirq_input_file=$1/proc/net/softnet_stat\n    if [[ ! -r $softirq_input_file ]]; then\n      echo -e \"${c[Warn2]}Warning:${c[Warn1]} '/proc/net/softnet_stat' unreadable; skipping softirq check${c[0]}\" >&2\n      echo -en $XSOS_HEADING_SEPARATOR >&2\n      return\n    fi\n    backlog=$(cat \"$1\"/proc/sys/net/core/netdev_max_backlog 2>/dev/null) \\\n      && backlog=\" (Current value: net.core.netdev_max_backlog = $backlog)\" \\\n      || backlog=\" (However, proc/sys/net/core/netdev_max_backlog is missing)\"\n    budget=$(cat \"$1\"/proc/sys/net/core/netdev_budget 2>/dev/null) \\\n      && budget=\" (Current value: net.core.netdev_budget = $budget)\" \\\n      || budget=\" (However, proc/sys/net/core/netdev_budget is missing)\"\n  fi\n  \n  echo -e \"${c[H1]}SOFTIRQ${c[0]}\"\n  \n  gawk '{if (strtonum(\"0x\" $2) > 0) exit 177}' \"$softirq_input_file\"\n  \n  if [[ $? -eq 177 ]]; then\n    echo -e \"${XSOS_INDENT_H1}${c[Warn1]}Backlog max has been reached, consider reviewing backlog tunable.${c[0]}$backlog\"\n  else\n    echo -e \"${XSOS_INDENT_H1}Backlog max is sufficient${c[0]}$backlog\"\n  fi\n  \n  \n  gawk '{if (strtonum(\"0x\" $3) > 0) exit 177}' \"$softirq_input_file\"\n  if [[ $? -eq 177 ]]; then\n    echo -e \"${XSOS_INDENT_H1}${c[Warn1]}Budget is not sufficient, consider reviewing budget tunable.${c[0]}$budget\"\n  else\n    echo -e \"${XSOS_INDENT_H1}Budget is sufficient${c[0]}$budget\"\n  fi\n  echo \"${XSOS_INDENT_H1}(see https://access.redhat.com/solutions/1241943)\"\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nNETDEV() {\n  # Local vars:\n  local netdev_input_file\n  \n  [[ -f $1 ]] && netdev_input_file=$1 || netdev_input_file=$1/proc/net/dev\n  \n  echo -e \"${c[H1]}NETDEV${c[0]}\"\n  tail -n+3 \"$netdev_input_file\" | grep -E -v 'lo:|sit0:' | sed 's,:, ,' |\n    gawk -vu=$(tr '[:lower:]' '[:upper:]' <<<$XSOS_NET_UNIT) '\n      function round(num, places) {\n        places = 10 ^ places\n        return int(num * places + .5) / places\n      }\n\n      {\n        # Set variables based on fields\n        \n        Interface[$1] = $1\n        RxBytes[$1]   = $2\n        RxPackets[$1] = $3\n        RxErrs[$1]    = $4\n        RxDrop[$1]    = $5\n        RxFifo[$1]    = $6\n        RxFram[$1]    = $7\n        RxComp[$1]    = $8\n        RxMult[$1]    = $9\n        RxTotal[$1]   = $3 + $4 + $5 + $6 + $7 + $8 + $9\n        TxBytes[$1]   = $10\n        TxPackets[$1] = $11\n        TxErrs[$1]    = $12\n        TxDrop[$1]    = $13\n        TxFifo[$1]    = $14\n        TxCols[$1]    = $15\n        TxCarr[$1]    = $16\n        TxComp[$1]    = $17\n        TxTotal[$1]   = $11 + $12 + $13 + $14 + $15 + $16 + $17\n        \n        # Calculate percentages only if rx/tx packets gt 0\n        \n        if  (RxTotal[$1] > 0) {\n          if  ($4 > 0) RxErrsPercent[$1] = \"(\" round($4  * 100 / RxTotal[$1],  0) \"%)\"\n          if  ($5 > 0) RxDropPercent[$1] = \"(\" round($5  * 100 / RxTotal[$1],  0) \"%)\"\n          if  ($6 > 0) RxFifoPercent[$1] = \"(\" round($6  * 100 / RxTotal[$1],  0) \"%)\"\n          if  ($7 > 0) RxFramPercent[$1] = \"(\" round($7  * 100 / RxTotal[$1],  0) \"%)\"\n          if  ($8 > 0) RxCompPercent[$1] = \"(\" round($8  * 100 / RxTotal[$1],  0) \"%)\"\n          if  ($9 > 0) RxMultPercent[$1] = \"(\" round($9  * 100 / RxTotal[$1],  0) \"%)\"\n        }\n        if (TxTotal[$1] > 0) {\n          if ($12 > 0) TxErrsPercent[$1] = \"(\" round($12 * 100 / TxTotal[$1], 0) \"%)\"\n          if ($13 > 0) TxDropPercent[$1] = \"(\" round($13 * 100 / TxTotal[$1], 0) \"%)\"\n          if ($14 > 0) TxFifoPercent[$1] = \"(\" round($14 * 100 / TxTotal[$1], 0) \"%)\"\n          if ($15 > 0) TxColsPercent[$1] = \"(\" round($15 * 100 / TxTotal[$1], 0) \"%)\"\n          if ($16 > 0) TxCarrPercent[$1] = \"(\" round($16 * 100 / TxTotal[$1], 0) \"%)\"\n          if ($17 > 0) TxCompPercent[$1] = \"(\" round($17 * 100 / TxTotal[$1], 0) \"%)\"\n        }\n        \n        # Figure out what number to divide by to end up with KiB, MiB, GiB, or TiB\n        \n        if      (u == \"K\") { bytes_divisor = 1024 }\n        else if (u == \"M\") { bytes_divisor = 1024 ** 2 ; packets_divisor = 1000      ; Packets_Unit = \" k\" }\n        else if (u == \"G\") { bytes_divisor = 1024 ** 3 ; packets_divisor = 1000 ** 2 ; Packets_Unit = \" M\" }\n        else if (u == \"T\") { bytes_divisor = 1024 ** 4 ; packets_divisor = 1000 ** 2 ; Packets_Unit = \" M\" }\n        \n        # Figure out decimal precision\n        \n        if (u == \"T\")\n          # For T, round Bytes field to nearest hundredth (.nn)\n          Precision_Bytes = 2\n          \n        else if (u == \"G\")\n          # For G, round Bytes field to nearest tenth (.n)\n          Precision_Bytes = 1\n          \n        else\n          # For K/M, keep Bytes as whole numbers\n          Precision_Bytes = 0\n        \n        # Never show decimal for Packets\n        Precision_Pckts = 0\n        \n        # If unit is anything but bytes, perform the necessary division\n        \n        if (u == \"K\" || u == \"M\" || u == \"G\" || u == \"T\") {\n          U = u\"iB\"\n          RxBytes[$1] /= bytes_divisor\n          TxBytes[$1] /= bytes_divisor\n        }\n        \n        # If unit is MiB, GiB, or TiB, perform division on packets as well\n        \n        if (u == \"M\" || u == \"G\" || u == \"T\") {\n          RxPackets[$1] /= packets_divisor\n          TxPackets[$1] /= packets_divisor\n        }\n        \n        # Now that we have our numbers, time to do rounding\n        \n        RxBytes[$1]   = round(RxBytes[$1],   Precision_Bytes)\n        TxBytes[$1]   = round(TxBytes[$1],   Precision_Bytes)\n        RxPackets[$1] = round(RxPackets[$1], Precision_Pckts)\n        TxPackets[$1] = round(TxPackets[$1], Precision_Pckts)\n        \n        # If U (pretty printing unit) was never set, it should be bytes\n        \n        if (U == \"\")\n          U = \"B\"\n      }\n      \n      END {\n        print \"  Interface❚Rx\"U\"ytes❚RxPackets❚RxErrs❚RxDrop❚RxFifo❚RxComp❚RxFrame❚RxMultCast\"\n        print \"  =========❚=========❚=========❚======❚======❚======❚======❚=======❚==========\"\n        n = asorti(Interface, IF)\n        for (i = 1; i <= n; i++) {\n          printf \"  %s❚\",   IF[i]\n          printf \"%s❚\",     RxBytes[IF[i]]\n          printf \"%s%s❚\",   RxPackets[IF[i]], Packets_Unit\n          printf \"%s %s❚\",  RxErrs[IF[i]],    RxErrsPercent[IF[i]]\n          printf \"%s %s❚\",  RxDrop[IF[i]],    RxDropPercent[IF[i]]\n          printf \"%s %s❚\",  RxFifo[IF[i]],    RxFifoPercent[IF[i]]\n          printf \"%s %s❚\",  RxComp[IF[i]],    RxCompPercent[IF[i]]\n          printf \"%s %s❚\",  RxFram[IF[i]],    RxFramPercent[IF[i]]\n          printf \"%s %s\", RxMult[IF[i]],    RxMultPercent[IF[i]]\n          printf \"\\n\"\n        }\n        print \"  Interface❚Tx\"U\"ytes❚TxPackets❚TxErrs❚TxDrop❚TxFifo❚TxComp❚TxColls❚TxCarrier \"\n        print \"  =========❚=========❚=========❚======❚======❚======❚======❚=======❚==========\"\n        n = asorti(Interface, IF)\n        for (i = 1; i <= n; i++) {\n          printf \"  %s❚\",   IF[i]\n          printf \"%s❚\",     TxBytes[IF[i]]\n          printf \"%s%s❚\",   TxPackets[IF[i]], Packets_Unit\n          printf \"%s %s❚\",  TxErrs[IF[i]],    TxErrsPercent[IF[i]]\n          printf \"%s %s❚\",  TxDrop[IF[i]],    TxDropPercent[IF[i]]\n          printf \"%s %s❚\",  TxFifo[IF[i]],    TxFifoPercent[IF[i]]\n          printf \"%s %s❚\",  TxComp[IF[i]],    TxCompPercent[IF[i]]\n          printf \"%s %s❚\",  TxCols[IF[i]],    TxColsPercent[IF[i]]\n          printf \"%s %s\",  TxCarr[IF[i]],    TxCarrPercent[IF[i]]\n          printf \"\\n\"\n        }\n      }\n    ' | column -ts❚ |\n      gawk -vH0=\"${c[0]}\" -vH2=\"${c[H2]}\" -vH3=\"${c[H3]}\" -vGREY=\"${c[lgrey]}\" '\n        {\n          if (NR <= 2)\n            print H2 $0 H0\n          else if ($1 == \"Interface\") {\n            print GREY \"  - - - - - - - - - - - - - - - - -\" H0\n            print H2 $0 H0\n          }\n          else if ($1 == \"=========\")\n            print H2 $0 H0\n          else\n            printf gensub(/(^  [[:graph:]]+ )/,   H3\"\\\\1\"H0, 1)\"\\n\"\n        }'\n\n# Disabled this cuz ... well, it took up space and I had no evidence that anyone uses it\n  if [[ -d $1 ]]; then\n    echo -en $XSOS_HEADING_SEPARATOR\n    echo -e \"${c[H1]}SOCKSTAT${c[0]}\"\n    gawk -vS=\"  \" -vH3=\"${c[H3]}\" -vH0=\"${c[0]}\" '\n      { printf gensub(/^(.*:)/, S H3\"\\\\1\"H0, 1)\"\\n\" }' <\"$1/proc/net/sockstat\"\n  fi\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nCHECK_TAINTED() {\n  # Local vars:\n  local quote sys_tainted_status sys_kernel_version taint_states taintbit taintval indent t\n  \n  [[ $1 == --quote ]] && quote=1 || quote=\n  \n  sys_tainted_status=$(<\"$2/proc/sys/kernel/tainted\")\n  sys_kernel_version=$(<\"$2/proc/sys/kernel/osrelease\")\n  \n  if [[ -n $quote ]]; then\n    echo -en \"\\\"$sys_tainted_status\\\"${c[0]}\"\n  else\n    echo -en \"$sys_tainted_status${c[0]}\"\n  fi\n\n  if [[ $sys_tainted_status == 0 ]]; then\n    echo \"  (kernel untainted)\"\n    return\n  else\n    echo \"  (see https://access.redhat.com/solutions/40594)\"\n  fi\n    \n  case $3 in\n    H0) indent=                ;;\n    H1) indent=$XSOS_INDENT_H1 ;;\n    H2) indent=$XSOS_INDENT_H2 ;;\n    H3) indent=$XSOS_INDENT_H3\n  esac\n  \n  # See /usr/share/doc/kernel-doc*/Documentation/sysctl/kernel.txt\n  #     kernel source: linux/kernel/panic.c\n  #     kernel source: include/linux/kernel.h\n  #     https://access.redhat.com/solutions/40594\n\n  t[0]=\"PROPRIETARY_MODULE: Proprietary module has been loaded\"\n  t[1]=\"FORCED_MODULE: Module has been forcibly loaded\"\n  t[2]=\"UNSAFE_SMP: SMP with CPUs not designed for SMP\"\n  t[3]=\"FORCED_RMMOD: User forced a module unload\"\n  t[4]=\"MACHINE_CHECK: System experienced a machine check exception\"\n  t[5]=\"BAD_PAGE: System has hit bad_page\"\n  if grep -qs '^2\\.6\\.18-.*el5' <<<\"$sys_kernel_version\"; then\n    t[6]=\"UNSIGNED_MODULE: Unsigned module has been loaded (RHEL5-specific)\"\n  else\n    t[6]=\"USER: Userspace-defined naughtiness (RHEL6+)\"\n  fi\n  t[7]=\"DIE: Kernel has oopsed before\"\n  t[8]=\"OVERRIDDEN_ACPI_TABLE: ACPI table overridden\"\n  t[9]=\"WARN: Taint on warning\"\n  t[10]=\"CRAP: Modules from drivers/staging are loaded\"\n  t[11]=\"FIRMWARE_WORKAROUND: Working around severe firmware bug\"\n  t[12]=\"OOT_MODULE: Out-of-tree module has been loaded\"\n  t[13]=\"UNSIGNED_MODULE: Unsigned module has been loaded\"\n  t[14]=\"SOFTLOCKUP: A soft lockup has previously occurred\"\n  t[15]=\"LIVEPATCH: Kernel has been live patched\"\n  t[16]=\"16: undefined\"\n  t[17]=\"17: undefined\"\n  t[18]=\"18: undefined\"\n  t[19]=\"19: undefined\"\n  t[20]=\"20: undefined\"\n  t[21]=\"21: undefined\"\n  t[22]=\"22: undefined\"\n  t[23]=\"23: undefined\"\n  t[24]=\"24: undefined\"\n  t[25]=\"25: undefined\"\n  t[26]=\"26: undefined\"\n  t[27]=\"BIT_BY_ZOMBIE: Kernel booted with OMGZOMBIES param\"\n  t[28]=\"HARDWARE_UNSUPPORTED: Hardware is unsupported\"\n  t[29]=\"TECH_PREVIEW: Technology Preview code is loaded\"\n  t[30]=\"RESERVED30: undefined\"\n  t[31]=\"RESERVED31: undefined\"\n  \n  taint_states=$(\n    for taintbit in $(sed 's, ,\\n,g' <<<\"${!t[@]}\" | tac); do\n      taintval=$((2**taintbit))\n      if [[ $sys_tainted_status -gt $taintval ]]; then\n        echo $taintbit\n        sys_tainted_status=$((sys_tainted_status-taintval))\n      elif [[ $sys_tainted_status == $taintval ]]; then\n        echo $taintbit\n        break\n      fi\n    done\n  )\n  \n  for taintbit in $(tac <<<\"$taint_states\"); do\n    printf \"$indent%2s  ${t[$taintbit]}\\n\" $taintbit\n  done\n}\n\n\nSYSCTL() {\n  # Local vars:\n  local pgsz hpgsz\n  \n  # VM PageSize (don't know how to find this from a sosreport, but I doubt that will often be a problem)\n  [[ $1 == / ]] && pgsz=$(($(getconf PAGESIZE)/1024)) || pgsz=4     # Saved as KiB\n  \n  # HugePage size\n  hpgsz=$(gawk '/Hugepagesize:/{print $2/1024}' <\"$1/proc/meminfo\")  # Saved as MiB\n  \n  __P() {\n    echo -e \"$XSOS_INDENT_H2${c[H3]}${1#*.} ${c[H4]}$2${c[H3]}=${c[Imp]}  $( [[ ! -f \"$sosroot\"/proc/sys/${1//.//} ]] && echo -e \"${c[Warn1]}{sysctl not present}\" || echo \\\"$(<\"$sosroot\"/proc/sys/${1//.//})\\\" )${c[0]}\"\n  }\n  \n  __Pa() {\n    echo -e \"$XSOS_INDENT_H2${c[H3]}${1#*.} ${c[H4]}$2${c[H3]}=${c[Imp]}  $( [[ ! -f \"$sosroot\"/proc/sys/${1//.//} ]] && echo -e \"${c[Warn1]}{sysctl not present}\" || gawk -vH0=\"${c[0]}\" \"$3\" \"$4\" <\"$sosroot\"/proc/sys/${1//.//} )${c[0]}\"\n  }\n  \n  echo -e \"${c[H1]}SYSCTLS${c[0]}\"\n  if grep -qsw rescue \"$1/proc/cmdline\"; then\n    echo -e \"${c[Warn2]}  WARNING: RESCUE MODE DETECTED${c[0]}\"\n    echo -e \"${c[Warn1]}  sysctls below reflect rescue env; inspect sysctl.conf manually${c[0]}\"\n  fi\n  \n  echo -e \"$XSOS_INDENT_H1${c[H2]}kernel.${c[0]}\"\n  [[ $XSOS_SCRUB_IP_HN == y ]] \\\n    && echo -e \"$XSOS_INDENT_H2${c[H3]}hostname =  ${c[Warn2]}HOSTNAME SCRUBBED${c[0]}\" \\\n    || __P kernel.hostname\n  __P kernel.osrelease\n  echo -e \"$XSOS_INDENT_H2${c[H3]}tainted =${c[Imp]}  $(CHECK_TAINTED --quote \"$1\" H3)\"\n  __P kernel.random.boot_id\n  __P kernel.random.entropy_avail \"[bits] \"\n  __P kernel.hung_task_panic \"[bool] \"\n  __Pa kernel.hung_task_timeout_secs \"\"  '{if ($1>0) printf \"\\\"%s\\\"%s  (secs task must be D-state to trigger)\", $1, H0; else printf \"\\\"0\\\"%s  (khungtaskd disabled)\", H0}'\n  __Pa kernel.hung_task_warnings \"[num_warnings] \"  '{if ($1==-1) printf \"\\\"-1\\\"%s  (will report infinite number of warnings)\", H0; else if ($1==0) printf \"\\\"0\\\"%s  (warnings disabled, either intentionally or after original num_warnings reached)\", H0; else printf \"\\\"%s\\\"%s  (will report %s [more] warnings)\", $1, H0, $1}'\n  __P kernel.msgmax \"[bytes] \"\n  __P kernel.msgmnb \"[bytes] \"\n  __P kernel.msgmni \"[msg queues] \"\n  __Pa kernel.panic \"[secs] \"  '{if ($1>0) printf \"\\\"%s\\\"%s  (secs til autoreboot after panic)\", $1, H0; else printf \"\\\"0\\\"%s  (no autoreboot on panic)\", H0}'\n  __P kernel.panic_on_oops \"[bool] \"\n  __P kernel.nmi_watchdog \"[bool] \"\n  __P kernel.panic_on_io_nmi \"[bool] \"\n  __P kernel.panic_on_unrecovered_nmi \"[bool] \"\n  __P kernel.unknown_nmi_panic \"[bool] \"\n  __P kernel.panic_on_stackoverflow \"[bool] \"\n  __P kernel.panic_on_warn \"[bool] \"\n  __P kernel.softlockup_panic \"[bool] \"\n  __P kernel.softlockup_thresh \"[secs] \"\n  __P kernel.pid_max\n  __P kernel.threads-max\n  __Pa kernel.sem \"[array] \"  \"-vS=$XSOS_INDENT_H3\"  '{printf \"\\\"%s  %s  %s  %s\\\"%s\\n\", $1,$2,$3,$4,H0; printf \"%sSEMMSL (max semaphores per array) =  %d\\n%sSEMMNS (max sems system-wide)     =  %d\\n%sSEMOPM (max ops per semop call)   =  %d\\n%sSEMMNI (max number of sem arrays) =  %d\\n\", S,$1, S,$2, S,$3, S,$4}'\n  __Pa kernel.shmall \"[$pgsz-KiB pages] \"  \"-vPGSZ=$pgsz\"  '{printf \"\\\"%s\\\"%s  (%.1f GiB max total shared memory)\", $1, H0, $1*PGSZ/1024/1024}'\n  __Pa kernel.shmmax \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%.2f GiB max segment size)\", $1, H0, $1/1024/1024/1024}'\n  __Pa kernel.shmmni \"[segments] \"  '{printf \"\\\"%s\\\"%s  (max number of segs)\", $1, H0}'\n  __Pa kernel.sysrq \"[bitmask] \"  '{if ($1==0) printf \"\\\"0\\\"%s  (disallowed)\", H0; else if ($1==1) printf \"\\\"1\\\"%s  (all SysRqs allowed)\", H0; else printf \"\\\"%s\\\"%s  (see proc man page)\", $1, H0}'\n  __Pa kernel.sched_min_granularity_ns \"[nanosecs] \"  '{printf \"\\\"%s\\\"%s  (%.5f sec)\\n\", $1, H0, $1*10^-9}'\n  __Pa kernel.sched_latency_ns \"[nanosecs] \"  '{printf \"\\\"%s\\\"%s  (%.5f sec)\", $1, H0, $1*10^-9}'\n  \n  echo -e \"$XSOS_INDENT_H1${c[H2]}fs.${c[0]}\"\n  __Pa fs.file-max \"[fds] \"  '{printf \"\\\"%s\\\"%s  (system-wide limit for num open files [file descriptors])\", $1,H0}'\n  __Pa fs.nr_open  \"[fds] \"  '{printf \"\\\"%s\\\"%s  (per-process limit for num open files [see also RLIMIT_NOFILE])\", $1,H0}'\n  __Pa fs.file-nr \"[fds] \"  '{printf \"\\\"%s  %s  %s\\\"%s  (num allocated fds, N/A, num free fds)\", $1,$2,$3,H0 }'\n  __Pa fs.inode-nr \"[inodes] \"  '{printf \"\\\"%s  %s\\\"%s  (nr_inodes allocated, nr_free_inodes)\", $1,$2,H0}'\n  __Pa fs.dentry-state \"[dentries] \"  '{printf \"\\\"%s  %s  %s  %s  %s  %s\\\"%s  (nr_dentry, nr_unused, age_limit, want_pages, nr_negative, dummy)\", $1,$2,$3,$4,$5,$6,H0}'\n  \n  echo -e \"$XSOS_INDENT_H1${c[H2]}net.${c[0]}\"\n  __Pa net.core.busy_read \"[microsec] \"  '{printf \"\\\"%s\\\"%s  \", $1, H0; if ($1==0) printf \"(off)\"}'\n  __Pa net.core.busy_poll \"[microsec] \"  '{printf \"\\\"%s\\\"%s  \", $1, H0; if ($1==0) printf \"(off)\"}'\n  __P net.core.netdev_budget \"[packets] \"\n  __P net.core.netdev_max_backlog \"[packets] \"\n  __Pa net.core.rmem_default \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __Pa net.core.wmem_default \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __Pa net.core.rmem_max \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __Pa net.core.wmem_max \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __P net.ipv4.icmp_echo_ignore_all \"[bool] \"\n  __P net.ipv4.ip_forward \"[bool] \"\n  __Pa net.ipv4.ip_local_port_range \"[ports] \"  '{printf \"\\\"%s  %s\\\"%s  (defines ephemeral port range used by TCP/UDP)\", $1,$2,H0}'\n  __Pa net.ipv4.ip_local_reserved_ports \"[ports] \"  '{printf \"\\\"%s\\\"%s  (comma-separated ports/ranges to exclude from automatic port assignments)\", $0,H0}'\n  __Pa net.ipv4.tcp_max_orphans \"[sockets] \"  '{printf \"\\\"%s\\\"%s  (%d MiB @ max 64 KiB per orphan)\", $1, H0, $1*64/1024}'\n  __Pa net.ipv4.tcp_mem \"[$pgsz-KiB pages] \"  \"-vPGSZ=$pgsz\"  '{printf \"\\\"%s  %s  %s\\\"%s  (%.2f GiB, %.2f GiB, %.2f GiB)\", $1, $2, $3, H0, $1*PGSZ/1024/1024, $2*PGSZ/1024/1024, $3*PGSZ/1024/1024}'\n  __Pa net.ipv4.udp_mem \"[$pgsz-KiB pages] \"  \"-vPGSZ=$pgsz\"  '{printf \"\\\"%s  %s  %s\\\"%s  (%.2f GiB, %.2f GiB, %.2f GiB)\", $1, $2, $3, H0, $1*PGSZ/1024/1024, $2*PGSZ/1024/1024, $3*PGSZ/1024/1024}'\n  __P net.ipv4.tcp_window_scaling \"[bool] \"\n  __Pa net.ipv4.tcp_rmem \"[bytes] \"  '{printf \"\\\"%s  %s  %s\\\"%s  (%d KiB, %d KiB, %d KiB)\", $1, $2, $3, H0, $1/1024, $2/1024, $3/1024}'\n  __Pa net.ipv4.tcp_wmem \"[bytes] \"  '{printf \"\\\"%s  %s  %s\\\"%s  (%d KiB, %d KiB, %d KiB)\", $1, $2, $3, H0, $1/1024, $2/1024, $3/1024}'\n  __Pa net.ipv4.udp_rmem_min \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __Pa net.ipv4.udp_wmem_min \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __P net.ipv4.tcp_sack \"[bool] \"\n  __P net.ipv4.tcp_timestamps \"[bool] \"\n  __Pa net.ipv4.tcp_fastopen \"[bitmap] \" '{printf \"\\\"%s\\\"%s  (\", $1, H0; if ($1==0) printf \"disabled\"; else if ($1==1) printf \"enable send\"; else if ($1==2) printf \"enable receive\"; else if ($1==3 || $1==7) printf \"enable send/receive\"; else if ($1==4) printf \"invalid value\"; else printf \"no logic for higher values\"; if ($1==7) printf \" + send regardless of cookies\"; printf \"; see ip-sysctl.txt)\"}'\n  __Pa net.ipv4.ipfrag_high_thresh \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __Pa net.ipv4.ipfrag_low_thresh \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __Pa net.ipv6.ip6frag_high_thresh \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n  __Pa net.ipv6.ip6frag_low_thresh \"[bytes] \"  '{printf \"\\\"%s\\\"%s  (%d KiB)\", $1, H0, $1/1024}'\n\n  echo -e \"$XSOS_INDENT_H1${c[H2]}vm.${c[0]}\"\n  __Pa vm.dirty_ratio \"\"  '{if ($1>0) printf \"\\\"%s\\\"%s  (%% of total system memory)\", $1, H0; else printf \"\\\"0\\\"%s  (disabled -- check dirty_bytes)\", H0}'\n  __Pa vm.dirty_bytes \"\"  '{if ($1>0) printf \"\\\"%s\\\"%s  (%.1f MiB)\", $1, H0, $1/1024/1024; else printf \"\\\"0\\\"%s  (disabled -- check dirty_ratio)\", H0}'\n  __Pa vm.dirty_background_ratio \"\"  '{if ($1>0) printf \"\\\"%s\\\"%s  (%% of total system memory)\", $1, H0; else printf \"\\\"0\\\"%s  (disabled -- check dirty_background_bytes)\", H0}'\n  __Pa vm.dirty_background_bytes \"\"  '{if ($1>0) printf \"\\\"%s\\\"%s  (%.1f MiB)\", $1, H0, $1/1024/1024; else printf \"\\\"0\\\"%s  (disabled -- check dirty_background_ratio)\", H0}'\n  __P vm.dirty_expire_centisecs\n  __P vm.dirty_writeback_centisecs\n  __P vm.max_map_count\n  __P vm.min_free_kbytes\n  __Pa vm.nr_hugepages \"[$hpgsz-MiB pages] \"   \"-vHPGSZ=$hpgsz\"  '{if ($1>0) printf \"\\\"%s\\\"%s  (%.1f GiB total)\", $1, H0, $1*HPGSZ/1024; else printf \"\\\"%s\\\"%s\", $1, H0}'\n  __Pa vm.nr_overcommit_hugepages \"[$hpgsz-MiB pages] \"   \"-vHPGSZ=$hpgsz\"  '{if ($1>0) printf \"\\\"%s\\\"%s  (%.1f GiB total)\", $1, H0, $1*HPGSZ/1024; else printf \"\\\"%s\\\"%s\", $1, H0}'\n  __Pa vm.overcommit_memory \"[0-2] \"   '{if ($1==0) printf \"\\\"0\\\"%s  (heuristic overcommit)\", H0; else if ($1==1) printf \"\\\"1\\\"%s  (always overcommit, never check)\", H0; else if ($1==2) printf \"\\\"2\\\"%s  (always check, never overcommit)\", H0}'\n  __P vm.overcommit_ratio\n  __Pa vm.oom_kill_allocating_task \"[bool] \"  '{if ($1==0) printf \"\\\"0\\\"%s  (scan tasklist)\", H0; else printf \"\\\"1\\\"%s  (kill OOM-triggering task)\", H0}'\n  __Pa vm.panic_on_oom \"[0-2] \"  '{if ($1==0) printf \"\\\"0\\\"%s  (no panic)\", H0; else if ($1==1) printf \"\\\"1\\\"%s  (no panic if OOM-triggering task limited by mbind/cpuset)\", H0; else if ($1==2) printf \"\\\"2\\\"%s  (always panic)\", H0}'\n  __P vm.swappiness \"[0-100] \"\n  __P vm.force_cgroup_v2_swappiness \"[bool] \"\n  __P vm.vfs_cache_pressure \"[0-100] \"\n  __Pa vm.zone_reclaim_mode \"[bitmask] \"  '{if ($1==0) printf \"\\\"0\\\"%s  (zone reclaim disabled)\", H0; else if ($1==1) printf \"\\\"1\\\"%s  (zone reclaim on)\", H0; else if ($1==3) printf \"\\\"3\\\"%s  (zone reclaim writes dirty pages out)\", H0; else if ($1==5) printf \"\\\"5\\\"%s  (zone reclaim swaps pages)\", H0; else if ($1==7) printf \"\\\"7\\\"%s  (zone reclaim writes dirty pages out and swaps pages)\", H0; else printf \"\\\"%s\\\"%s  (sysctl set to invalid value; it should be 0, 1, 3, 5, or 7)\", $1, H0}'\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\n\nPSCHECK() {\n  # Local vars:\n  local ps_input_procs ps_input_thrds_raw ps_input_thrds num_sleepers_procs=? num_zombies_procs=? num_sleepers_thrds=? num_zombies_thrds=? ps_input noun top_threads_ps_header top_threads ps_header num_top_users num_comm_args num_process_lines process_line_length Dsleepers Zombies msg_sleepers_thrds msg_zombies_thrds top_users top_users_header\n  \n  # Get input from proper place dependent on what was passed\n  if [[ -z $1 ]]; then\n    ps_input_thrds_raw=$(ps auxm)\n    ps_input_procs=$(ps aux)\n  elif [[ -f $1 ]]; then\n    # If passed a single file\n    if [[ $XSOS_PS_THREADS == y ]]; then\n      ps_input_thrds_raw=$(gawk '$1!=\"/bin/ps\"{print}' <\"$1\")\n    else\n      ps_input_procs=$(gawk '$1!=\"/bin/ps\"{print}' <\"$1\")\n    fi\n  else\n    ps_input_thrds_raw=$(gawk '$1!=\"/bin/ps\"{print}' <\"$1/sos_commands/process/ps_auxwwwm\")\n    ps_input_procs=$(gawk '$1!=\"/bin/ps\"{print}' <\"$1/ps\")\n  fi\n  # Need to protect any percent signs by doubling them up\n  if [[ -n $ps_input_procs ]]; then\n    ps_input_procs=$(sed '1!s/%/%%/g' <<<\"$ps_input_procs\")\n    num_sleepers_procs=$(gawk 'BEGIN{n=0} $8~/D/{n++} END{print n}' <<<\"$ps_input_procs\")\n    num_zombies_procs=$(gawk 'BEGIN{n=0} $8~/Z/{n++} END{print n}' <<<\"$ps_input_procs\")\n  fi\n  if [[ -n $ps_input_thrds_raw ]]; then\n    ps_input_thrds_raw=$(sed '1!s/%/%%/g' <<<\"$ps_input_thrds_raw\")\n    num_sleepers_thrds=$(gawk 'BEGIN{n=0} $8~/D/{n++} END{print n}' <<<\"$ps_input_thrds_raw\")\n    num_zombies_thrds=$(gawk 'BEGIN{n=0} $8~/Z/{n++} END{print n}' <<<\"$ps_input_thrds_raw\")\n    if [[ $XSOS_PS_THREADS != y ]]; then\n      [[ $num_sleepers_thrds -gt $num_sleepers_procs ]] && msg_sleepers_thrds=\"\\n$XSOS_INDENT_H2${c[Warn1]}Blocked threads detected; run with --threads option for full detail${c[0]}\"\n      [[ $num_zombies_thrds -gt $num_zombies_procs ]] && msg_zombies_thrds=\"\\n$XSOS_INDENT_H2${c[Warn1]}Defunct threads detected; run with --threads option for full detail${c[0]}\"\n    fi\n    # Threads in ps m output show with \"-\" for PID ($2) and COMMAND ($11), so let's fix that\n    ps_input_thrds=$(\n      gawk '\n        {\n          if ($2==\"-\") {\n            $2 = pid; $11 = \"[thread of] \" cmd\n          }\n          else {\n            pid = $2; cmd = $11\n            for (i=12; i<=NF; i++) cmd = cmd FS $i\n          }\n          print\n        }\n      ' <<<\"$ps_input_thrds_raw\"\n    )\n  fi\n  \n  if [[ $XSOS_PS_THREADS == y ]]; then\n    noun=\"threads\"\n    ps_input=$ps_input_thrds\n  else\n    noun=\"processes\"\n    ps_input=$ps_input_procs\n  fi\n  \n  # Verbosity? We den need no stinkin' verbosity!\n  if [[ $XSOS_PS_LEVEL == 0 ]]; then\n    # V-level 0: Less than default\n    num_top_users=3\n    num_comm_args=0\n    num_process_lines=5\n    process_line_length=100\n  elif [[ -z $XSOS_PS_LEVEL || $XSOS_PS_LEVEL == 1 ]]; then\n    # V-level 1: Default\n    num_top_users=10\n    num_comm_args=2\n    num_process_lines=10\n    process_line_length=150\n  elif [[ $XSOS_PS_LEVEL == 2 ]]; then\n    # V-level 2: Verbose\n    num_top_users=30\n    num_comm_args=10\n    num_process_lines=30\n    process_line_length=512\n  elif [[ $XSOS_PS_LEVEL == 3 ]]; then\n    # V-level 3: MOOOAAAARR\n    num_top_users=60\n    num_comm_args=1023\n    num_process_lines=60\n    process_line_length=2047  # This is the max that `column` can handle\n  elif [[ $XSOS_PS_LEVEL == 4 ]]; then\n    # V-level 4: Eerrryting\n    num_top_users=\n    num_comm_args=1023\n    num_process_lines=\n    process_line_length=2047  # This is the max that `column` can handle\n  fi\n  \n  __conditional_head() {\n  [[ -n $1 ]] &&\n    echo head -n$1 ||\n    echo cat\n  }\n  \n  # First, we need to convert VSZ & RSS in the ps input to MiB or GiB (if necessary)\n  # We also need to perfectly columnize the input and chop off extra command args based on above options\n  _convert_and_columize() {\n    gawk -vMAX_fields=$((num_comm_args+12)) -vu=$(tr '[:lower:]' '[:upper:]' <<<\"$XSOS_PS_UNIT\") '\n      BEGIN {\n        # Not going to worry about down-converting to bytes or up-converting to TiB\n        if      (u == \"B\") u = \"K\"\n        else if (u == \"T\") u = \"G\"\n        else if (u == \"K\" || u == \"G\") u = u\n        else u = \"M\"\n        \n        # Figure out what number to divide by to end up with KiB or MiB or GiB\n        if      (u == \"K\") divisor = 1\n        else if (u == \"M\") divisor = 1024\n        else if (u == \"G\") divisor = 1024 ** 2\n        \n        # Set pretty printing unit\n        U = u\"iB\"\n      }\n      NR==1 {\n        if ($1==\"USER\")\n          j = 0\n        else if ($1==\"#\") {\n          j = 1\n          MAX_fields ++\n        }\n        fieldvsz = j + 5\n        fieldrss = j + 6\n        fieldtty = j + 7\n        fieldcmd = j + 11\n      }\n      {\n        # Print fields up through %MEM\n        for (i=1; i<fieldvsz; i++)\n          printf \"%s❚\",$i\n        \n        # Print fields VSZ & RSS\n        for (i=fieldvsz; i<fieldtty; i++) {\n          if      (NR == 1)  printf \"%s-%s❚\", $i, U\n          else if (u == \"G\") printf \"%.1f❚\", $i/divisor\n          else               printf \"%.0f❚\", $i/divisor\n        }\n        \n        # Print fields up through TIME\n        for (i=fieldtty; i<fieldcmd; i++)\n          printf $i\"❚\"\n        \n        # For the last field (command) we need to chop things up\n        for (i=fieldcmd; i<=NF && i<MAX_fields; i++)\n          printf $i\" \"\n        printf \"\\n\"\n      }\n    ' <<<\"$1\" | cut -c-$process_line_length | column -ts❚ | sed \"s,^,$XSOS_INDENT_H2,\"\n  }\n  \n  ps_input=$(_convert_and_columize \"$ps_input\")\n  # Deal with header\n  ps_header=$(head -n1 <<<\"$ps_input\")\n  ps_input=$(tail -n+2 <<<\"$ps_input\")\n  \n  if [[ -n $ps_input_thrds_raw ]]; then\n    # Let's get a count of how many threads each PID has\n    top_threads=$(\n      gawk '\n        NR==1 {\n          printf \"# %s\\n\", $0\n        }\n        NR>1 {\n          if ($2 ~ /^[0-9]+$/) {\n            pid = $2\n            line[pid] = $0\n          }\n          else if ($2 == \"-\") {\n            nthreads[pid] ++\n          }\n          else\n            pid = \"NULL\"\n        }\n        END {\n          for (pid in line)\n            printf (\"%d %s\\n\", nthreads[pid], line[pid]) | \"sort -rn\"\n        }\n      ' <<<\"$ps_input_thrds_raw\"\n    )\n    top_threads=$(_convert_and_columize \"$top_threads\")\n    top_threads_ps_header=$(head -n1 <<<\"$top_threads\")\n    top_threads=\"${c[H3]}$top_threads_ps_header${c[0]}\\n$(tail -n+2 <<<\"$top_threads\" | $(__conditional_head $num_process_lines))\"\n  else\n    top_threads=\"$XSOS_INDENT_H2${c[lgrey]}[No thread info]${c[0]}\"\n  fi\n  \n  # Format and prepare sleeping/zombie processes\n  Dsleepers=$(gawk -vcolor_warn=\"${c[Warn1]}\" -vc_0=\"${c[0]}\" '$8~/D/ {print color_warn $0 c_0}' <<<\"$ps_input\")\n  Zombies=$(gawk -vc_grey=\"${c[lgrey]}\" -vc_0=\"${c[0]}\" '$8~/Z/ {print c_grey $0 c_0}' <<<\"$ps_input\")\n  if [[ -n $Dsleepers ]]; then\n    Dsleepers=\"${c[H3]}$ps_header${c[0]}\\n$Dsleepers$msg_sleepers_thrds\"\n  else\n    Dsleepers=\"$XSOS_INDENT_H2${c[lgrey]}[None]${c[0]}$msg_sleepers_thrds\"\n  fi\n  if [[ -n $Zombies ]]; then\n    Zombies=\"${c[H3]}$ps_header${c[0]}\\n$Zombies$msg_zombies_thrds\"\n  else\n    Zombies=\"$XSOS_INDENT_H2${c[lgrey]}[None]${c[0]}$msg_zombies_thrds\"\n  fi\n  \n  # Calculate top cpu-using & mem-using users\n  if [[ $XSOS_PS_LEVEL -lt 3 ]]; then  # If verbosity level 0-2, restrict number of users shown\n    # Process ps input to generate summary user-list of top-users\n    top_users=$(\n      gawk -vu=$(tr '[:lower:]' '[:upper:]' <<<\"$XSOS_PS_UNIT\") '\n        BEGIN { print \"USER❚%CPU❚%MEM❚RSS\" }\n        { pCPU[$1]+=$3; pMEM[$1]+=$4; sRSS[$1]+=$6 }\n        END {\n          # Figure out what number to divide by to end up with GiB\n          if      (u == \"K\") divisor = 1024 ** 2\n          else if (u == \"M\") divisor = 1024\n          else if (u == \"G\") divisor = 1\n          for (user in pCPU)\n            # Only show if greater than 0% CPU and 0.1% MEM\n            if (pCPU[user]>0 || pMEM[user]>0.1)\n              printf \"%s❚%.1f%%❚%.1f%%❚%.2f GiB\\n\", user, pCPU[user], pMEM[user], sRSS[user]/divisor\n        }\n      ' <<<\"$ps_input\" | column -ts❚ | sed \"s,^,$XSOS_INDENT_H2,\")\n    # Grab header from the top\n    top_users_header=$(head -n1 <<<\"$top_users\")\n  \n  else  # If verbosity level 3-4, show all users\n    # Process ps input to generate summary user-list of top-users\n    top_users=$(\n      gawk -vu=$(tr '[:lower:]' '[:upper:]' <<<\"$XSOS_PS_UNIT\") '\n        BEGIN { print \"USER❚%CPU❚%MEM❚RSS\" }\n        { pCPU[$1]+=$3; pMEM[$1]+=$4; sRSS[$1]+=$6 }\n        END {\n          # Figure out what number to divide by to end up with GiB\n          if      (u == \"K\") divisor = 1024 ** 2\n          else if (u == \"M\") divisor = 1024\n          else if (u == \"G\") divisor = 1\n          for (user in pCPU)\n            printf \"%s❚%.1f%%❚%.1f%%❚%.2f GiB\\n\", user, pCPU[user], pMEM[user], sRSS[user]/divisor\n        }\n      ' <<<\"$ps_input\" | column -ts❚ | sed \"s,^,$XSOS_INDENT_H2,\")\n    # Grab header from the top\n    top_users_header=$(head -n1 <<<\"$top_users\")\n  fi\n  \n  # Remove header from the top and sort everything else by %CPU, potentially trimming down list\n  top_users=$(tail -n+2 <<<\"$top_users\" | sort -rnk2 | $(__conditional_head $num_top_users))\n    ps_input=$(tail -n+2 <<<\"$ps_input\")\n  \n  # Print!\n  echo -e \"${c[H1]}PS CHECK${c[0]}\n$XSOS_INDENT_H1${c[H2]}Total number of threads/processes:${c[0]} \\n$XSOS_INDENT_H2${c[Imp]}$(tail -n+2 <<<\"$ps_input_thrds\" | wc -l) / $(tail -n+2 <<<\"$ps_input_procs\" | wc -l)${c[0]}\n$XSOS_INDENT_H1${c[H2]}Top users of CPU & MEM:${c[0]} \\n${c[H3]}$top_users_header${c[0]} \\n$top_users\n$XSOS_INDENT_H1${c[H2]}Uninteruptible sleep threads/processes ($num_sleepers_thrds/$num_sleepers_procs):${c[0]} \\n$Dsleepers\n$XSOS_INDENT_H1${c[H2]}Defunct zombie threads/processes ($num_zombies_thrds/$num_zombies_procs):${c[0]} \\n$Zombies\n$XSOS_INDENT_H1${c[H2]}Top CPU-using ${noun}:${c[0]} \\n${c[H3]}$ps_header${c[0]} \\n$(sort -rnk3 <<<\"$ps_input\" | $(__conditional_head $num_process_lines))\n$XSOS_INDENT_H1${c[H2]}Top MEM-using ${noun}:${c[0]} \\n${c[H3]}$ps_header${c[0]} \\n$(sort -rnk6 <<<\"$ps_input\" | $(__conditional_head $num_process_lines))\n$XSOS_INDENT_H1${c[H2]}Top thread-spawning processes:${c[0]} \\n$top_threads\"\n  echo -en $XSOS_HEADING_SEPARATOR\n}\n\nSSCHECK(){\n\n  # These are used later to print the name, cpu and mem of the process owner of the socket.\n  pids=$(cat $1/ps | tr -d '()[]' | tr -s ' ' | cut -d' ' -f2)\n  cmds=$(cat $1/ps | tr -d '()[]' | tr -s ' ' | cut -d' ' -f11)\n  cpus=$(cat $1/ps | tr -d '()[]' | tr -s ' ' | cut -d' ' -f3)\n  mems=$(cat $1/ps | tr -d '()[]' | tr -s ' ' | cut -d' ' -f4)\n\n  # These fields have format \"name value\". Add them a \":\" so they have the same format as the other fields (name: value)\n  cat \"$1/sos_commands/networking/ss_-peaonmi\" | sed \\\n    -e 's/ send / send:/' \\\n    -e 's/ pacing_rate / pacing_rate:/' \\\n    -e 's/ delivered / delivered:/' \\\n    -e 's/ delivery_rate / delivery_rate:/' |\n\n    gawk -vpid_list=\"$pids\" -vcmd_list=\"$cmds\" -vmem_list=\"$mems\" -vcpu_list=\"$cpus\" \\\n    -vcheck_fields_str=\"${XSOS_SS_CHECK_FIELDS}\" \\\n    -vI=\"$XSOS_INDENT_H1\" -vcH1=\"${c[H1]}\" -vcH2=\"${c[H2]}\" -vcH3=\"${c[H3]}\" -vc0=\"${c[0]}\" '\n\n    BEGIN{\n\n      split(pid_list, pids, \" \")\n      split(cmd_list, cmds, \" \")\n      split(mem_list, mems, \" \")\n      split(cpu_list, cpus, \" \")\n\n      for(i in pids){\n        pid = pids[i]\n        pidcmd[pid][\"cmd\"] = cmds[i]\n        pidcmd[pid][\"mem\"] = mems[i]\n        pidcmd[pid][\"cpu\"] = cpus[i]\n      }\n\n      split(check_fields_str, check_fields, \"|\") \n\n    }\n\n    # Returns the value part of a key-value pair with format \"key: value\"\n    function valueof(keyvalue){\n      split(keyvalue, splitted, \":\")\n      return splitted[2]\n    }\n\n    function print_stream_summary(params){\n      for (key in params){\n        print \"KEY \"key, params[key]\n      }\n    }\n\n    {\n    #if (/^[^\\t].*/){\n    if (/^(tcp|udp|sctp)/){\n\n      # New session starts. Clear everything\n      delete params\n\n      params[\"proto\"] = $1\n      params[\"state\"] = $2\n      params[\"rq\"] = $3\n      params[\"tq\"] = $4\n      params[\"local\"] = $5\n      params[\"peer\"] = $6\n\n      # Initialize bools\n      params[\"ts\"] = 0\n      params[\"sack\"] = 0\n      params[\"htcp\"] = 0\n      params[\"app_limited\"] = 0\n      params[\"v6only\"] = 0\n\n      # Index for everything related to this stream, Used later when printing\n      params[\"string\"] = sprintf(\"%s❚%s❚%s\" , params[\"proto\"], params[\"local\"], params[\"peer\"])\n\n      # Figure out what the other info provided is and parse it.\n      for (i=7; i<NF; i++){\n        switch($i){\n          case /^users/:\n            # Format: users:((\"user1\",pid=PID,fd=FD),\"user2\",pid=PID2,fd=FD2, ...)\n            # First we extract all the definitions\n            match($i, /^users:\\(\\((.*)\\)$/, users0);\n            user_list_n = split(users0[1], user_list, /\\),?\\(?/)\n\n            # split each user definition and add it\n            for (j=1; j<user_list_n; j++){\n              userdef_n = split(user_list[j], userdef ,\",\")\n              gsub(/\"/, \"\", userdef[1])\n              gsub(/pid=/, \"\", userdef[2])\n              gsub(/fd=/, \"\", userdef[3])\n              params[\"users\"][j][\"name\"] = userdef[1]\n              params[\"users\"][j][\"pid\"] = userdef[2]\n              params[\"users\"][j][\"fd\"] = userdef[3]\n            }\n\n            break\n\n          case /^\"timer\"/:\n            # Format: timer:(<timer_name>,<expire_time>,<retrans>)\n            match($i, /^timer:\\(\\)$/, timer)\n            split(timer, \",\", timer_params)\n            params[\"timer_name\"] =     timer_params[1]\n            params[\"timer_expire\"] =   timer_params[2]\n            params[\"timer_retrans\"] =  timer_params[3];                           break\n\n\n          case /^ino:/:               params[\"ino\"] =           valueof($i);      break\n          case /^sk:/:                params[\"cookie\"] =        valueof($i);      break\n          case /^uid:/:               params[\"uid\"] =           valueof($i);      break\n          case /^v6only:/:            params[\"v6only\"] =        valueof($i);      break\n        }\n      }\n    }\n    else if (/^\\t/ && params[\"proto\"]){\n      # The second line provides more fields. We keep parsing them and adding them to \"params\"\n\n      for (i=1; i<=NF; i++){\n        switch($i){\n\n          # Boolean fields. We only check for the presence of these ones.\n          case /^cubic$/:             params[\"congestion\"] =     \"cubic\";         break\n          case /^vegas$/:             params[\"congestion\"] =     \"vegas\";         break\n          case /^ts$/:                params[\"ts\"] =             1;               break\n          case /^sack$/:              params[\"sack\"] =           1;               break\n          case /^htcp$/:              params[\"htcp\"] =           1;               break\n          case /^app_limited$/:       params[\"app_limited\"] =    1;               break\n\n          # Most of the other fields have format \"name: value\"\n          case /^send:/:              params[\"send\"] =          valueof($i);      break\n          case /^delivered:/:         params[\"delivered\"] =     valueof($i);      break\n          case /^pacing_rate:/:       params[\"pacing_rate\"] =   valueof($i);      break\n          case /^delivery_rate:/:     params[\"delivery_rate\"] = valueof($i);      break\n          case /^rto:/:               params[\"rto\"] =           valueof($i);      break\n          case /^ato:/:               params[\"ato\"] =           valueof($i);      break\n          case /^mss:/:               params[\"mss\"] =           valueof($i);      break\n          case /^pmtu:/:              params[\"pmtu\"] =          valueof($i);      break\n          case /^rcvmss/:             params[\"rcvmss\"] =        valueof($i);      break\n          case /^advmss:/:            params[\"advmss\"] =        valueof($i);      break\n          case /^cwnd:/:              params[\"cwnd\"] =          valueof($i);      break\n          case /^ssthresh:/:          params[\"ssthresh\"] =      valueof($i);      break\n          case /^bytes_sent:/:        params[\"bytes_sent\"] =    valueof($i);      break\n          case /^bytes_retrans:/:     params[\"bytes_retrans\"] = valueof($i);      break\n          case /^bytes_acked:/:       params[\"bytes_acked\"] =   valueof($i);      break\n          case /^bytes_received:/:    params[\"bytes_received\"] =valueof($i);      break\n          case /^segs_out:/:          params[\"segs_out\"] =      valueof($i);      break\n          case /^segs_in:/:           params[\"segs_in\"] =       valueof($i);      break\n          case /^data_segs_out:/:     params[\"data_segs_out\"] = valueof($i);      break\n          case /^data_segs_in:/:      params[\"data_segs_in\"] =  valueof($i);      break\n          case /^delivered:/:         params[\"delivered\"] =     valueof($i);      break\n          case /^rwnd_limited:/:      params[\"rwnd_limited\"] =  valueof($i);      break\n          case /^dsack_dups:/:        params[\"dsack_dups\"] =    valueof($i);      break\n          case /^rcv_rtt:/:           params[\"rcv_rtt\"] =       valueof($i);      break\n          case /^rcv_space:/:         params[\"rcv_space\"] =     valueof($i);      break\n          case /^rcv_ssthresh:/:      params[\"rcv_sshthresh\"] = valueof($i);      break\n          case /^rcv_notsent:/:       params[\"rcv_notsent\"] =   valueof($i);      break\n          case /^minrtt:/:            params[\"minrtt\"] =        valueof($i);      break\n          case /^lastsnd:/:           params[\"lastsnd\"] =       valueof($i);      break\n          case /^lastrcv:/:           params[\"lastrcv\"] =       valueof($i);      break\n          case /^lastack:/:           params[\"lastack\"] =       valueof($i);      break\n          case /^reordering:/:        params[\"reordering\"] =    valueof($i);      break\n          case /^unacked:/:           params[\"unacked\"] =       valueof($i);      break\n          case /^lost:/:              params[\"lost\"] =          valueof($i);      break\n          case /^backoff:/:           params[\"backoff\"] =       valueof($i);      break\n          case /^reord_seen:/:        params[\"reord_seen\"] =    valueof($i);      break\n          case /^notsent:/:           params[\"notsent\"] =       valueof($i);      break\n\n          # Some exceptions with a completely different format:\n          \n          #skmem:(r<rmem_alloc>,rb<rcv_buf>,t<wmem_alloc>,tb<snd_buf>,\n          #              f<fwd_alloc>,w<wmem_queued>,o<opt_mem>,\n          #              bl<back_log>,d<sock_drop>)\n          case /^skmem:/:\n\n            match($i, /^skmem:\\(r([0-9]+),rb([0-9]+),t([0-9]+),tb([0-9]+),f([0-9]+),w([0-9]+),o([0-9]+),bl([0-9]+),d([0-9]+)/, skmem)\n\n            params[\"rmem_alloc\"] =    skmem[1]\n            params[\"rmem_buf\"] =      skmem[2]\n            params[\"wmem_alloc\"] =    skmem[3]\n            params[\"snd_buf\"] =       skmem[4]\n            params[\"fwd_alloc\"] =     skmem[5]\n            params[\"wmem_queued\"] =   skmem[6]\n            params[\"ropt_mem\"] =      skmem[7]\n            params[\"back_log\"] =      skmem[8]\n            params[\"sock_drop\"] =     skmem[9];          break\n\n          # busy:NNN.NNms\n          case /^busy:/:              match($i, /^busy:([0-9]+)ms/,   busyms)\n                                      params[\"busyms\"] =         busyms[1];        break\n\n          # wscale:<snd_wscale>:<rcv_wscale>\n          case /^wscale:/:            #split ($i, wscale, \",\")\n                                      match($i, /^wscale:([0-9]+),([0-9]+)/, wscale)\n                                      params[\"snd_wscale\"] =     wscale[1]\n                                      params[\"rcv_wscale\"] =     wscale[2];         break\n\n          # rtt:<rtt>/<rttvar>\n          case /^rtt:/:                split ($i, rtt, \"/\")\n                                      params[\"rtt\"] =           rtt[1]\n                                      params[\"rttvar\"] =         rtt[2];           break\n\n          # retrans:<retrans_current>/<retrans_total>\n          case /^retrans:/:            split ($i, retrans, \"/\")\n                                      params[\"retrans_current\"] = retrans[1]\n                                      params[\"retrans_total\"] =   retrans[2];     break\n        } # end switch\n      } # end for\n\n      # Next line will be a new session, so here we save the interesting fields of the session\n\n      # Increment global counters for the protocol and the state\n      counters[\"proto\"][ params[\"proto\"] ] += 1\n      counters[\"state\"][ params[\"state\"] ] += 1\n\n      # Check fields provided via XSOS_SS_CHECK_FIELDS. If any of them is >0, then we add this session to be printed later\n      added = 0\n      for(x in check_fields){\n        key = check_fields[x]\n\n        if(params[key] > 0){\n          string = params[\"string\"]\n          sessions[string][key][\"val\"] = params[key]\n          added = 1\n        }\n      }\n\n      # If this session will be printed, then we want to have some extra info\n      if (added == 1){\n        if(typeof(params[\"users\"]) == \"array\"){\n          for (user_n in params[\"users\"]){\n            sessions[string][\"cmd\"][user_n][\"pid\"] = params[\"users\"][user_n][\"pid\"]\n            sessions[string][\"cmd\"][user_n][\"name\"] = params[\"users\"][user_n][\"name\"]\n          }\n        }else{\n          #print(\"NOT AN ARRAY\", string)\n        }\n        sessions[string][\"proto\"] = params[\"proto\"]\n        sessions[string][\"local\"] = params[\"local\"]\n        sessions[string][\"peer\"] = params[\"peer\"]\n      }\n    } # else if (^\\t /)\n  }\n  function print_table(){\n\n    # Prepare column names\n    _col_names[1] = \"Proto\"\n    _col_names[2] = \"Local\"\n    _col_names[3] = \"Peer\"\n    for (x in check_fields){\n      _col_names[length(_col_names)+1] = check_fields[x]\n    }\n    _col_names[length(_col_names)+1] = \"%CPU\"\n    _col_names[length(_col_names)+1] = \"%MEM\"\n    _col_names[length(_col_names)+1] = \"User\"\n    _col_names[length(_col_names)+1] = \"Command\"\n\n    # Prepare values\n    i = 1\n    for (string in sessions){\n      _values[i][1] = sessions[string][\"proto\"]\n      _values[i][2] = sessions[string][\"local\"]\n      _values[i][3] = sessions[string][\"peer\"]\n\n      for (j in check_fields){\n        key = check_fields[j]\n        _values[i][length(_values[i])+1] = sessions[string][key][\"val\"]\n      }\n\n      _pid = sessions[string][\"cmd\"][1][\"pid\"]\n      _values[i][length(_values[i])+1] = pidcmd[_pid][\"cpu\"]\n      _values[i][length(_values[i])+1] = pidcmd[_pid][\"mem\"]\n      _values[i][length(_values[i])+1] = sessions[string][\"cmd\"][1][\"name\"]\n      _values[i][length(_values[i])+1] = pidcmd[_pid][\"cmd\"]\n      i++\n    }\n\n    # Compute initial widths based on the column names\n    for (i in _col_names){\n      _col_widths[i] = length(_col_names[i])\n    }\n \n    # Compute final widths based on the actual row values\n    for (i in _values){\n      for (j in _values[i]){\n        __value_len = length(_values[i][j])\n        if(__value_len > _col_widths[j]){ _col_widths[j] = __value_len }\n      }\n    }\n\n    # Print headers + underscores\n    # Columns containing numbers are right aligned for clarity\n    printf(I\"\"I\"\"cH3)\n    for (i in _col_names){\n      if (_values[1][i] + 0 == _values[1][i]){ \n        # First row has a number, we assume the same col in all rows are numbers.\n        printf(\"%*s \", _col_widths[i], _col_names[i])\n      }else{\n        printf(\"%*-s \", _col_widths[i], _col_names[i])\n      }\n    }\n    printf(\"\\n\"I\"\"I)\n    for (i in _col_widths){\n      for(j=1; j<= _col_widths[i]; j++){\n          printf(\"-\")\n      }\n      printf(\" \")\n    }\n\n    printf(c0)\n\n    # Finally, print the values\n    for (i in _values){\n      printf(\"\\n\"I\"\"I)\n      for(j in _values[i]){\n        if (_values[i][j] + 0 == _values[i][j]){\n          # its a number, align: right\n          printf(\"%*s \", _col_widths[j], _values[i][j])\n        }else{\n          printf(\"%*-s \", _col_widths[j], _values[i][j])\n        }\n      }\n    }\n    printf(\"\\n\")\n  }\n\n  function print_totals(){\n    for (by in session_c){\n      for (key in counters[by]){\n        printf(\"%s=%s: %d \\n\", by, key, counters[by][key])\n      }\n    }\n  }\n\n  END{\n  printf(cH1\"%s\"c0\"\\n\", \"SS CHECK\")\n  printf(I\"\"cH2\"Sessions:\\n\"c0)\n    print_table()\n  }'\n}\n\nFIREWALL(){\n\n  iptables_vnxL=\"$1/sos_commands/networking/iptables_-vnxL\"\n  firewallcmd_state=\"$1/sos_commands/firewalld/firewall-cmd_--state\"\n  nft_list_ruleset=\"$(echo $1/sos_commands/*/nft_list_ruleset)\"\n  nft_list_ruleset=${nft_list_ruleset%% *}\n  systemctl_list_unit_files=\"$1/sos_commands/systemd/systemctl_list-unit-files\"\n  systemctl_status_all=\"$1/sos_commands/systemd/systemctl_status_--all\"\n\n  __retrieve_service_status(){\n      grep -E -A 2 \"^\\* $1.service\" <$systemctl_status_all | xargs echo |\n        sed 's,\\* .*Loaded: \\([^ ]*\\)[^;]*; \\?\\([^;]*\\);.*Active: \\([^ ]*\\) (\\([^)]*\\)).*,([loaded]=\\1 [enabled]=\\2 [active]=\\3 [running]=\\4),g'\n  }\n\n  declare -A iptables=$(__retrieve_service_status iptables)\n  declare -A nftables=$(__retrieve_service_status nftables)\n  declare -A firewalld=$(__retrieve_service_status firewalld)\n\n  iptables[rules]=$(cat $iptables_vnxL 2>/dev/null | grep -E -v '^$|^Chain|pkts *bytes' | wc -l)\n  nftables[rules]=$(cat $nft_list_ruleset 2>/dev/null | grep -E -v '^table|^$|\\t*chain.*{$|\\t*}$' | wc -l)\n\n  echo -e \"${c[H1]}FIREWALL${c[0]}\"\n  echo -e \"$XSOS_INDENT_H1${c[H2]}Services enabled:${c[0]}\"\n  if echo ${iptables[enabled]} ${nftables[enabled]} ${firewalld[enabled]} | grep enabled >/dev/null; then\n    if [ \"${iptables[enabled]}\"  = \"enabled\" ]; then echo -e \"${XSOS_INDENT_H2}iptables (${iptables[active]}, ${iptables[running]})\"; fi\n    if [ \"${firewalld[enabled]}\" = \"enabled\" ]; then echo -e \"${XSOS_INDENT_H2}firewalld (${firewalld[active]}, ${firewalld[running]})\"; fi\n    if [ \"${nftables[enabled]}\"  = \"enabled\" ]; then echo -e \"${XSOS_INDENT_H2}nftables (${nftables[active]}, ${nftables[running]})\"; fi\n  else\n    echo \"${XSOS_INDENT_H2}No firewall services enabled.\"\n  fi\n\n  echo -e \"\\n$XSOS_INDENT_H1${c[H2]}Rules loaded:${c[0]}\"\n  if [ \"${iptables[rules]}${nftables[rules]}\" -gt 0 ]; then\n    if [ \"${iptables[rules]}\" -gt 0 ]; then echo -e \"${XSOS_INDENT_H2}iptables: ${iptables[rules]}\"; fi\n    if [ \"${nftables[rules]}\" -gt 0 ]; then echo -e \"${XSOS_INDENT_H2}nftables: ${nftables[rules]}\"; fi\n  else\n    echo -e \"${XSOS_INDENT_H2}No rules loaded.\"\n  fi\n}\n\nIFCFG(){\n  files=$(echo $1/etc/sysconfig/network-scripts/ifcfg-*)\n  echo -e \"${c[H1]}IFCFG${c[0]}\"\n  echo -e \"$XSOS_INDENT_H1${c[H2]}Services enabled:${c[0]}\"\n  (\n   echo -e \"FILE❚TYPE❚DEVICE❚NAME❚HWADDR❚ONBOOT❚DEFROUTE❚GATEWAY❚NM_CONTROLLED❚BOND/TEAM❚MASTER❚BRIDGE❚ETHTOOL❚PHYSDEV❚PEERDNS❚ZONE❚MTU\"\n   for f in $files; do\n     fname=\"$(basename $f)\"\n     name=${fname//ifcfg-/}\n\n     # Just fill the array ifcfg with all key=value entries found\n     declare -A ifcfg=\"(\"$(grep -v '^[check_link_down|return 1|^}|#|$]' <$f | sed 's/^\\([^=]\\+\\)=\\(.*\\)$/[\\1]=\\2/g' )\")\"\n\n\n     master=${ifcfg[BONDING_MASTER]}${ifcfg[TEAM_MASTER]}${ifcfg[MASTER]}\n     bond_team_cfg=${ifcfg[BONDING_OPTS]}${ifcfg[TEAM_CONFIG]}\n\n     echo -n $fname❚\n     echo -n ${ifcfg[TYPE]:--}❚\n     echo -n ${ifcfg[DEVICE]:--}❚\n     echo -n ${ifcfg[NAME]:--}❚\n     echo -n ${ifcfg[HWADDR]:--}❚\n     echo -n ${ifcfg[ONBOOT]:--}❚\n     echo -n ${ifcfg[DEFROUTE]:--}❚\n     echo -n ${ifcfg[GATEWAY]:--}❚\n     echo -n ${ifcfg[NM_CONTROLLED]:--}❚\n     echo -n ${bonding_team_cfg:--}❚\n     echo -n ${master:--}❚\n     echo -n ${ifcfg[BRIDGE]:--}❚\n     echo -n ${ifcfg[ETHTOOL_OPTS]:--}❚\n     echo -n ${ifcfg[PHYSDEV]:--}❚\n     echo -n ${ifcfg[PEERDNS]:--}❚\n     echo -n ${ifcfg[ZONE]:--}❚\n     echo -n ${ifcfg[MTU]:--}❚\n     echo\n   done\n  ) | column -ts\"❚\" | sed -e \"s,^\\(FILE.*\\)$,$(printf ${c[H3]})&$(printf ${c[0]}),\" -e \"s,^,${XSOS_INDENT_H2},\"\n}\n\nNETSTAT(){\n  _parse_proc_net_file(){\n    __path=\"$1\"; __hdrs=\"\"; __vals=\"\"; __prefix=\"\";\n    while read line; do \n      if [ -z \"${__hdrs}\" ];then\n        __prefix=\"${line%:*}\"; __hdrs=(${line#*: });\n      else\n        __vals=(${line#*: })\n        __hdr_count=${#__hdrs[@]}\n        __val_count=${#__vals[@]}\n\n        if [ \"$__hdr_count\" != \"$__val_count\" ]; then\n          echo -e \"${c[Warn1]} WARNING: Number of headers and values in ${__path} file don\\'t match\"\n        fi\n\n        for i in $(seq 1 $__hdr_count); do\n          hdr=${__hdrs[$i]}\n          test -z \"$hdr\" && continue\n          val=${__vals[$i]}\n          echo -n \"[${__prefix}.${hdr}]=${val} \"\n        done\n\n        __hdrs=\"\"\n      fi\n    \n    done < \"$1\" \n  }\n  _print_proc_net_array(){\n    declare -A __array=\"$*\"\n    for hdr in \"${!__array[@]}\"; do\n      val=\"${__array[$hdr]}\"\n      [ \"${XSOS_NETSTAT_IGNORE_ZERO}\" == \"y\" ]   && [ \"$val\" -eq \"0\" ] && continue\n      [ \"${XSOS_NETSTAT_FILTER_REGEX}\" != \"\" ]    && [[ ! ${hdr,,} =~ ${XSOS_NETSTAT_FILTER_REGEX,,} ]]    && continue\n      [ \"${XSOS_NETSTAT_HIGHLIGHT_REGEX}\" != \"\" ] && [[ \"${hdr,,}\" =~ ${XSOS_NETSTAT_HIGHLIGHT_REGEX,,} ]] && __color=\"${c[red]}\" || __color=\"\\033[0;00m\" #hdr=${c[red]}${hdr}${c[0]}\n\n      printf \"${__color}%-34s % 10d%b\\n\" $hdr: $val ${c[0]}\n    done\n  }\n\n  echo -e \"${c[H1]}NET STATS${c[0]}\"\n  (\n  # Print all key:value pairs where the value is > 0\n  # LC_ALL=C is set for `sort` to make sure it uses natural sorting\n  [ -f \"$1/proc/net/netstat\" ] && _print_proc_net_array \"($(_parse_proc_net_file $1/proc/net/netstat))\"\n  [ -f \"$1/proc/net/snmp\"    ] && _print_proc_net_array \"($(_parse_proc_net_file $1/proc/net/snmp))\"\n  [ -f \"$1/proc/net/snmp6\" ]   && _print_proc_net_array \"($(cat $1/proc/net/snmp6 | awk '{ printf \"[%s]=%d \", $1, $2}'))\"\n  ) | LC_ALL=C sort -k 1.9 | sed \"s/^/$XSOS_INDENT_H1/g\"\n  \n}\n\n#-------------------------------------------------------------------------------\n# BLEH\n# Eventually I'll probably replace all of this with a python loader.\n# Python's argparse is so much better than dealing with all this crap.\n\n# Used to check for existence of files on a sosreport and print errors to stderr\nSOS_CHECKFILE() {\n  local module firstfile\n  # $1: module name, e.g. bios, os, cpu, mem\n  # $2+: file names, i.e. potential files to be found in sosreport root\n  module=$1; shift; firstfile=$1\n  # If module needs to be called, check for files\n  if [[ $(eval echo \\$$module) == y ]]; then\n    while [[ $# -gt 0 ]]; do\n      # If ethtool or teaming module being called, do something specific\n      if [[ $module == ethtool || $module == teaming ]] && ls \"$sosroot\"/$1 &>/dev/null; then\n          return  # Return successfully if ethtool files found\n      # If file ends in slash, look for dir\n      elif [[ $1 =~ /$ ]]; then\n        [[ -d $sosroot/$1 ]] && return  # Return successfully if dir found\n      else\n        [[ -r $sosroot/$1 ]] && return  # Return successfully if file readable\n      fi\n      shift\n    done\n  else\n    return  # If module doesn't need to be called, return success\n  fi\n  # If we're still here, a module for which we don't have files was requested -- warn\n  echo -e \"${c[Warn2]}Warning:${c[Warn1]} '$sosroot/$firstfile' file unreadable; skipping $module check${c[0]}\" >&2\n  echo -en $XSOS_HEADING_SEPARATOR >&2\n  return 1\n}\n\n# Used to conditionally run certain functions when running on localhost\nCOND_RUN() {\n  if [[ $2 == --require_root && $UID != 0 ]]; then\n    echo -e \"${c[Warn2]}Warning:${c[Warn1]} Need root access to run $1 command on localhost${c[0]}\" >&2\n    echo -en $XSOS_HEADING_SEPARATOR >&2\n  elif command -v $1 &>/dev/null; then\n    # The following tr command translates $1 to the uppercase function name, e.g. lspci --> LSPCI\n    # In a BASHv4-only world, this could be done with simply: ${1^^}\n    $(tr '[:lower:]' '[:upper:]' <<<\"$1\")\n  else\n    echo -e \"${c[Warn2]}Warning:${c[Warn1]} $1 command not present in PATH${c[0]}\" >&2\n    echo -en $XSOS_HEADING_SEPARATOR >&2\n  fi\n}\n\n\n# Create sub tempdir in /dev/shm (tons of bash constructs use TMPDIR)\n[[ -d /dev/shm && -w /dev/shm ]] && parent=/dev/shm || parent=/tmp\nexport TMPDIR=$(mktemp -d -p $parent)\n# Create tmp file for capturing stderr\nstderr_file=$TMPDIR/stderr\n# Remove temp dir when we're done\ntrap \"rm -rf $TMPDIR 2>/dev/null\" EXIT\n\n{\n  # Redirect stderr to temp file\n  exec 7>&2 2>$stderr_file\n  \n  # If special options and files were provided ....\n  if [[ $BASH_VERSINFO -ge 4 && -n ${sfile[*]} ]]; then\n    [[ -r ${sfile[B]} ]] && DMIDECODE \"${sfile[B]}\"\n    [[ -r ${sfile[C]} ]] && CPUINFO   \"${sfile[C]}\"\n    [[ -r ${sfile[F]} ]] && INTERRUPT \"${sfile[F]}\"\n    [[ -r ${sfile[M]} ]] && MEMINFO   \"${sfile[M]}\"\n    [[ -r ${sfile[D]} ]] && STORAGE   \"${sfile[D]}\" --no-mpath\n    [[ -r ${sfile[T]} ]] && MULTIPATH \"${sfile[T]}\"\n    [[ -r ${sfile[L]} ]] && LSPCI     \"${sfile[L]}\"\n    [[ -r ${sfile[R]} ]] && SOFTIRQ   \"${sfile[R]}\"\n    [[ -r ${sfile[N]} ]] && NETDEV    \"${sfile[N]}\"\n    [[ -r ${sfile[G]} ]] && BONDING   \"${sfile[G]}\"\n    [[ -r ${sfile[I]} ]] && IPADDR    \"${sfile[I]}\"\n    [[ -r ${sfile[P]} ]] && PSCHECK   \"${sfile[P]}\"\n    [[ -r ${sfile[S]} ]] && SSCHECK   \"${sfile[S]}\"\n    [[ -r ${sfile[F]} ]] && FIREWALL  \"${sfile[F]}\"\n\n  # If SOSREPORT-ROOT provided, use that\n  elif [[ -n $sosroot ]]; then\n    SOS_CHECKFILE bios    {,sos_commands/{kernel.,hardware/}}dmidecode \\\n                                                               && DMIDECODE \"$sosroot\"\n    SOS_CHECKFILE os      \"proc/\"                              && OSINFO    \"$sosroot\"\n    SOS_CHECKFILE kdump   \"\"                                   && KDUMP     \"$sosroot\"\n    SOS_CHECKFILE cpu     \"proc/cpuinfo\"                       && CPUINFO   \"$sosroot\"\n    SOS_CHECKFILE intrupt \"proc/interrupts\"                    && INTERRUPT \"$sosroot\"\n    SOS_CHECKFILE mem     \"proc/meminfo\"                       && MEMINFO   \"$sosroot\"\n    SOS_CHECKFILE disks   \"proc/partitions\"                    && STORAGE   \"$sosroot\"\n    SOS_CHECKFILE mpath   sos_commands/{devicemapper,multipath}/multipath_-v4_-ll \\\n                                                               && MULTIPATH \"$sosroot\"\n    SOS_CHECKFILE lspci   \"lspci\"                              && LSPCI     \"$sosroot\"\n    SOS_CHECKFILE ethtool \"sos_commands/networking/ethtool*\"   && ETHTOOL   \"$sosroot\"\n    SOS_CHECKFILE softirq \"proc/net/softnet_stat\"              && SOFTIRQ   \"$sosroot\"\n    SOS_CHECKFILE netdev  \"proc/net/dev\"                       && NETDEV    \"$sosroot\"\n    SOS_CHECKFILE bonding \"proc/net/bonding/\"                  && BONDING   \"$sosroot\"\n    SOS_CHECKFILE teaming \"sos_commands/teamd/teamdctl_*_state_dump\" \\\n                                                               && TEAMING   \"$sosroot\"\n    SOS_CHECKFILE ip      sos_commands/networking/ip_{,-d_}address \\\n                                                               && {\n                                                                  IPADDR    \"$sosroot\"\n                                                                  XSOS_IP_VERSION=6\n                                                                  IPADDR    \"$sosroot\"; }\n    SOS_CHECKFILE sysctl  \"proc/sys/\"                          && SYSCTL    \"$sosroot\" 2>/dev/null\n    SOS_CHECKFILE ps      \"ps\"                                 && PSCHECK   \"$sosroot\"\n    SOS_CHECKFILE ss      \"sos_commands/networking/ss_-peaonmi\" && SSCHECK  \"$sosroot\"\n    SOS_CHECKFILE firewall \"sos_commands/systemd/systemctl_status_--all\" && FIREWALL   \"$sosroot\"\n    SOS_CHECKFILE ifcfg   \"etc/sysconfig/network-scripts\"      && IFCFG     \"$sosroot\"\n    SOS_CHECKFILE netstat \"/proc/net/netstat\"                  && NETSTAT   \"$sosroot\"\n    \n  # If no SOSREPORT-ROOT provided, run checks against local system\n  else\n    [[ -n $bios ]]    && COND_RUN dmidecode --require_root\n    [[ -n $os ]]      && OSINFO /\n    [[ -n $kdump ]]   && KDUMP /\n    [[ -n $cpu ]]     && CPUINFO /\n    [[ -n $intrupt ]] && INTERRUPT /\n    [[ -n $mem ]]     && MEMINFO /\n    [[ -n $disks ]]   && STORAGE /\n    [[ -n $mpath ]]   && COND_RUN multipath --require_root\n    [[ -n $lspci ]]   && COND_RUN lspci\n    [[ -n $ethtool ]] && COND_RUN ethtool --require_root\n    [[ -n $softirq ]] && SOFTIRQ /\n    [[ -n $netdev ]]  && NETDEV /\n    [[ -n $bonding ]] && BONDING /\n    [[ -n $teaming ]] && TEAMING /\n    [[ -n $ip ]]      && IPADDR\n    [[ -n $all ]]     && XSOS_IP_VERSION=6 IPADDR\n    [[ -n $sysctl ]]  && SYSCTL / 2>/dev/null\n    [[ -n $ps ]]      && PSCHECK\n    [[ -n $ss ]]      && SSCHECK\n    [[ -n $firewall ]]&& FIREWALL\n    [[ -n $ifcfg ]]   && IFCFG\n    [[ -n $netstat ]] && NETSTAT\n\n  fi\n  \n  # If sending output to less or more, let's just append stderr to stdout\n  # If just outputting to term (cat), redirect fd2 to tty\n  case $XSOS_OUTPUT_HANDLER in\n    less*|more)  cat $stderr_file ;;\n    cat)         exec 2>&7\n  esac\n\n} | $XSOS_OUTPUT_HANDLER\n\n# If output going to term (cat), print stderr tmp file contents to stderr\n[[ $XSOS_OUTPUT_HANDLER == cat ]] && cat $stderr_file >&2 || :\n"
  },
  {
    "path": "xsos-bash-completion.bash",
    "content": "# This file is part of xsos, providing intelligent xsos tab-completion for BASH\n# Save it to: /etc/bash_completion.d/\n#\n# Revision date:  2015/07/11 matching up with xsos v0.7.x\n# Latest version: <http://github.com/ryran/xsos>\n#\n# Copyright 2013, 2015 Ryan Sawhill Aroha <rsaw@redhat.com>\n#\n#    This program is free software: you can redistribute it and/or modify\n#    it under the terms of the GNU General Public License as published by\n#    the Free Software Foundation, either version 3 of the License, or\n#    (at your option) any later version.\n#\n#    This program is distributed in the hope that it will be useful,\n#    but WITHOUT ANY WARRANTY; without even the implied warranty of\n#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n#    General Public License <gnu.org/licenses/gpl.html> for more details.\n#\n#-------------------------------------------------------------------------------\n\n_xsos()  {\n  \n  # Variables\n  local curr prev shrtopts longopts\n  \n  # Wipe out COMPREPLY array\n  COMPREPLY=()\n  \n  # Set cur & prev appropriately\n  curr=${COMP_WORDS[COMP_CWORD]}\n  prev=${COMP_WORDS[COMP_CWORD-1]}\n  \n  # Short and long options\n  shrtopts=\"-h -V\n            -a -b -o -k -c -f -m -d -t -l -e -r -n -g -i -s -p -S -F -I -N\n            -6 -q -u -v -w\n            -x -y -z\"\n            \n  longopts=\"--help --version\n            --all --bios --os --kdump --cpu --intrupt --mem --disks --mpath --lspci --ethtool --softirq --netdev --bonding --ip --net --sysctl --ps -ss --firewall --ifcfg --netstat\n            --B --C --F --M --D --T --L --R --N --G --I --P\n            --scrub --ipv6 --wwid --unit --threads --verbose --width\n            --nocolor --less --more\"\n  \n  # Check previous arg to see if we need to do anything special\n  case \"$prev\" in\n  \n      # Disable autocompletion for solo options that can only be run alone\n      -h|--help|-V|--version)\n          return 0\n          ;;\n          \n      # These special opts require filenames as arguments\n      --B|--C|--F|--M|--D|--T|--L|--R|--N|--G|--I|--P)\n          compopt -o plusdirs  # Important!\n          COMPREPLY=( $(compgen -f -- \"$curr\") )\n          return 0\n          ;;\n          \n      # For unit, choices are b-t\n      -u|--unit)\n          COMPREPLY=( $(compgen -W \"b k m g t\" -- \"$curr\") )\n          return 0\n          ;;\n          \n      # For verbosity, choices are 0-4\n      -v|--verbose)\n          COMPREPLY=( $(compgen -W \"0 1 2 3 4\" -- \"$curr\") )\n          return 0\n          ;;\n          \n      # For width, choices are w, 0, or any number\n      -w|--width)\n          COMPREPLY=( $(compgen -W \"w 0\" -- \"$curr\") )\n          return 0\n  \n  esac\n  \n  # Now that we've made it past the options that require args,\n  # we can enable directory completion\n  compopt -o plusdirs\n   \n  if [[ $curr == --* ]]; then\n      # If current arg starts w/2 dashes, attempt to autocomplete long opts\n      COMPREPLY=( $(compgen -W \"$longopts\" -- \"$curr\") )\n      return 0\n  elif [[ $curr == -* ]]; then\n      # Otherwise, if current only starts w/1 dash, attempt autocomplete short opts\n      COMPREPLY=( $(compgen -W \"$shrtopts\" -- \"$curr\") )\n      return 0\n  fi\n}\n\n# Add the names of any xsos aliases (or alternate file-names) to the end of the following line\n# (And remove \"x\" if you have an \"x\" command that *isn't* an alias for xsos)\ncomplete -F _xsos xsos x\n"
  }
]