system-info.sh 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #!/usr/bin/env sh
  2. # -------------------------------------------------------------------------------------------------
  3. # detect the kernel
  4. KERNEL_NAME="$(uname -s)"
  5. KERNEL_VERSION="$(uname -r)"
  6. ARCHITECTURE="$(uname -m)"
  7. # -------------------------------------------------------------------------------------------------
  8. # detect the virtualization
  9. if [ -z "${VIRTUALIZATION}" ]; then
  10. VIRTUALIZATION="unknown"
  11. VIRT_DETECTION="none"
  12. if [ -n "$(command -v systemd-detect-virt 2>/dev/null)" ]; then
  13. VIRTUALIZATION="$(systemd-detect-virt -v)"
  14. VIRT_DETECTION="systemd-detect-virt"
  15. CONTAINER="$(systemd-detect-virt -c)"
  16. CONT_DETECTION="systemd-detect-virt"
  17. else
  18. if grep -q "^flags.*hypervisor" /proc/cpuinfo 2>/dev/null; then
  19. VIRTUALIZATION="hypervisor"
  20. VIRT_DETECTION="/proc/cpuinfo"
  21. elif [ -n "$(command -v dmidecode)" ]; then
  22. # Virtualization detection from https://unix.stackexchange.com/questions/89714/easy-way-to-determine-virtualization-technology
  23. # This only works as root
  24. if dmidecode -s system-product-name 2>/dev/null | grep -q "VMware\|Virtual\|KVM\|Bochs"; then
  25. VIRTUALIZATION="$(dmidecode -s system-product-name)"
  26. VIRT_DETECTION="dmidecode"
  27. fi
  28. fi
  29. fi
  30. else
  31. # Passed from outside - probably in docker run
  32. VIRT_DETECTION="provided"
  33. fi
  34. # -------------------------------------------------------------------------------------------------
  35. # detect containers with heuristics
  36. CONTAINER="unknown"
  37. CONT_DETECTION="none"
  38. if [ "${CONTAINER}" = "unknown" ]; then
  39. if [ -f /proc/1/sched ] ; then
  40. IFS='(, ' read -r process _ </proc/1/sched
  41. if [ "${process}" = "netdata" ]; then
  42. CONTAINER="container"
  43. CONT_DETECTION="process"
  44. fi
  45. fi
  46. # ubuntu and debian supply /bin/running-in-container
  47. # https://www.apt-browse.org/browse/ubuntu/trusty/main/i386/upstart/1.12.1-0ubuntu4/file/bin/running-in-container
  48. if /bin/running-in-container >/dev/null 2>&1; then
  49. CONTAINER="container"
  50. CONT_DETECTION="/bin/running-in-container"
  51. fi
  52. # lxc sets environment variable 'container'
  53. #shellcheck disable=SC2154
  54. if [ -n "${container}" ]; then
  55. CONTAINER="lxc"
  56. CONT_DETECTION="containerenv"
  57. fi
  58. # docker creates /.dockerenv
  59. # http://stackoverflow.com/a/25518345
  60. if [ -f "/.dockerenv" ]; then
  61. CONTAINER="docker"
  62. CONT_DETECTION="dockerenv"
  63. fi
  64. fi
  65. # -------------------------------------------------------------------------------------------------
  66. # detect the operating system
  67. # Initially assume all OS detection values are for a container, these are moved later if we are bare-metal
  68. CONTAINER_OS_DETECTION="unknown"
  69. CONTAINER_NAME="unknown"
  70. CONTAINER_VERSION="unknown"
  71. CONTAINER_VERSION_ID="unknown"
  72. CONTAINER_ID="unknown"
  73. CONTAINER_ID_LIKE="unknown"
  74. if [ "${KERNEL_NAME}" = "Darwin" ]; then
  75. CONTAINER_ID=$(sw_vers -productName)
  76. CONTAINER_ID_LIKE="mac"
  77. CONTAINER_NAME="mac"
  78. CONTAINER_VERSION=$(sw_vers -productVersion)
  79. CONTAINER_OS_DETECTION="sw_vers"
  80. elif [ "${KERNEL_NAME}" = "FreeBSD" ]; then
  81. CONTAINER_ID="FreeBSD"
  82. CONTAINER_ID_LIKE="FreeBSD"
  83. CONTAINER_NAME="FreeBSD"
  84. CONTAINER_OS_DETECTION="uname"
  85. CONTAINER_VERSION=$(uname -r)
  86. KERNEL_VERSION=$(uname -K)
  87. else
  88. if [ -f "/etc/os-release" ]; then
  89. eval "$(grep -E "^(NAME|ID|ID_LIKE|VERSION|VERSION_ID)=" </etc/os-release | sed 's/^/CONTAINER_/')"
  90. CONTAINER_OS_DETECTION="/etc/os-release"
  91. fi
  92. if [ "${NAME}" = "unknown" ] || [ "${VERSION}" = "unknown" ] || [ "${ID}" = "unknown" ]; then
  93. if [ -f "/etc/lsb-release" ]; then
  94. if [ "${OS_DETECTION}" = "unknown" ]; then
  95. CONTAINER_OS_DETECTION="/etc/lsb-release"
  96. else
  97. CONTAINER_OS_DETECTION="Mixed"
  98. fi
  99. DISTRIB_ID="unknown"
  100. DISTRIB_RELEASE="unknown"
  101. DISTRIB_CODENAME="unknown"
  102. eval "$(grep -E "^(DISTRIB_ID|DISTRIB_RELEASE|DISTRIB_CODENAME)=" </etc/lsb-release)"
  103. if [ "${NAME}" = "unknown" ]; then CONTAINER_NAME="${DISTRIB_ID}"; fi
  104. if [ "${VERSION}" = "unknown" ]; then CONTAINER_VERSION="${DISTRIB_RELEASE}"; fi
  105. if [ "${ID}" = "unknown" ]; then CONTAINER_ID="${DISTRIB_CODENAME}"; fi
  106. fi
  107. if [ -n "$(command -v lsb_release 2>/dev/null)" ]; then
  108. if [ "${OS_DETECTION}" = "unknown" ]; then
  109. CONTAINER_OS_DETECTION="lsb_release"
  110. else
  111. CONTAINER_OS_DETECTION="Mixed"
  112. fi
  113. if [ "${NAME}" = "unknown" ]; then CONTAINER_NAME="$(lsb_release -is 2>/dev/null)"; fi
  114. if [ "${VERSION}" = "unknown" ]; then CONTAINER_VERSION="$(lsb_release -rs 2>/dev/null)"; fi
  115. if [ "${ID}" = "unknown" ]; then CONTAINER_ID="$(lsb_release -cs 2>/dev/null)"; fi
  116. fi
  117. fi
  118. fi
  119. # If Netdata is not running in a container then use the local detection as the host
  120. HOST_OS_DETECTION="unknown"
  121. HOST_NAME="unknown"
  122. HOST_VERSION="unknown"
  123. HOST_VERSION_ID="unknown"
  124. HOST_ID="unknown"
  125. HOST_ID_LIKE="unknown"
  126. if [ "${CONTAINER}" = "unknown" ]; then
  127. for v in NAME ID ID_LIKE VERSION VERSION_ID OS_DETECTION; do
  128. eval "HOST_$v=\$CONTAINER_$v; CONTAINER_$v=none"
  129. done
  130. else
  131. # Otherwise try and use a user-supplied bind-mount into the container to resolve the host details
  132. if [ -e "/host/etc/os-release" ]; then
  133. OS_DETECTION="/etc/os-release"
  134. eval "$(grep -E "^(NAME|ID|ID_LIKE|VERSION|VERSION_ID)=" </host/etc/os-release | sed 's/^/HOST_/')"
  135. HOST_OS_DETECTION="/host/etc/os-release"
  136. fi
  137. if [ "${HOST_NAME}" = "unknown" ] || [ "${HOST_VERSION}" = "unknown" ] || [ "${HOST_ID}" = "unknown" ]; then
  138. if [ -f "/host/etc/lsb-release" ]; then
  139. if [ "${HOST_OS_DETECTION}" = "unknown" ]; then
  140. HOST_OS_DETECTION="/etc/lsb-release"
  141. else
  142. HOST_OS_DETECTION="Mixed"
  143. fi
  144. DISTRIB_ID="unknown"
  145. DISTRIB_RELEASE="unknown"
  146. DISTRIB_CODENAME="unknown"
  147. eval "$(grep -E "^(DISTRIB_ID|DISTRIB_RELEASE|DISTRIB_CODENAME)=" </etc/lsb-release)"
  148. if [ "${HOST_NAME}" = "unknown" ]; then HOST_NAME="${DISTRIB_ID}"; fi
  149. if [ "${HOST_VERSION}" = "unknown" ]; then HOST_VERSION="${DISTRIB_RELEASE}"; fi
  150. if [ "${HOST_ID}" = "unknown" ]; then HOST_ID="${DISTRIB_CODENAME}"; fi
  151. fi
  152. fi
  153. fi
  154. # -------------------------------------------------------------------------------------------------
  155. # Detect information about the CPU
  156. LCPU_COUNT="unknown"
  157. CPU_MODEL="unknown"
  158. CPU_VENDOR="unknown"
  159. CPU_FREQ="unknown"
  160. CPU_INFO_SOURCE="none"
  161. possible_cpu_freq=""
  162. nproc="$(command -v nproc)"
  163. lscpu="$(command -v lscpu)"
  164. lscpu_output=""
  165. dmidecode="$(command -v dmidecode)"
  166. dmidecode_output=""
  167. if [ -n "${lscpu}" ] && lscpu >/dev/null 2>&1 ; then
  168. lscpu_output="$(LC_NUMERIC=C ${lscpu} 2>/dev/null)"
  169. CPU_INFO_SOURCE="lscpu"
  170. LCPU_COUNT="$(echo "${lscpu_output}" | grep "^CPU(s):" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  171. CPU_VENDOR="$(echo "${lscpu_output}" | grep "^Vendor ID:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  172. CPU_MODEL="$(echo "${lscpu_output}" | grep "^Model name:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  173. possible_cpu_freq="$(echo "${lscpu_output}" | grep -F "CPU max MHz:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | grep -o '^[0-9]*') MHz"
  174. elif [ -n "${dmidecode}" ] && dmidecode -t processor >/dev/null 2>&1 ; then
  175. dmidecode_output="$(${dmidecode} -t processor 2>/dev/null)"
  176. CPU_INFO_SOURCE="dmidecode"
  177. LCPU_COUNT="$(echo "${dmidecode_output}" | grep -F "Thread Count:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  178. CPU_VENDOR="$(echo "${dmidecode_output}" | grep -F "Manufacturer:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  179. CPU_MODEL="$(echo "${dmidecode_output}" | grep -F "Version:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  180. possible_cpu_freq="$(echo "${dmidecode_output}" | grep -F "Current Speed:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  181. else
  182. if [ -n "${nproc}" ] ; then
  183. CPU_INFO_SOURCE="nproc"
  184. LCPU_COUNT="$(${nproc})"
  185. elif [ "${KERNEL_NAME}" = FreeBSD ] ; then
  186. CPU_INFO_SOURCE="sysctl"
  187. LCPU_COUNT="$(sysctl -n kern.smp.cpus)"
  188. elif [ -d /sys/devices/system/cpu ] ; then
  189. CPU_INFO_SOURCE="sysfs"
  190. # This is potentially more accurate than checking `/proc/cpuinfo`.
  191. LCPU_COUNT="$(find /sys/devices/system/cpu -mindepth 1 -maxdepth 1 -type d -name 'cpu*' | grep -cEv 'idle|freq')"
  192. elif [ -r /proc/cpuinfo ] ; then
  193. CPU_INFO_SOURCE="procfs"
  194. LCPU_COUNT="$(grep -c ^processor /proc/cpuinfo)"
  195. fi
  196. # If we have GNU uname, we can use that to get CPU info (probably).
  197. if unmae --version 2>/dev/null | grep -qF 'GNU coreutils' ; then
  198. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} uname"
  199. CPU_MODEL="$(uname -p)"
  200. CPU_VENDOR="$(uname -i)"
  201. elif [ "${KERNEL_NAME}" = FreeBSD ] ; then
  202. if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysctl ) ; then
  203. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysctl"
  204. fi
  205. CPU_MODEL="$(sysctl -n hw.model)"
  206. elif [ -r /proc/cpuinfo ] ; then
  207. if ( echo "${CPU_INFO_SOURCE}" | grep -qv procfs ) ; then
  208. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} procfs"
  209. fi
  210. CPU_MODEL="$(grep -F "model name" /proc/cpuinfo | head -n 1 | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  211. CPU_VENDOR="$(grep -F "vendor_id" /proc/cpuinfo | head -n 1 | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  212. fi
  213. fi
  214. if [ -r /sys/devices/system/cpu/cpu0/cpufreq/base_frequency ] ; then
  215. if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysfs ) ; then
  216. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysfs"
  217. fi
  218. CPU_FREQ="$(cat /sys/devices/system/cpu/cpu0/cpufreq/base_frequency)"
  219. elif [ -n "${possible_cpu_freq}" ] ; then
  220. CPU_FREQ="${possible_cpu_freq}"
  221. elif [ -r /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq ] ; then
  222. if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysfs ) ; then
  223. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysfs"
  224. fi
  225. CPU_FREQ="$(cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq)"
  226. fi
  227. freq_units="$(echo "${CPU_FREQ}" | cut -f 2 -d ' ')"
  228. case "${freq_units}" in
  229. GHz)
  230. value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')"
  231. CPU_FREQ="$((value*1000*1000*1000))"
  232. ;;
  233. MHz)
  234. value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')"
  235. CPU_FREQ="$((value*1000*1000))"
  236. ;;
  237. KHz)
  238. value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')"
  239. CPU_FREQ="$((value*1000))"
  240. ;;
  241. *)
  242. ;;
  243. esac
  244. # -------------------------------------------------------------------------------------------------
  245. # Detect the total system RAM
  246. TOTAL_RAM="unknown"
  247. RAM_DETECTION="none"
  248. if [ "${KERNEL_NAME}" = FreeBSD ] ; then
  249. RAM_DETECTION="sysctl"
  250. TOTAL_RAM="$(sysctl -n hw.physmem)"
  251. elif [ -r /proc/meminfo ] ; then
  252. RAM_DETECTION="procfs"
  253. TOTAL_RAM="$(grep -F MemTotal /proc/meminfo | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | cut -f 1 -d ' ')"
  254. TOTAL_RAM="$((TOTAL_RAM*1024))"
  255. fi
  256. # -------------------------------------------------------------------------------------------------
  257. # Detect the total system disk space
  258. DISK_SIZE="unknown"
  259. DISK_DETECTION="none"
  260. if [ "${KERNEL_NAME}" = "Darwin" ]; then
  261. types='hfs'
  262. if (lsvfs | grep -q apfs) ; then
  263. types="${types},apfs"
  264. fi
  265. if (lsvfs | grep -q ufs) ; then
  266. types="${types},ufs"
  267. fi
  268. DISK_DETECTION="df"
  269. total="$(/bin/df -k -t ${types} | tail -n +1 | awk '{s+=$2} END {print s}')"
  270. DISK_SIZE="$((total * 1024))"
  271. elif [ "${KERNEL_NAME}" = FreeBSD ] ; then
  272. types='ufs'
  273. if (lsvfs | grep -q zfs) ; then
  274. types="${types},zfs"
  275. fi
  276. DISK_DETECTION="df"
  277. total="$(df -t ${types} -c -k | tail -n 1 | awk '{print $2}')"
  278. DISK_SIZE="$((total * 1024))"
  279. else
  280. if [ -d /sys/block ] ; then
  281. # List of device majors we actually count towards total disk space.
  282. # The meanings of these can be found in `Documentation/admin-guide/devices.txt` in the Linux sources.
  283. # The ':' surrounding each number are important for matching.
  284. dev_major_whitelist=':3:8:9:21:22:28:31:33:34:44:45:47:48:49:50:51:52:53:54:55:56:57:65:66:67:68:69:70:71:72:73:74:75:76:77:78:79:88:89:90:91:93:94:96:98:101:104:105:106:107:108:109:110:111:112:114:116:128:129:130:131:132:134:135:136:137:138:139:140:141:142:143:153:160:161:179:180:202:256:257:'
  285. if [ "${VIRTUALIZATION}" != "unknown" ] ; then
  286. # We're running virtualized, add the local range of device major numbers so that we catch paravirtualized block devices.
  287. dev_major_whitelist="${dev_major_whitelist}240:241:242:243:244:245:246:247:248:249:250:251:252:253:254:"
  288. fi
  289. DISK_DETECTION="sysfs"
  290. DISK_SIZE="0"
  291. for disk in /sys/block/* ; do
  292. if [ -r "${disk}/size" ] && \
  293. (echo "${dev_major_whitelist}" | grep -q ":$(cut -f 1 -d ':' "${disk}/dev"):") && \
  294. grep -qv 1 "${disk}/removable"
  295. then
  296. size="$(cat "${disk}/size")"
  297. DISK_SIZE="$((DISK_SIZE + size))"
  298. fi
  299. done
  300. elif df --version 2>/dev/null | grep -qF "GNU coreutils" ; then
  301. DISK_DETECTION="df"
  302. DISK_SIZE="$(df -x tmpfs -x devtmpfs -x squashfs -l --total -B1 --output=size | tail -n 1 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  303. else
  304. DISK_DETECTION="df"
  305. include_fs_types="ext*|btrfs|xfs|jfs|reiser*|zfs"
  306. total="$(df -T -P | grep "${include_fs_types}" | awk '{s+=$3} END {print s}')"
  307. DISK_SIZE="$((total * 1024))"
  308. fi
  309. fi
  310. echo "NETDATA_CONTAINER_OS_NAME=${CONTAINER_NAME}"
  311. echo "NETDATA_CONTAINER_OS_ID=${CONTAINER_ID}"
  312. echo "NETDATA_CONTAINER_OS_ID_LIKE=${CONTAINER_ID_LIKE}"
  313. echo "NETDATA_CONTAINER_OS_VERSION=${CONTAINER_VERSION}"
  314. echo "NETDATA_CONTAINER_OS_VERSION_ID=${CONTAINER_VERSION_ID}"
  315. echo "NETDATA_CONTAINER_OS_DETECTION=${CONTAINER_OS_DETECTION}"
  316. echo "NETDATA_HOST_OS_NAME=${HOST_NAME}"
  317. echo "NETDATA_HOST_OS_ID=${HOST_ID}"
  318. echo "NETDATA_HOST_OS_ID_LIKE=${HOST_ID_LIKE}"
  319. echo "NETDATA_HOST_OS_VERSION=${HOST_VERSION}"
  320. echo "NETDATA_HOST_OS_VERSION_ID=${HOST_VERSION_ID}"
  321. echo "NETDATA_HOST_OS_DETECTION=${HOST_OS_DETECTION}"
  322. echo "NETDATA_SYSTEM_KERNEL_NAME=${KERNEL_NAME}"
  323. echo "NETDATA_SYSTEM_KERNEL_VERSION=${KERNEL_VERSION}"
  324. echo "NETDATA_SYSTEM_ARCHITECTURE=${ARCHITECTURE}"
  325. echo "NETDATA_SYSTEM_VIRTUALIZATION=${VIRTUALIZATION}"
  326. echo "NETDATA_SYSTEM_VIRT_DETECTION=${VIRT_DETECTION}"
  327. echo "NETDATA_SYSTEM_CONTAINER=${CONTAINER}"
  328. echo "NETDATA_SYSTEM_CONTAINER_DETECTION=${CONT_DETECTION}"
  329. echo "NETDATA_CPU_LOGICAL_CPU_COUNT=${LCPU_COUNT}"
  330. echo "NETDATA_CPU_VENDOR=${CPU_VENDOR}"
  331. echo "NETDATA_CPU_MODEL=${CPU_MODEL}"
  332. echo "NETDATA_CPU_FREQ=${CPU_FREQ}"
  333. echo "NETDATA_CPU_DETECTION=${CPU_INFO_SOURCE}"
  334. echo "NETDATA_TOTAL_RAM=${TOTAL_RAM}"
  335. echo "NETDATA_RAM_DETECTION=${RAM_DETECTION}"
  336. echo "NETDATA_TOTAL_DISK_SIZE=${DISK_SIZE}"
  337. echo "NETDATA_DISK_DETECTION=${DISK_DETECTION}"