Scientific Computing

Reboot computer from terminal command

There are several ways to reboot a computer from the terminal. For Linux or macOS the “reboot” command (or shutdown -r) is commonly used. For Windows, the PowerShell command Restart-Computer is a standard way to reboot the system from Terminal.

Within Windows Subsystem for Linux (WSL), the “reboot” command is only for the particular WSL instance and actually results in a shutdown of the WSL instance, not the entire Windows system. One can verify this by before and after the standard 8 second WSL shutdown time, running in Windows Terminal:

wsl.exe --list --running

Anytone AT-5000 CPS Com Port Driver

Anytone (Qixiang Electronics) provides a programming cable for the Anytone AT-5000 radio, which connects via the 8P8C modular microphone jack to USB. This is a USB to serial adapter. If the comm port does not appear in the AT-5000 CPS software or in Device Manager under “Ports (COM & LPT)” as “USB-SERIAL CH340 (COMx)”, check Windows Device Manager under “Other devices” for “USB Serial” with a yellow warning icon.

The driver necessary is the GD USB Virtual Comm Port driver, which can be downloaded as part of the Anytone D878 programming software package if not seen as part of the Anytone AT-5000 CPS install package. Don’t install the D878 CPS software, just extract the Zip archive folder titled like “Virtual GD USB Com Drivers (Only If Needed)” and extract the “GD_VirtualComDriver v2.0.2.4944.rar” file to get the driver installer under the “x64” folder. After installing the driver, unplug and replug the programming cable. If it’s still showing a yellow warning icon, right-click on the “USB Serial” entry, select “Update driver”, and choose to browse for drivers on the computer by “let me pick from a list of available drivers on my computer”. Under USB Devices look for “USB-SERIAL CH340” and select it to install the driver. It might be necessary to unplug and replug the programming cable again after installing the driver for it to be recognized properly. There should no longer be a yellow warning icon, and the comm port should appear in the AT-5000 CPS software as “USB-SERIAL CH340 (COMx)” under the “Port” dropdown menu.

CMake Ninja show link commands

For CMake, the export of compile commands comes by setting the CMAKE_EXPORT_COMPILE_COMMANDS variable to ON. This generates <build_dir>/compile_commands.json file that contains the compile commands for each source file. However, this does not include the link commands used to link the final executable or library. To show the link commands in Ninja for a specific target, use:

ninja -t compdb-targets mytarg

This command has to be issued directly to Ninja, not using “cmake –build”.

Matlab reset preferences

Matlab preferences are stored in <prefdir>/matlab.mlsettings since Matlab R2020a. To reset Matlab preferences, one can rename / move this file–keep it for a backup. The location of <prefdir> can be found by running the following command in Matlab:

prefdir

After moving the matlab.mlsettings file, restart Matlab. Matlab will create a new matlab.mlsettings file with default preferences.

This is particularly helpful if Python is setup with a “bad” distribution that crashes Matlab upon Python py. commands in Matlab, and there isn’t another Python distribution available to switch to in Matlab’s preferences.

The matlab.mlsettings file is a ZIP file of XML and JSON files and folders.

Find largest directories one-liner

These one-line Unix-like shell commands help find the directories consuming the most hard drive space. This command lists the top 10 largest directories in the specified path. This is useful to HPC where disk quota as seen by quota -s or similar indicates it’s time to clean up some files.

du -hd1 /path/to/check 2>/dev/null | sort -rh | head

While disk size quota is often the main concern, there is often also a quota on the number of files (inodes) that can be owned by a user. To find the directories with the most files, use this command:

find /path/to/check -type f -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -rn | head

Graphical terminal disk usage program “ncdu” is a widely-available Ncurses based program showing the largest files. NCDU is more user-friendly than the plain text method above. NCDU allows deleting files interactively. When using on WSL, specify the desired drive like (for C: in this example):

ncdu /mnt/c

CMake add_custom_target Windows nuisance rebuild

When using CMake’s add_custom_command and add_custom_target on Windows, if the CMAKE_EXECUTABLE_SUFFIX (which is typically .exe) is not included as part of the command or target, it can lead to the custom target is rebuilt every time the project is rebuilt, even if the command is up to date. This happens because CMake does not exactly match the output file of the custom command, since the .exe suffix was missing on Windows, and therefore CMake does not properly track the existence of a target’s dependencies. As a result, CMake assumes that the target is always out of date and needs to be rebuilt. To avoid this issue, ensure that the output of your custom command includes the CMAKE_EXECUTABLE_SUFFIX. For example, if generating an executable with add_custom_command, specify the output file with the correct suffix:

set(myexe ${CMAKE_CURRENT_BINARY_DIR}/my_executable${CMAKE_EXECUTABLE_SUFFIX})

add_custom_command(
    OUTPUT ${myexe}
    COMMAND ...
)

add_custom_target(MyTarget ALL
    DEPENDS ${myexe}
)

By including the CMAKE_EXECUTABLE_SUFFIX in both the OUTPUT and DEPENDS sections, CMake will correctly recognize the target as an executable and will only rebuild it when necessary, thus avoiding unnecessary rebuilds.

Public WiFi SSL mangling

Check the desired website’s SSL certificate with a service like Qualys SSL Labs to see if the certificate is valid and properly configured. If the certificate is valid but you still encounter SSL errors, it’s possible that the public WiFi network is interfering with the SSL connection. Also try using command line web programs to see if there are any SSL errors or warnings in the output. Examples:

curl -v https://www.scivision.dev

python -c "import requests; print(requests.get('https://www.scivision.dev').status_code)"

If these fail, try without SSL

curl -v http://www.neverssl.com

python -c "import requests; print(requests.get('http://www.neverssl.com').status_code)"

An example of the curl output when even HTTP connections are interfered with:

curl -v http://neverssl.com
* Host neverssl.com:80 was resolved.
* IPv6: (none)
* IPv4: x.x.x.x
*   Trying x.x.x.x:80...
* connect to x.x.x.x port 80 from 0.0.0.0 port 58197 failed: Timed out
* Failed to connect to neverssl.com port 80 after 21104 ms: Could not connect to server
* closing connection #0
curl: (28) Failed to connect to neverssl.com port 80 after 21104 ms: Could not connect to server

Docker on GitHub Actions

Docker images are useful for reproducibility and ease of setup and for software binary distribution on platforms not natively available on GitHub Actions runner images. While one can setup a custom Docker image, it’s often possible to simply use an existing official image from Docker Hub.

Example: Ubuntu 20.04

This example GitHub Actions workflow uses the Ubuntu 20.04 image to build a C++ binary with the GNU C++ compiler. For APT operations, the “-y” option is necessary. Environment variable DEBIAN_FRONTEND is set to “noninteractive” to avoid interactive prompts for certain operations despite “-y”. Don’t use “sudo” as the container user is root and the “sudo” package is not installed.

A special feature of this example is using Kitware’s CMake APT repo to install the latest version of CMake on an EOL Ubuntu distro.

name: ubuntu-20.04

on: [push]

# avoid wasted runs
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  ubuntu-20.04:
    runs-on: ubuntu-latest
    container:
      image: ubuntu:20.04
      env:
        DEBIAN_FRONTEND: noninteractive

    strategy:
      fail-fast: false
      matrix:
        gcc-version: [7, 8]

    env:
      CC: gcc-${{ matrix.gcc-version }}
      CXX: g++-${{ matrix.gcc-version }}
      FC: gfortran-${{ matrix.gcc-version }}

    steps:

    - name: install compilers
      run: |
        apt update -y
        apt install -y --no-install-recommends ca-certificates gpg curl ninja-build ${{ env.CC }} ${{ env.CXX }} ${{ env.FC }}

    - name: install CMake
      run: |
        curl -s https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
        echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | tee /etc/apt/sources.list.d/kitware.list >/dev/null
        apt-get update
        test -f /usr/share/doc/kitware-archive-keyring/copyright || rm /usr/share/keyrings/kitware-archive-keyring.gpg
        apt-get install --no-install-recommends -y kitware-archive-keyring
        apt-get install --no-install-recommends -y cmake

    - uses: actions/checkout

    - name: CMake configure
      run: cmake -B build

    - name: CMake build
      run: cmake --build build

    - name: CMake test
      run: ctest --test-dir build

Example: Alpine Linux

This example GitHub Actions workflow uses the Alpine Linux image with the MUSL C library to build a statically-linked binary.

name: alpine-musl

on: [push]

jobs:
  musl:
    runs-on: ubuntu-latest
    container:
      image: alpine

    steps:
    - uses: actions/checkout

    - name: install build tools
      run: apk add --no-cache ninja-build cmake make gfortran openmpi-dev

    - name: print MUSL version
      continue-on-error: true
      run: ldd --version

    - name: CMake configure
      run: cmake -B build

    - name: CMake build
      run: cmake --build build

# Good idea to ensure self-tests pass before packaging
    - name: CMake test
      run: ctest --test-dir build

(Optional) If a CPack archive is desired add step:

    - name: CMake package
      if: success()
      run: cpack --config build/CPackConfig.cmake

The binary artifact or CPack archive can be uploaded by step upload-artifact:

    - name: .exe for release
      uses: actions/upload-artifact@v7
      archive: false
      if: success()
      with:
        name: my.exe
        path: build/my.exe

GitHub Actions upload CMakeConfigureLog.yaml

When CMake fails on the configure or generate steps in a CI workflow, having CMakeConfigureLog.yaml uploaded a as a file can help debug the issue. Add this step to the GitHub Actions workflow YAML file:

  - name: Configure CMake
    run: cmake -B build

# other steps ...

  - name: upload CMakeConfigureLog.yaml
    if: failure() && hashFiles('build/CMakeFiles/CMakeConfigureLog.yaml') != ''
    uses: actions/upload-artifact@v7
    archive: false
    with:
      name: ${{ runner.os }}-${{ env.CC }}-CMakeConfigureLog.yaml
      path: build/CMakeFiles/CMakeConfigureLog.yaml
      retention-days: 5

The “retention-days” parameter is optional. Ensure the “name” parameter is unique to avoid conflicts with other jobs in the workflow. Here we assume that the OS and C compiler are unique between jobs.

Git commit PGP signing

Git signed commits help verify the Git author’s identity using PGP. Optionally, a user or organization can set rules requiring Git PGP signed commits on Git hosting providers such as GitHub and GitLab

PGP public keys can help verify author identity of Git commits, social media, website, etc. Setup GPG on the laptop:

  • Linux: apt install gnupg
  • macOS: brew install gnupg
  • Windows: winget install --id=GnuPG.Gpg4win

Generate a GPG keypair if one doesn’t already exist for yourself.

Export the GPG public and private key and import into GPG:

If one has Keybase, first export Keybase.io PGP key to GPG. If one does NOT have Keybase, use gpg --full-generate-key to generate a GPG keypair.

Verify PGP key:

gpg --list-secret-keys --keyid-format LONG

The first lines will be like:

sec   rsa4096/<public_hex>

The hexadecimal part after the / is a public reference to the GPG keypair.


Add Git provider such as GitHub or GitLab verified email address to the PGP key. To make commits “Verified” with the Git provider, at least one of the Git provider verified email addresses must match:

git config --get user.email

Use the GPG public ID below:

gpg --edit-key <public_hex>

In the interactive GPG session that launches, type

adduid

and enter Name and the Email address–which must exactly match the GitHub verified email address. I also add the @users.noreply.github.com fake email that I always use to avoid spam. Do adduid twice–once for the real GitHub verified email address and again for the github_username@users.noreply.github.com fake email.

Add “trust” from the GPG> prompt:

trust

Since it’s you, perhaps a trust level of 5 is appropriate. type

save

to save changes, which may not show up until exiting and reentering the GPG> prompt.

Configure Git to use the GPG public hex ID like:

git config --global user.signingkey <public_hex>

git config --global commit.gpgsign true

On Windows, even though “gpg” works from Windows Terminal, it’s essential to tell Git the full path to GPG.exe, otherwise Git will fail to sign commits.

git config --global gpg.program "C:\Program Files\GnuPG\bin\gpg.ex"

Find the path with:

where.exe gpg

Add the GPG public key to the Git provider. Copy and paste the output from this command into GPG Key of GitHub or GitLab. This is done only once per human, not once per device.

gpg --armor --export <public_hex>

Usage

GPG can be used to sign Git commits and tags, and can also be disabled per commit.

Verify Git PGP commit sign

Make a git commit after the procedure above, and see the signature notes:

git log --show-signature

it will start with

gpg: Signature made

Temporary disable Git commit sign

If you temporarily lose access to the GPG password, you won’t be able to git commit. A temporary workaround is to set

git config commit.gpgsign false

or simply add the --no-gpg-sign option like:

git commit -am "msg" --no-gpg-sign

If not signing as default, sign only certain commits by

git commit -S

Note that’s a capital “S”.

Troubleshooting

Signing subkey expired

If you get gpg: signing failed: No secret key or gpg: skipped "...": No secret key, the signing subkey may have expired. GPG subkeys (encryption, signing) expire independently from the main key.

Check which subkeys are expired:

gpg --list-secret-keys

Look for subkeys marked expired. To extend them:

gpg --edit-key <public_hex>
key 1
expire
1y
save

The key N selects which subkey to extend (1 for first, 2 for second, etc.). Then export the updated key to GitHub.

Password prompt not working (macOS)

On macOS if entering the password on git commit doesn’t work, try:

brew install pinentry-mac

and add to ~/.zshrc:

export GPG_TTY=$TTY