system-info.sh 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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. # shellcheck disable=SC2153
  93. if [ "${NAME}" = "unknown" ] || [ "${VERSION}" = "unknown" ] || [ "${ID}" = "unknown" ]; then
  94. if [ -f "/etc/lsb-release" ]; then
  95. if [ "${OS_DETECTION}" = "unknown" ]; then
  96. CONTAINER_OS_DETECTION="/etc/lsb-release"
  97. else
  98. CONTAINER_OS_DETECTION="Mixed"
  99. fi
  100. DISTRIB_ID="unknown"
  101. DISTRIB_RELEASE="unknown"
  102. DISTRIB_CODENAME="unknown"
  103. eval "$(grep -E "^(DISTRIB_ID|DISTRIB_RELEASE|DISTRIB_CODENAME)=" </etc/lsb-release)"
  104. if [ "${NAME}" = "unknown" ]; then CONTAINER_NAME="${DISTRIB_ID}"; fi
  105. if [ "${VERSION}" = "unknown" ]; then CONTAINER_VERSION="${DISTRIB_RELEASE}"; fi
  106. if [ "${ID}" = "unknown" ]; then CONTAINER_ID="${DISTRIB_CODENAME}"; fi
  107. fi
  108. if [ -n "$(command -v lsb_release 2>/dev/null)" ]; then
  109. if [ "${OS_DETECTION}" = "unknown" ]; then
  110. CONTAINER_OS_DETECTION="lsb_release"
  111. else
  112. CONTAINER_OS_DETECTION="Mixed"
  113. fi
  114. if [ "${NAME}" = "unknown" ]; then CONTAINER_NAME="$(lsb_release -is 2>/dev/null)"; fi
  115. if [ "${VERSION}" = "unknown" ]; then CONTAINER_VERSION="$(lsb_release -rs 2>/dev/null)"; fi
  116. if [ "${ID}" = "unknown" ]; then CONTAINER_ID="$(lsb_release -cs 2>/dev/null)"; fi
  117. fi
  118. fi
  119. fi
  120. # If Netdata is not running in a container then use the local detection as the host
  121. HOST_OS_DETECTION="unknown"
  122. HOST_NAME="unknown"
  123. HOST_VERSION="unknown"
  124. HOST_VERSION_ID="unknown"
  125. HOST_ID="unknown"
  126. HOST_ID_LIKE="unknown"
  127. if [ "${CONTAINER}" = "unknown" ]; then
  128. for v in NAME ID ID_LIKE VERSION VERSION_ID OS_DETECTION; do
  129. eval "HOST_$v=\$CONTAINER_$v; CONTAINER_$v=none"
  130. done
  131. else
  132. # Otherwise try and use a user-supplied bind-mount into the container to resolve the host details
  133. if [ -e "/host/etc/os-release" ]; then
  134. OS_DETECTION="/etc/os-release"
  135. eval "$(grep -E "^(NAME|ID|ID_LIKE|VERSION|VERSION_ID)=" </host/etc/os-release | sed 's/^/HOST_/')"
  136. HOST_OS_DETECTION="/host/etc/os-release"
  137. fi
  138. if [ "${HOST_NAME}" = "unknown" ] || [ "${HOST_VERSION}" = "unknown" ] || [ "${HOST_ID}" = "unknown" ]; then
  139. if [ -f "/host/etc/lsb-release" ]; then
  140. if [ "${HOST_OS_DETECTION}" = "unknown" ]; then
  141. HOST_OS_DETECTION="/etc/lsb-release"
  142. else
  143. HOST_OS_DETECTION="Mixed"
  144. fi
  145. DISTRIB_ID="unknown"
  146. DISTRIB_RELEASE="unknown"
  147. DISTRIB_CODENAME="unknown"
  148. eval "$(grep -E "^(DISTRIB_ID|DISTRIB_RELEASE|DISTRIB_CODENAME)=" </etc/lsb-release)"
  149. if [ "${HOST_NAME}" = "unknown" ]; then HOST_NAME="${DISTRIB_ID}"; fi
  150. if [ "${HOST_VERSION}" = "unknown" ]; then HOST_VERSION="${DISTRIB_RELEASE}"; fi
  151. if [ "${HOST_ID}" = "unknown" ]; then HOST_ID="${DISTRIB_CODENAME}"; fi
  152. fi
  153. fi
  154. fi
  155. # -------------------------------------------------------------------------------------------------
  156. # Detect information about the CPU
  157. LCPU_COUNT="unknown"
  158. CPU_MODEL="unknown"
  159. CPU_VENDOR="unknown"
  160. CPU_FREQ="unknown"
  161. CPU_INFO_SOURCE="none"
  162. possible_cpu_freq=""
  163. nproc="$(command -v nproc)"
  164. lscpu="$(command -v lscpu)"
  165. lscpu_output=""
  166. dmidecode="$(command -v dmidecode)"
  167. dmidecode_output=""
  168. if [ -n "${lscpu}" ] && lscpu >/dev/null 2>&1 ; then
  169. lscpu_output="$(LC_NUMERIC=C ${lscpu} 2>/dev/null)"
  170. CPU_INFO_SOURCE="lscpu"
  171. LCPU_COUNT="$(echo "${lscpu_output}" | grep "^CPU(s):" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  172. CPU_VENDOR="$(echo "${lscpu_output}" | grep "^Vendor ID:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  173. CPU_MODEL="$(echo "${lscpu_output}" | grep "^Model name:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  174. 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"
  175. if [ "${possible_cpu_freq}" = " MHz" ] ; then
  176. possible_cpu_freq="$(echo "${lscpu_output}" | grep -F "CPU MHz:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | grep -o '^[0-9]*') MHz"
  177. fi
  178. elif [ -n "${dmidecode}" ] && dmidecode -t processor >/dev/null 2>&1 ; then
  179. dmidecode_output="$(${dmidecode} -t processor 2>/dev/null)"
  180. CPU_INFO_SOURCE="dmidecode"
  181. LCPU_COUNT="$(echo "${dmidecode_output}" | grep -F "Thread Count:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  182. CPU_VENDOR="$(echo "${dmidecode_output}" | grep -F "Manufacturer:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  183. CPU_MODEL="$(echo "${dmidecode_output}" | grep -F "Version:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  184. possible_cpu_freq="$(echo "${dmidecode_output}" | grep -F "Current Speed:" | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  185. else
  186. if [ -n "${nproc}" ] ; then
  187. CPU_INFO_SOURCE="nproc"
  188. LCPU_COUNT="$(${nproc})"
  189. elif [ "${KERNEL_NAME}" = FreeBSD ] ; then
  190. CPU_INFO_SOURCE="sysctl"
  191. LCPU_COUNT="$(sysctl -n kern.smp.cpus)"
  192. elif [ -d /sys/devices/system/cpu ] ; then
  193. CPU_INFO_SOURCE="sysfs"
  194. # This is potentially more accurate than checking `/proc/cpuinfo`.
  195. LCPU_COUNT="$(find /sys/devices/system/cpu -mindepth 1 -maxdepth 1 -type d -name 'cpu*' | grep -cEv 'idle|freq')"
  196. elif [ -r /proc/cpuinfo ] ; then
  197. CPU_INFO_SOURCE="procfs"
  198. LCPU_COUNT="$(grep -c ^processor /proc/cpuinfo)"
  199. fi
  200. # If we have GNU uname, we can use that to get CPU info (probably).
  201. if unmae --version 2>/dev/null | grep -qF 'GNU coreutils' ; then
  202. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} uname"
  203. CPU_MODEL="$(uname -p)"
  204. CPU_VENDOR="$(uname -i)"
  205. elif [ "${KERNEL_NAME}" = FreeBSD ] ; then
  206. if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysctl ) ; then
  207. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysctl"
  208. fi
  209. CPU_MODEL="$(sysctl -n hw.model)"
  210. elif [ -r /proc/cpuinfo ] ; then
  211. if ( echo "${CPU_INFO_SOURCE}" | grep -qv procfs ) ; then
  212. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} procfs"
  213. fi
  214. CPU_MODEL="$(grep -F "model name" /proc/cpuinfo | head -n 1 | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  215. CPU_VENDOR="$(grep -F "vendor_id" /proc/cpuinfo | head -n 1 | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  216. fi
  217. fi
  218. if [ -r /sys/devices/system/cpu/cpu0/cpufreq/base_frequency ] ; then
  219. if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysfs ) ; then
  220. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysfs"
  221. fi
  222. CPU_FREQ="$(cat /sys/devices/system/cpu/cpu0/cpufreq/base_frequency)"
  223. elif [ -n "${possible_cpu_freq}" ] ; then
  224. CPU_FREQ="${possible_cpu_freq}"
  225. elif [ -r /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq ] ; then
  226. if ( echo "${CPU_INFO_SOURCE}" | grep -qv sysfs ) ; then
  227. CPU_INFO_SOURCE="${CPU_INFO_SOURCE} sysfs"
  228. fi
  229. CPU_FREQ="$(cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq)"
  230. fi
  231. freq_units="$(echo "${CPU_FREQ}" | cut -f 2 -d ' ')"
  232. case "${freq_units}" in
  233. GHz)
  234. value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')"
  235. CPU_FREQ="$((value*1000*1000*1000))"
  236. ;;
  237. MHz)
  238. value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')"
  239. CPU_FREQ="$((value*1000*1000))"
  240. ;;
  241. KHz)
  242. value="$(echo "${CPU_FREQ}" | cut -f 1 -d ' ')"
  243. CPU_FREQ="$((value*1000))"
  244. ;;
  245. *)
  246. ;;
  247. esac
  248. # -------------------------------------------------------------------------------------------------
  249. # Detect the total system RAM
  250. TOTAL_RAM="unknown"
  251. RAM_DETECTION="none"
  252. if [ "${KERNEL_NAME}" = FreeBSD ] ; then
  253. RAM_DETECTION="sysctl"
  254. TOTAL_RAM="$(sysctl -n hw.physmem)"
  255. elif [ -r /proc/meminfo ] ; then
  256. RAM_DETECTION="procfs"
  257. TOTAL_RAM="$(grep -F MemTotal /proc/meminfo | cut -f 2 -d ':' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | cut -f 1 -d ' ')"
  258. TOTAL_RAM="$((TOTAL_RAM*1024))"
  259. fi
  260. # -------------------------------------------------------------------------------------------------
  261. # Detect the total system disk space
  262. DISK_SIZE="unknown"
  263. DISK_DETECTION="none"
  264. if [ "${KERNEL_NAME}" = "Darwin" ]; then
  265. types='hfs'
  266. if (lsvfs | grep -q apfs) ; then
  267. types="${types},apfs"
  268. fi
  269. if (lsvfs | grep -q ufs) ; then
  270. types="${types},ufs"
  271. fi
  272. DISK_DETECTION="df"
  273. DISK_SIZE=$(($(/bin/df -k -t ${types} | tail -n +2 | sed -E 's/\/dev\/disk([[:digit:]]*)s[[:digit:]]*/\/dev\/disk\1/g' | sort -k 1 | awk -F ' ' '{s=$NF;for(i=NF-1;i>=1;i--)s=s FS $i;print s}' | uniq -f 9 | awk '{print $8}' | tr '\n' '+' | rev | cut -f 2- -d '+' | rev) * 1024))
  274. elif [ "${KERNEL_NAME}" = FreeBSD ] ; then
  275. types='ufs'
  276. if (lsvfs | grep -q zfs) ; then
  277. types="${types},zfs"
  278. fi
  279. DISK_DETECTION="df"
  280. total="$(df -t ${types} -c -k | tail -n 1 | awk '{print $2}')"
  281. DISK_SIZE="$((total * 1024))"
  282. else
  283. if [ -d /sys/block ] && [ -r /proc/devices ] ; then
  284. dev_major_whitelist=''
  285. # This is a list of device names used for block storage devices.
  286. # These translate to the prefixs of files in `/dev` indicating the device type.
  287. # They are sorted by lowest used device major number, with dynamically assigned ones at the end.
  288. # We use this to look up device major numbers in `/proc/devices`
  289. device_names='hd sd mfm ad ftl pd nftl dasd intfl mmcblk ub xvd rfd vbd nvme'
  290. for name in ${device_names} ; do
  291. if grep -qE " ${name}\$" /proc/devices ; then
  292. dev_major_whitelist="${dev_major_whitelist}:$(grep -E "${name}\$" /proc/devices | sed -e 's/^[[:space:]]*//' | cut -f 1 -d ' ' | tr '\n' ':'):"
  293. fi
  294. done
  295. DISK_DETECTION="sysfs"
  296. DISK_SIZE="0"
  297. for disk in /sys/block/* ; do
  298. if [ -r "${disk}/size" ] && \
  299. (echo "${dev_major_whitelist}" | grep -q ":$(cut -f 1 -d ':' "${disk}/dev"):") && \
  300. grep -qv 1 "${disk}/removable"
  301. then
  302. size="$(($(cat "${disk}/size") * 512))"
  303. DISK_SIZE="$((DISK_SIZE + size))"
  304. fi
  305. done
  306. elif df --version 2>/dev/null | grep -qF "GNU coreutils" ; then
  307. DISK_DETECTION="df"
  308. DISK_SIZE=$(($(df -x tmpfs -x devtmpfs -x squashfs -l -B1 --output=source,size | tail -n +2 | sort -u -k 1 | awk '{print $2}' | tr '\n' '+' | head -c -1)))
  309. else
  310. DISK_DETECTION="df"
  311. include_fs_types="ext*|btrfs|xfs|jfs|reiser*|zfs"
  312. DISK_SIZE=$(($(df -T -P | tail -n +2 | sort -u -k 1 | grep "${include_fs_types}" | awk '{print $3}' | tr '\n' '+' | head -c -1) * 1024))
  313. fi
  314. fi
  315. echo "NETDATA_CONTAINER_OS_NAME=${CONTAINER_NAME}"
  316. echo "NETDATA_CONTAINER_OS_ID=${CONTAINER_ID}"
  317. echo "NETDATA_CONTAINER_OS_ID_LIKE=${CONTAINER_ID_LIKE}"
  318. echo "NETDATA_CONTAINER_OS_VERSION=${CONTAINER_VERSION}"
  319. echo "NETDATA_CONTAINER_OS_VERSION_ID=${CONTAINER_VERSION_ID}"
  320. echo "NETDATA_CONTAINER_OS_DETECTION=${CONTAINER_OS_DETECTION}"
  321. echo "NETDATA_HOST_OS_NAME=${HOST_NAME}"
  322. echo "NETDATA_HOST_OS_ID=${HOST_ID}"
  323. echo "NETDATA_HOST_OS_ID_LIKE=${HOST_ID_LIKE}"
  324. echo "NETDATA_HOST_OS_VERSION=${HOST_VERSION}"
  325. echo "NETDATA_HOST_OS_VERSION_ID=${HOST_VERSION_ID}"
  326. echo "NETDATA_HOST_OS_DETECTION=${HOST_OS_DETECTION}"
  327. echo "NETDATA_SYSTEM_KERNEL_NAME=${KERNEL_NAME}"
  328. echo "NETDATA_SYSTEM_KERNEL_VERSION=${KERNEL_VERSION}"
  329. echo "NETDATA_SYSTEM_ARCHITECTURE=${ARCHITECTURE}"
  330. echo "NETDATA_SYSTEM_VIRTUALIZATION=${VIRTUALIZATION}"
  331. echo "NETDATA_SYSTEM_VIRT_DETECTION=${VIRT_DETECTION}"
  332. echo "NETDATA_SYSTEM_CONTAINER=${CONTAINER}"
  333. echo "NETDATA_SYSTEM_CONTAINER_DETECTION=${CONT_DETECTION}"
  334. echo "NETDATA_SYSTEM_CPU_LOGICAL_CPU_COUNT=${LCPU_COUNT}"
  335. echo "NETDATA_SYSTEM_CPU_VENDOR=${CPU_VENDOR}"
  336. echo "NETDATA_SYSTEM_CPU_MODEL=${CPU_MODEL}"
  337. echo "NETDATA_SYSTEM_CPU_FREQ=${CPU_FREQ}"
  338. echo "NETDATA_SYSTEM_CPU_DETECTION=${CPU_INFO_SOURCE}"
  339. echo "NETDATA_SYSTEM_TOTAL_RAM=${TOTAL_RAM}"
  340. echo "NETDATA_SYSTEM_RAM_DETECTION=${RAM_DETECTION}"
  341. echo "NETDATA_SYSTEM_TOTAL_DISK_SIZE=${DISK_SIZE}"
  342. echo "NETDATA_SYSTEM_DISK_DETECTION=${DISK_DETECTION}"