changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > infra / check.sh

changeset 218: f88e8a46080b
parent: 98abb7f50885
child: b1a96e0e3add
author: Richard Westhaver <ellis@rwest.io>
date: Tue, 30 Apr 2024 22:35:33 -0400
permissions: -rwxr-xr-x
description: check mem
1 #!/usr/bin/env sh
2 set -eu
3 main() {
4  need_cmd uname
5  need_cmd mktemp
6  need_cmd chmod
7  need_cmd mkdir
8  need_cmd rm
9  need_cmd rmdir
10  need_cmd tar
11  need_cmd zstd
12  need_cmd hg
13  need_cmd git
14  need_cmd clang
15  need_cmd grep
16  need_cmd awk
17  need_cmd head
18  need_cmd tail
19  host_config_file=host.sxp
20  rm -f $host_config_file
21  check_mem
22  local _mem_total="$RETVAL"
23  check_disk
24  check_mod kvm
25  get_architecture || return 1
26  local _arch="$RETVAL"
27  assert_nz "$_arch" "arch"
28  _write ";; -*- mode:skel -*-"
29  _write ":arch \"$_arch\""
30  kernel_version
31  local _kernel_version="$RETVAL"
32  _write ":kernel \"$_kernel_version\""
33  check_cpus
34  local _num_cpus="$RETVAL"
35  _write ":cpus $_num_cpus"
36  _write ":mem $_mem_total"
37  case "$_arch" in
38  *windows*)
39  _write ":ext \"exe\""
40  ;;
41  *)
42  _write ":ext nil"
43  esac
44 }
45 
46 say() {
47  printf '%s\n' "$1"
48 }
49 
50 _write() {
51  say "$1" >> $host_config_file
52 }
53 
54 err() {
55  say "$1" >&2
56  exit 1
57 }
58 
59 assert_nz() {
60  if [ -z "$1" ]; then err "assert_nz $2"; fi
61 }
62 
63 check_cmd() {
64  command -v "$1" > /dev/null 2>&1
65 }
66 
67 need_cmd() {
68  if ! check_cmd "$1"; then
69  err "need '$1' (command not found)"
70  fi
71 }
72 
73 ensure() {
74  if ! "$@"; then err "command failed: $*"; fi
75 }
76 
77 check_proc() {
78  # Check for /proc by looking for the /proc/self/exe link
79  # This is only run on Linux
80  if ! test -L /proc/self/exe ; then
81  err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc."
82  fi
83 }
84 
85 get_bitness() {
86  # Architecture detection without dependencies beyond coreutils.
87  # ELF files start out "\x7fELF", and the following byte is
88  # 0x01 for 32-bit and
89  # 0x02 for 64-bit.
90  # The printf builtin on some shells like dash only supports octal
91  # escape sequences, so we use those.
92  local _current_exe_head
93  _current_exe_head=$(head -c 5 /proc/self/exe )
94  if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
95  echo 32
96  elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
97  echo 64
98  else
99  err "unknown platform bitness"
100  fi
101 }
102 
103 is_host_amd64_elf() {
104  # ELF e_machine detection without dependencies beyond coreutils.
105  # Two-byte field at offset 0x12 indicates the CPU,
106  # but we're interested in it being 0x3E to indicate amd64, or not that.
107  local _current_exe_machine
108  _current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
109  [ "$_current_exe_machine" = "$(printf '\076')" ]
110 }
111 
112 get_endianness() {
113  local cputype=$1
114  local suffix_eb=$2
115  local suffix_el=$3
116 
117  # detect endianness without od/hexdump, like get_bitness() does.
118  local _current_exe_endianness
119  _current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
120  if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
121  echo "${cputype}${suffix_el}"
122  elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
123  echo "${cputype}${suffix_eb}"
124  else
125  err "unknown platform endianness"
126  fi
127 }
128 
129 get_architecture() {
130  local _ostype _cputype _bitness _arch _clibtype
131  _ostype="$(uname -s)"
132  _cputype="$(uname -m)"
133  _clibtype="gnu"
134 
135  if [ "$_ostype" = Linux ]; then
136  if [ "$(uname -o)" = Android ]; then
137  _ostype=Android
138  fi
139  if ldd --version 2>&1 | grep -q 'musl'; then
140  _clibtype="musl"
141  fi
142  fi
143 
144  if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then
145  # Darwin `uname -m` lies
146  if sysctl hw.optional.x86_64 | grep -q ': 1'; then
147  _cputype=x86_64
148  fi
149  fi
150 
151  if [ "$_ostype" = SunOS ]; then
152  # Both Solaris and illumos presently announce as "SunOS" in "uname -s"
153  # so use "uname -o" to disambiguate. We use the full path to the
154  # system uname in case the user has coreutils uname first in PATH,
155  # which has historically sometimes printed the wrong value here.
156  if [ "$(/usr/bin/uname -o)" = illumos ]; then
157  _ostype=illumos
158  fi
159 
160  # illumos systems have multi-arch userlands, and "uname -m" reports the
161  # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86
162  # systems. Check for the native (widest) instruction set on the
163  # running kernel:
164  if [ "$_cputype" = i86pc ]; then
165  _cputype="$(isainfo -n)"
166  fi
167  fi
168 
169  case "$_ostype" in
170 
171  Android)
172  _ostype=linux-android
173  ;;
174 
175  Linux)
176  check_proc
177  _ostype=unknown-linux-$_clibtype
178  _bitness=$(get_bitness)
179  ;;
180 
181  FreeBSD)
182  _ostype=unknown-freebsd
183  ;;
184 
185  NetBSD)
186  _ostype=unknown-netbsd
187  ;;
188 
189  DragonFly)
190  _ostype=unknown-dragonfly
191  ;;
192 
193  Darwin)
194  _ostype=apple-darwin
195  ;;
196 
197  illumos)
198  _ostype=unknown-illumos
199  ;;
200 
201  MINGW* | MSYS* | CYGWIN* | Windows_NT)
202  _ostype=pc-windows-gnu
203  ;;
204 
205  *)
206  err "unrecognized OS type: $_ostype"
207  ;;
208 
209  esac
210 
211  case "$_cputype" in
212 
213  i386 | i486 | i686 | i786 | x86)
214  _cputype=i686
215  ;;
216 
217  xscale | arm)
218  _cputype=arm
219  if [ "$_ostype" = "linux-android" ]; then
220  _ostype=linux-androideabi
221  fi
222  ;;
223 
224  armv6l)
225  _cputype=arm
226  if [ "$_ostype" = "linux-android" ]; then
227  _ostype=linux-androideabi
228  else
229  _ostype="${_ostype}eabihf"
230  fi
231  ;;
232 
233  armv7l | armv8l)
234  _cputype=armv7
235  if [ "$_ostype" = "linux-android" ]; then
236  _ostype=linux-androideabi
237  else
238  _ostype="${_ostype}eabihf"
239  fi
240  ;;
241 
242  aarch64 | arm64)
243  _cputype=aarch64
244  ;;
245 
246  x86_64 | x86-64 | x64 | amd64)
247  _cputype=x86_64
248  ;;
249 
250  mips)
251  _cputype=$(get_endianness mips '' el)
252  ;;
253 
254  mips64)
255  if [ "$_bitness" -eq 64 ]; then
256  # only n64 ABI is supported for now
257  _ostype="${_ostype}abi64"
258  _cputype=$(get_endianness mips64 '' el)
259  fi
260  ;;
261 
262  ppc)
263  _cputype=powerpc
264  ;;
265 
266  ppc64)
267  _cputype=powerpc64
268  ;;
269 
270  ppc64le)
271  _cputype=powerpc64le
272  ;;
273 
274  s390x)
275  _cputype=s390x
276  ;;
277  riscv64)
278  _cputype=riscv64gc
279  ;;
280  loongarch64)
281  _cputype=loongarch64
282  ;;
283  *)
284  err "unknown CPU type: $_cputype"
285 
286  esac
287 
288  # Detect 64-bit linux with 32-bit userland
289  if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
290  case $_cputype in
291  x86_64)
292  if [ -n "${CPUTYPE:-}" ]; then
293  _cputype="$CPUTYPE"
294  else {
295  # 32-bit executable for amd64 = x32
296  if is_host_amd64_elf; then {
297  echo "This host is running an x32 userland; as it stands, x32 support is poor," 1>&2
298  echo "and there isn't a native toolchain -- you will have to install" 1>&2
299  echo "multiarch compatibility with i686 and/or amd64, then select one" 1>&2
300  echo "by re-running this script with the CPUTYPE environment variable" 1>&2
301  echo "set to i686 or x86_64, respectively." 1>&2
302  exit 1
303  }; else
304  _cputype=i686
305  fi
306  }; fi
307  ;;
308  mips64)
309  _cputype=$(get_endianness mips '' el)
310  ;;
311  powerpc64)
312  _cputype=powerpc
313  ;;
314  aarch64)
315  _cputype=armv7
316  if [ "$_ostype" = "linux-android" ]; then
317  _ostype=linux-androideabi
318  else
319  _ostype="${_ostype}eabihf"
320  fi
321  ;;
322  riscv64gc)
323  err "riscv64 with 32-bit userland unsupported"
324  ;;
325  esac
326  fi
327 
328  if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
329  if ensure grep '^Features' /proc/cpuinfo | grep -q -v neon; then
330  # At least one processor does not have NEON.
331  _cputype=arm
332  fi
333  fi
334 
335  _arch="${_cputype}-${_ostype}"
336 
337  RETVAL="$_arch"
338 }
339 
340 mem_total () {
341  local _mem_total
342  _mem_total=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
343  RETVAL="$_mem_total"
344 }
345 
346 check_mem () {
347  mem_total
348  local _mem_total="$RETVAL"
349  local _mem_min=8388608 # 8Gb in kB
350  if [ "$_mem_total" -lt "$_mem_min" ]; then
351  err "not enough memory: $_mem_total < $_mem_min";
352  fi
353 }
354 
355 disk_free () {
356  local _disk_free
357  _disk_free=$(df . | tail -n1 | awk '{print $4}')
358  RETVAL="${_disk_free}"
359 }
360 
361 check_disk () {
362  disk_free
363  local _disk_free="$RETVAL"
364  local _disk_min=33554432 # in bytes
365  if [ "$_disk_free" -lt "$_disk_min" ]; then
366  err "not enough disk space: $_disk_free < $_disk_min"
367  fi
368 }
369 
370 kernel_version () {
371  local _kernel_version
372  _kernel_version=$(uname -r)
373  RETVAL="$_kernel_version"
374 }
375 
376 check_mod () {
377  if ! lsmod | grep -wq "$1"; then
378  err "kernel module $1 isn't loaded"
379  fi
380 }
381 
382 num_cpus () {
383  local _num_cpus
384  _num_cpus=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null)
385  RETVAL="$_num_cpus"
386  # sysctl -n hw.ncpu # nproc --all
387 }
388 
389 check_cpus () {
390  num_cpus
391  local _num_cpus="$RETVAL"
392  local _min_cpus=8
393  if [ "$_num_cpus" -lt "$_min_cpus" ]; then
394  err "not enough cpu threads ($_num_cpus < $_min_cpus)"
395  fi
396 }
397 
398 main "$@" || exit 1