Scientific Computing

SSH headless Raspberry Pi setup

This guide assumes there is no Internet, no Wifi, no router, no display, no keyboard. It assumes you have a Raspberry Pi and laptop with:

  • Ethernet port (built-in or USB-Ethernet adapter)
  • plain (or crossover) Ethernet cable–no router/switch is required

Some laptops can also work via USB-C connection and the RNDIS Ethernet driver instead of the Ethernet jack. However, some laptops, particularly on Windows may not work for RNDIS. The symptom of this is that the Pi shows up as a serial port instead of an Ethernet connection. Hence, best to use the Ethernet jack for better reliability.

Before going into the field away from internet, download:

Prepare SD card via the Raspberry Pi Imaging tool to write the desired SD card image. If the laptop is not on the internet, use the imager tool to write the .img you downloaded previously. BEFORE writing, use Imager settings to enable SSH, set username, hostname, etc.

“eject” or unmount the SD card before removal, to avoid corrupting the SD card file system.

Boot the headless Pi by inserting the SD card into the Pi and powering up the Pi. We use link-local networking, where the IP address will be in the 169.254.*.* range, no DHCP server needed. You may need to manually select this network when you plug the Pi into the laptop. After about one minute, on your laptop plugged directly to the Pi via Ethernet (username, hostname are those picked for the Pi by the Raspberry Pi Imager program):

ssh username@hostname.local

Just a simple network switch connecting Raspberry Pis, PCs and other devices makes an internet-free, pure link-local “off the grid” network. Of course, you can also put the Pis on a wired or wireless network connected to the Internet if desired. The .local address functionality will NOT work over the Internet, but only on the LAN segment your device is on.

Without further configuration, SSH servers listen on all interfaces. Normally this is fine. If you want only specific interface(s) to have the SSH server listen, you will need to research ListenAddress of /etc/ssh/sshd_config and/or IPTables.

Keep Windows .rsp files with Ninja

Ninja normally deletes each response .rsp file if the target build is successful. When debugging a program, we may need to see all the commands run before failure by keeping the .rsp files.

Ninja keeps the .rsp files after compilation by using option:

ninja -d keeprsp

Ninja is a build backend used by Meson build system and CMake as a fast, modern replacement for GNU Make. .rsp files are simply a plain text file containing the command fragment to be run on the command line.

For example, a build line:

cc -Iinc hello.c -lm

is implemented with an .rsp file by the build system as:

cc hello.rsp

where file foo.rsp contains

-Iinc hello.c -lm

There is currently not a Meson or CMake option to keep the .rsp files. Instead, manually invoke Ninja as above when Meson or CMake has configured the build. That is, instead of:

cmake --build build --target hello -v

or

meson compile -C build

do:

ninja -C build -d keeprsp hello

Git pull request force pull

Sometimes a pull request/merge request needs changes before it can be merged. On GitHub, a typical workflow is like:

git switch -c feature main
git pull https://github.com/friend/repo.git main
# other person's repo branch PR/MR is from

Then one edits the files, and commits the changes. However, if the Git pull command fails like:

fatal: Not possible to fast-forward, aborting.

From the new feature branch:

git pull https://github.com/friend/repo.git main
git reset FETCH_HEAD --hard

Then one edits the files, and commits the changes.

Finally, the generic workflow to merge the PR/MR is:

git switch main
git merge --no-ff feature
git push

CI Git reference not a tree

If the CI-detected change is git commit --amend or squash and force push over previous commits, the CI run may fail with a message like:

fatal: reference is not a tree: <commit id>
The command "git checkout -qf <commit id>" failed and exited with 128 during .

Different CI systems have distinct default Git depth. Checking out all commits takes too much time, while too shallow can falsely fail on force push.

We would suggest not specifying the Git clone depth, thereby using the CI system default, unless the repo is very large and Git clone is taking too long. If manually specifying Git depth, the depth must be larger than the number of Git commits your team would ever squash and force push (overwriting prior commits).

For example, in GitHub Actions:

- uses: actions/checkout
  with:
    fetch-depth: 5

Intel MPI on Windows

The Windows Intel oneAPI compilers present Visual Studio-like command line options. Intel oneAPI HPC toolkit includes the Intel MPI library, which provides “mpiexec” needed to run MPI programs and MPI compiler wrappers.

Most users use the Intel oneAPI command prompt environment. Alternatively, use a script

Newer versions of Intel MPI have “mpiicx”, “mpiicpx” and “mpiifx” compiler wrappers.

Intel MPI on Windows is only for Intel oneAPI compiler and Visual Studio.


Although not often needed, a separate username can be used for Windows Intel MPI jobs by from Command Prompt:

runas /user:username cmd

Environment variables are not passed to the new window, so it may be necessary to run Intel compilervars.bat again. It’s possible to register the user credential in the Windows registry.

Stop shell script on exception

Shell scripts can stop upon exception rather than handling each one manually. This can significanlty reduce logical clutter in a script. Stop a shell script on error for Unix / Linux / macOS shell by setting near the top of the .sh script file:

set -o errexit

This is a human-readable equivalent to set -e This works for commonly used Unix shells including Bash and Zsh.

Another useful option is to stop the script if any script variables are defined:

set -o nounset

Stop executing a Powershell script upon exception by adding near the top of the .ps1 Powershell script:

$ErrorActionPreference = 'Stop'

Homebrew binary bottle download

Downloading binary Homebrew bottles without installing Homebrew can be useful to check the location of the bottle contents. This is useful when developing Meson native-files or CMake Find*.cmake modules.

Homebrew distributes bottles from GitHub Packages. For example, HDF5 binary “bottle” may be inspected by:

tar --list -f <filename>

No Homebrew install is necessary for inspection. Using the libraries and binaries is best done by installing Homebrew.

GNU Radio for Windows Subsystem for Linux

Graphics and sound in Windows Subsystem for Linux (WSL) work via WSLg. Networked SDRs (connected to computer via Ethernet) and simulations can work with GNU Radio and GNU Radio Companion on WSL. USB (non-networked) SDRs may or may not work–need an SDR hardware-specific USB to network driver from Windows and additional configuration at best.

Install and run GNU Radio Companion:

apt install gnuradio

gnuradio-companion

Troubleshooting

Error “ValueError: Namespace Gtk not available” can be fixed by:

apt install python3-gi gobject-introspection gir1.2-gtk-3.0

Despite apt install python3-pyqt5 this may help:

python3 -m pip install pyqt5

GNU radio ImportError fixes

GNU Octave font size fix

If GNU Octave plot fonts are too small or the lines are too thin in GNU Octave plotting, typically the first of these methods will be adequate, the others are for reference.

Octave has multiple graphics “toolkits” or “backends”, and prefers QT. If you don’t want the graphical IDE, start Octave with octave -no-gui instead of octave-cli. Using octave-cli disables the QT backend.

Default plot settings are for qt backend. Avoid setting font sizes in the program itself. Tweaking plots for a aparticular computer display may reduce plot fidelity on other computers with different displays.

The “correct” way to scale plot fonts is thus to change your system defaults. Add this to ~/.octaverc instead of ~/Documents/MATLAB/startup.m so that you don’t disturb Matlab’s plotting defaults.

set(0, "defaulttextfontsize", 24)  % title
set(0, "defaultaxesfontsize", 16)  % axes labels

set(0, "defaulttextfontname", "Courier")
set(0, "defaultaxesfontname", "Courier")

set(0, "defaultlinelinewidth", 2)

adjust 16 to produce the most appealing text labels in:

  • axes tick labels
  • legend key
  • title text

defaultline is the root category for lines, so defaultlinelinewidth is not a typo.


The alternative methods below are not normally needed, but are for reference. PPI adjustments: find your PPI by Internet search or spec sheet. Octave’s PPI estimate is:

get(0, 'screenpixelsperinch')

If Octave’s PPI estimate is too small, this is probably why your plot text is too small–Octave thinks your resolution is much less than it really is.

If still a font size problem, try changing system DPI scaling. On Ubuntu, try Gnome Tweak Tool → Fonts → Scaling Factor Octave GUI settings:

  • → General → Interface → Icon Size: large
  • → Editor Styles → Octave: default
  • → Terminal → Font Size

You can also try changing the graphics toolkit. Usually Qt is the best and most modern.

Octave graphics toolkits available:

available_graphics_toolkits()

Active graphics toolkit:

graphics_toolkit()

Select graphics toolkit to see if font sizes are better. Be sure to open a new figure when trying different graphics toolkits.


GNU Octave default settings docs


Related: GNU Octave set defaults

Keep program running after disconnect

Screen is a terminal multiplexer program. Screen allows programs to continue running after a remote user disconnects. If a remote connection is lost unintentionally, screen may not allow reconnection by default by the usual

screen -list

screen -r <id>

normally allows reconnecting to a remote session after logging off. When a connection is lost before disconnecting from screen, you may need the “-x” option:

screen -x <id>

A downside of screen is the difficulty scrolling back in history.

Screen is a terminal multiplexer, and some prefer tmux over screen. Another option is using nohup.