Run LXC CentOS 8 container with bridged network under CentOS 8

The LXC container software comes to CentOS 8 with the EPEL 8 repository. LXC is a multiprocesses container, which offers to boot a Linux distribution under container isolation. It is very similar to systemd-nspawn and a bit different from docker containers. LXC containers are used when multiple processes are needed under one container only. In most cases, the LXC container is a fully-featured Linux distribution (systemd or SysV, i.e. init) booted under a Linux container.
There are several major differences between docker/podman containers and LXC:

  • Multiprocesses.
  • Easy configuration modification. Even hot-plugin supported.
  • Unprivileged Linux containers.
  • Complex network setups. Multiple network interfaces connected to different networks, for example.
  • Live systemd, i.e. systemd or SysV init are booted as usual. Much of the software rellies on systemd/udev features and in many cases, it is really hard to run a software without a systemd or init process

Here are the steps to boot a CentOS 8 container under CentOS 8 host server:

STEP 1) Install EPEL repository.

EPEL CentOS 8 repository now includes LXC 3.0 software.

dnf install -y epel-release

STEP 2) Install LXC software and start LXC service.

At present, the LXC software version is 3.0.4. The package lxc-templates includes template scripts to create a Linux distribution environment like CentOS, Ubuntu, Debian, Gentoo, ArchLinux, Oracle, Alpine, and many others and it also includes the configuration templates to start these Linux distributions.

dnf install -y lxc lxc-templates
dnf install -y wget tar

The wget and tar are required if LXC templates installation is going to be performed.

STEP 3) Create a CentOS 8 container with the help of LXC templates and run it.

Use the lxc-templates to prepare a CentOS 8 container environment. The currently available containers are listed here http://images.linuxcontainers.org/. Check out the URL and choose the right container. Here the CentOS 8 amd64 is used.

lxc-create --template download -n mycontainer -- --dist centos --release 8 --arch amd64 --keyserver hkp://keyserver.ubuntu.com

Keep on reading!

Repairing damaged backup GPT with gdisk

Problem with network shared storage could lead to a damaged file system or even GPT tables, so the gdisk may help in this case.
Here it is a nasty the error:

[root@srv1 ~]# kpartx /dev/loop0
Alternate GPT is invalid, using primary GPT.
loop0p1 : 0 83881984 /dev/loop0 2048
[root@srv1 ~]# parted /dev/loop0
GNU Parted 3.1
Using /dev/loop0
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) p                                                                
Error: The backup GPT table is corrupt, but the primary appears OK, so that will be used.
OK/Cancel? OK                                                             
Model: Loopback device (loopback)
Disk /dev/loop0: 42.9GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  42.9GB  42.9GB               primary

(parted)

So parted reports the backup GPT is damaged, but how to fix it? The solution is to use gdisk and use write “w” command in it. gdisk also shows the exact error with the GPT table with “v” option:

[root@srv1 ~]# gdisk 
GPT fdisk (gdisk) version 0.8.10

Type device filename, or press <Enter> to exit: /dev/loop0
Warning! Main and backup partition tables differ! Use the 'c' and 'e' options
on the recovery & transformation menu to examine the two tables.

Warning! One or more CRCs don't match. You should repair the disk!

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: damaged

****************************************************************************
Caution: Found protective or hybrid MBR and corrupt GPT. Using GPT, but disk
verification and recovery are STRONGLY recommended.
****************************************************************************

Command (? for help): p
Disk /dev/loop0: 83886080 sectors, 40.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 7EDF123B-FBC4-4C09-B636-922BD165F862
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 83886046
Partitions will be aligned on 2048-sector boundaries
Total free space is 4029 sectors (2.0 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048        83884031   40.0 GiB    0700  primary

Command (? for help): v

Caution: The CRC for the backup partition table is invalid. This table may
be corrupt. This program will automatically create a new backup partition
table when you save your partitions.

Identified 1 problems!

Command (? for help): p
Disk /dev/loop0: 83886080 sectors, 40.0 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 7EDF123B-FBC4-4C09-B636-922BD165F862
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 83886046
Partitions will be aligned on 2048-sector boundaries
Total free space is 4029 sectors (2.0 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048        83884031   40.0 GiB    0700  primary

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to /dev/loop0.

Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.
The operation has completed successfully.

And the GPT backup in this loop device is fixed. Executing parted again reports no problems:

[root@srv1 ~]# parted /dev/loop0 print
Model: Loopback device (loopback)
Disk /dev/loop0: 42.9GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  42.9GB  42.9GB               primary

Verify also reports nor error. More options are available:

[root@srv1 ~]# gdisk /dev/loop0
GPT fdisk (gdisk) version 0.8.10

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): h
b  back up GPT data to a file
c  change a partition's name
d  delete a partition
i  show detailed information on a partition
l  list known partition types
n  add a new partition
o  create a new empty GUID partition table (GPT)
p  print the partition table
q  quit without saving changes
r  recovery and transformation options (experts only)
s  sort partitions
t  change a partition's type code
v  verify disk
w  write table to disk and exit
x  extra functionality (experts only)
?  print this menu

Command (? for help): v

No problems found. 4029 free sectors (2.0 MiB) available in 2
segments, the largest of which is 2015 (1007.5 KiB) in size.

Command (? for help): q

display packages from the Gentoo emerge resume list

A quick tip and an easy hack to see the emerge resume list, which will be used by the “emerge –resume” command. There are two resume lists – resume and resume_backup in the binary file /var/cache/edb/mtimedb.
The first two commands are python 3+.
The resume and resume_backup lists

python -c 'import portage; print(portage.mtimedb.get("resume", {}).get("mergelist"))'
python -c 'import portage; print(portage.mtimedb.get("resume_backup", {}).get("mergelist"))'

If you need the command for the python 2 you should use the following:

python -c 'import portage; print portage.mtimedb.get("resume", {}).get("mergelist")'
python -c 'import portage; print portage.mtimedb.get("resume_backup", {}).get("mergelist")'

Real world example

Resume list for

desktop ~ # emerge -v --nodeps $(qlist -IC|grep dev-qt)

These are the packages that would be merged, in order:

[ebuild     U  ] dev-qt/designer-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="declarative webkit -debug -test" 8,493 KiB
[ebuild     U  ] dev-qt/linguist-tools-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="qml -debug -test" 0 KiB
[ebuild     U  ] dev-qt/qdbus-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 0 KiB
[ebuild     U  ] dev-qt/qtbluetooth-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -qml -test" 2,727 KiB
[ebuild   R    ] dev-qt/qtchooser-66::gentoo  USE="-test" 32 KiB
[ebuild     U  ] dev-qt/qtconcurrent-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 48,549 KiB
[ebuild     U  ] dev-qt/qtcore-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="icu -debug (-systemd) -test" 0 KiB
[ebuild     U  ] dev-qt/qtdbus-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 0 KiB
[ebuild     U  ] dev-qt/qtdeclarative-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="jit widgets -debug -gles2 -localstorage -test" 20,753 KiB
[ebuild     U  ] dev-qt/qtgraphicaleffects-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 13,713 KiB
[ebuild     U  ] dev-qt/qtgui-5.14.0-r1:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="accessibility dbus egl evdev gif ibus jpeg libinput png udev vnc wayland%* xcb -debug -eglfs -gles2 -test -tslib -tuio" 0 KiB
[ebuild     U  ] dev-qt/qthelp-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 0 KiB
[ebuild     U  ] dev-qt/qtimageformats-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="mng -debug -test (-jpeg2k%)" 1,768 KiB
[ebuild     U  ] dev-qt/qtlocation-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 5,974 KiB
[ebuild   R    ] dev-qt/qtlockedfile-2.4.1_p20171024::gentoo  USE="-doc" 694 KiB
[ebuild     U  ] dev-qt/qtmultimedia-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="alsa gstreamer openal pulseaudio qml widgets -debug -gles2 -test" 3,671 KiB
[ebuild     U  ] dev-qt/qtnetwork-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="libproxy networkmanager ssl -bindist -connman -debug -sctp -test" 0 KiB
[ebuild     U  ] dev-qt/qtopengl-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -gles2 -test" 0 KiB
[ebuild     U  ] dev-qt/qtpaths-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 0 KiB
[ebuild     U  ] dev-qt/qtpositioning-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="qml -debug -geoclue -test" 0 KiB
[ebuild     U  ] dev-qt/qtprintsupport-5.14.0-r1:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="cups -debug -gles2 -test" 0 KiB
[ebuild     U  ] dev-qt/qtquickcontrols2-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test -widgets" 7,947 KiB
[ebuild     U  ] dev-qt/qtquickcontrols-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="widgets -debug -test" 5,843 KiB
[ebuild     U  ] dev-qt/qtscript-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="jit scripttools -debug -test" 2,584 KiB
[ebuild     U  ] dev-qt/qtsensors-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -qml -test" 1,996 KiB
[ebuild   R    ] dev-qt/qtsingleapplication-2.6.1_p20171024::gentoo  USE="X -doc" 0 KiB
[ebuild     U  ] dev-qt/qtspeech-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 99 KiB
[ebuild     U  ] dev-qt/qtsql-5.14.0:5/5.14.0::gentoo [5.12.2:5/5.12.2::gentoo] USE="mysql sqlite -debug -freetds -oci8 -odbc -postgres -test" 0 KiB
[ebuild     U  ] dev-qt/qtsvg-5.14.0-r1:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 1,822 KiB
[ebuild     U  ] dev-qt/qttest-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 0 KiB
[ebuild     U  ] dev-qt/qttranslations-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 1,302 KiB
[ebuild     U  ] dev-qt/qtvirtualkeyboard-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="spell xcb -debug -handwriting -test" 10,705 KiB
[ebuild     U  ] dev-qt/qtwayland-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="libinput xcomposite -debug -test" 532 KiB
[ebuild     U  ] dev-qt/qtwebchannel-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="qml -debug -test" 192 KiB
[ebuild     U  ] dev-qt/qtwebengine-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="alsa pulseaudio system-icu widgets -bindist -debug -designer -jumbo-build -pax_kernel -system-ffmpeg -test (-geolocation%*)" 235,904 KiB
[ebuild     U  ] dev-qt/qtwebkit-5.212.0_pre20190629:5/5.212::gentoo [5.212.0_pre20180120:5/5.212::gentoo] USE="X geolocation hyphen jit multimedia opengl printsupport qml -gles2 -gstreamer -nsplugin -orientation -webp" 12,166 KiB
[ebuild     U  ] dev-qt/qtwidgets-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="gtk png xcb -debug -gles2 -test" 0 KiB
[ebuild     U  ] dev-qt/qtx11extras-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 125 KiB
[ebuild     U  ] dev-qt/qtxml-5.14.0:5/5.14::gentoo [5.12.2:5/5.12::gentoo] USE="-debug -test" 0 KiB
[ebuild     U  ] dev-qt/qtxmlpatterns-5.14.0:5/5.14::gentoo [5.11.1:5/5.11::gentoo] USE="-debug -qml% -test" 1,362 KiB

Total: 40 packages (37 upgrades, 3 reinstalls), Size of downloads: 388,941 KiB


>>> Verifying ebuild manifests
>>> Running pre-merge checks for dev-qt/qtwebkit-5.212.0_pre20190629

>>> Emerging (1 of 40) dev-qt/designer-5.14.0::gentoo
 * Fetching files in the background.
 * To view fetch progress, run in another terminal:
 * tail -f /var/log/emerge-fetch.log
 * qttools-everywhere-src-5.14.0.tar.xz BLAKE2B SHA512 size ;-) ...                                                                                                  [ ok ]
!!! Failed to set new SELinux execution context. Is your current SELinux context allowed to run Portage?
>>> Unpacking source...
>>> Unpacking qttools-everywhere-src-5.14.0.tar.xz to /var/tmp/portage/dev-qt/designer-5.14.0/work
^C

Exiting on signal 2
sandbox:stop  caught signal 2 in pid 22886
sandbox:stop  Send signal 4 more times to force SIGKILL
Sandboxed process killed by signal: Interrupt
^C * The ebuild phase 'die_hooks' has been killed by signal 2.

 * Messages for package dev-qt/designer-5.14.0:

We interrupted it on purpose with Ctrl+C.

The output of the above python command:

desktop ~ # python -c 'import portage; print(portage.mtimedb.get("resume", {}).get("mergelist"))'
[['ebuild', '/', 'dev-qt/designer-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/linguist-tools-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qdbus-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtbluetooth-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtchooser-66', 'merge'], ['ebuild', '/', 'dev-qt/qtconcurrent-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtcore-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtdbus-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtdeclarative-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtgraphicaleffects-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtgui-5.14.0-r1', 'merge'], ['ebuild', '/', 'dev-qt/qthelp-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtimageformats-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtlocation-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtlockedfile-2.4.1_p20171024', 'merge'], ['ebuild', '/', 'dev-qt/qtmultimedia-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtnetwork-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtopengl-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtpaths-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtpositioning-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtprintsupport-5.14.0-r1', 'merge'], ['ebuild', '/', 'dev-qt/qtquickcontrols2-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtquickcontrols-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtscript-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtsensors-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtsingleapplication-2.6.1_p20171024', 'merge'], ['ebuild', '/', 'dev-qt/qtspeech-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtsql-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtsvg-5.14.0-r1', 'merge'], ['ebuild', '/', 'dev-qt/qttest-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qttranslations-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtvirtualkeyboard-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtwayland-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtwebchannel-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtwebengine-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtwebkit-5.212.0_pre20190629', 'merge'], ['ebuild', '/', 'dev-qt/qtwidgets-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtx11extras-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtxml-5.14.0', 'merge'], ['ebuild', '/', 'dev-qt/qtxmlpatterns-5.14.0', 'merge']]
desktop ~ # python -c 'import portage; print(portage.mtimedb.get("resume_backup", {}).get("mergelist"))'
None

distccd failed to exec with “No such file or directory”

And you think your compile box using distccd is ready you start emerge in your server/desktop/laptop and the first package is OK, the your emerge is using the distccd properly and the compilation is distributed to the compile box get compiled.
But just then another package gets a warning during build time:

distcc[9356] (dcc_build_somewhere) Warning: failed to distribute, running locally instead

So everything is back in your machine not in the compile box! And you find in the logs of the distccd compile box:

Apr 23 00:36:17 compile distccd[6177]: (dcc_execvp) ERROR: failed to exec x86_64-pc-linux-gnu-clang++: No such file or directory
Apr 23 00:36:17 compile distccd[12965]: (dcc_job_summary) client: 10.10.10.10:54946 COMPILE_ERROR exit:110 sig:0 core:0 ret:0 time:3492ms x86_64-pc-linux-gnu-clang++ ../../v8/src/accessors.cc
Apr 23 00:36:17 compile distccd[13490]: (dcc_job_summary) client: 10.10.10.10:54954 COMPILE_ERROR exit:110 sig:0 core:0 ret:0 time:1677ms x86_64-pc-linux-gnu-clang++ ../../v8/src/asmjs/asm-types.cc
Apr 23 00:36:18 compile distccd[6178]: (dcc_execvp) ERROR: failed to exec x86_64-pc-linux-gnu-clang++: No such file or directory
Apr 23 00:36:18 compile distccd[6097]: (dcc_job_summary) client: 10.10.10.10:54956 COMPILE_ERROR exit:110 sig:0 core:0 ret:0 time:2340ms x86_64-pc-linux-gnu-clang++ ../../v8/src/assembler.cc
Apr 23 00:37:22 compile distccd[6180]: (dcc_execvp) ERROR: failed to exec x86_64-pc-linux-gnu-clang++: No such file or directory
Apr 23 00:37:22 compile distccd[13307]: (dcc_job_summary) client: 10.10.10.10:54990 COMPILE_ERROR exit:110 sig:0 core:0 ret:0 time:1878ms x86_64-pc-linux-gnu-clang++ ../../v8/src/heap/incremental-marking-job.cc
Apr 23 00:37:23 compile distccd[6184]: (dcc_execvp) ERROR: failed to exec x86_64-pc-linux-gnu-clang++: No such file or directory
Apr 23 00:37:23 compile distccd[13719]: (dcc_job_summary) client: 10.10.10.10:54992 COMPILE_ERROR exit:110 sig:0 core:0 ret:0 time:2139ms x86_64-pc-linux-gnu-clang++ ../../v8/src/heap/incremental-marking.cc

Ahh you missed a package, then you emerge it fast with (assumed you used Gentoo, but the solution is valid for all distros)

[root@local ]# emerge -v sys-devel/clang sys-devel/clang-runtime

And start up the build process again (if Gentoo with emerge) and again the same situation? Again the same error, but you have the “x86_64-pc-linux-gnu-clang++” command and when you type x86_64-pc-linux-gnu-clang++ it executes properly! So what is the problem? The problem is that x86_64-pc-linux-gnu-clang++ is not in the current environment PATH:

compile ~ # whereis x86_64-pc-linux-gnu-clang++
x86_64-pc-linux-gnu-clang++: /usr/lib64/llvm/5/bin/x86_64-pc-linux-gnu-clang++

The solution is very simple just restart “distccd”. A trivial one, but could save you time next time! If you install a package, which is expected to be used with distccd restart distccd!!!

Under Getnoo:

compile ~ # /etc/init.d/distccd restart
 * Caching service dependencies ...
 * Stopping distccd ...  [ ok ]
 * Starting distccd ...  [ ok ]
compile ~ #

* You might get error for another file, check if it exists if not install it and then restart the distccd daemon, for example you could get error for any of these:

x86_64-pc-linux-gnu-addr2line
x86_64-pc-linux-gnu-elfedit
x86_64-pc-linux-gnu-gprof
x86_64-pc-linux-gnu-ar
x86_64-pc-linux-gnu-g++
x86_64-pc-linux-gnu-ld
x86_64-pc-linux-gnu-as
x86_64-pc-linux-gnu-g++-6.4.0
x86_64-pc-linux-gnu-ld.bfd
x86_64-pc-linux-gnu-c++
x86_64-pc-linux-gnu-g++-7.2.0
x86_64-pc-linux-gnu-ld.gold
x86_64-pc-linux-gnu-c++-6.4.0
x86_64-pc-linux-gnu-gcc
x86_64-pc-linux-gnu-libgcrypt-config
x86_64-pc-linux-gnu-c++-7.2.0
x86_64-pc-linux-gnu-gcc-6.4.0
x86_64-pc-linux-gnu-llvm-config
x86_64-pc-linux-gnu-c++filt
x86_64-pc-linux-gnu-gcc-7.2.0
x86_64-pc-linux-gnu-nm
x86_64-pc-linux-gnu-clang
x86_64-pc-linux-gnu-gcc-ar
x86_64-pc-linux-gnu-objcopy
x86_64-pc-linux-gnu-clang++
x86_64-pc-linux-gnu-gcc-nm
x86_64-pc-linux-gnu-objdump
x86_64-pc-linux-gnu-clang-5.0
x86_64-pc-linux-gnu-gcc-ranlib
x86_64-pc-linux-gnu-pcre-config
x86_64-pc-linux-gnu-clang++-5.0
x86_64-pc-linux-gnu-gcov
x86_64-pc-linux-gnu-pkg-config
x86_64-pc-linux-gnu-clang-cl
x86_64-pc-linux-gnu-gcov-6.4.0
x86_64-pc-linux-gnu-ranlib
x86_64-pc-linux-gnu-clang-cl-5.0
x86_64-pc-linux-gnu-gcov-7.2.0
x86_64-pc-linux-gnu-readelf
x86_64-pc-linux-gnu-clang-cpp
x86_64-pc-linux-gnu-gcov-dump
x86_64-pc-linux-gnu-size
x86_64-pc-linux-gnu-clang-cpp-5.0
x86_64-pc-linux-gnu-gcov-tool
x86_64-pc-linux-gnu-strings
x86_64-pc-linux-gnu-cpp
x86_64-pc-linux-gnu-gfortran
x86_64-pc-linux-gnu-strip
x86_64-pc-linux-gnu-cpp-6.4.0
x86_64-pc-linux-gnu-gfortran-6.4.0
x86_64-pc-linux-gnu-xml2-config
x86_64-pc-linux-gnu-cpp-7.2.0
x86_64-pc-linux-gnu-gfortran-7.2.0
x86_64-pc-linux-gnu-xslt-config
x86_64-pc-linux-gnu-curl-config
x86_64-pc-linux-gnu-gio-querymodules

Busybox ash, Debian dash and simulating bash arrays

Busybox ash (Almquist shell) shell and Debian dash (Debian Almquist shell) are lightweight Unix shell and they are a variant of System V.4 variant of the Bourne shell. Ash/dash shell is known to be very small and is used mainly in embedded (ash) devices and installation scripts (Debian/Ubuntu setup).
Unfortunately they do not support arrays, which could be really a problem in many cases. But we can simulate the arrays with eval function.
So if you need to write a ash/dash script let’s say for an installation script of Ubuntu or Debian or a script for an embedded device, which uses busybox or even you do not want to use arrays in bash, you can follow the consepts below – create variable with a “name” concatenated with a number.

  • 1) Set a variable

    It can be done with two ways:

    1. for myi in 0 1 2 ; do
          setvar mvar$myi "Payload: $myi"
      done
      
    2. for myi in 0 1 2 ; do
          eval mvar$myi=\"Payload: $myi\"
      done
      

    This will create variables with names:

    mvar1, mvar2, mvar3

    and they can be used in any place of your script after the creation of the variables using “eval” or accessing them with the names.

    * bash shell do not support the command “setvar”, so for bash scripts use only eval version.

  • 2) Use a variable

    1. using “eval”
      for myi in 0 1 2 ; do
          eval echo \$mvar$myi
      done
      
      myi=1
      eval newvar="\$mvar$myi"
      echo $newvar
      
    2. direct access
      echo $mvar2
      $mvar2="Payload 20"
      echo $mvar2