Making Debian 9 (Stretch) configure GRUB to boot partitions with UUIDs

As per this bug:

Debian Bug report logs – #852323

The Debian 9 installer (up to v9.5 at least) does not always configure GRUB to find the boot partition using UUID, but leaves it pointing to /dev/sdb or whatever. This can be a problem if you change disks in the system. In particular, if you install from a USB stick and then remove it when the system reboots after the install this can change the disk /dev id. The result is a unbootable system. This can be a bit fiddly to fix (although the first thing that’s always worth trying is to reverse the changes you made and see if it boots, e.g. plug the install USB stick back in to the same usb slot).

You can check this by looking at the /boot/grub/grub.cfg file. A quick check is:

grep "/boot/v" /boot/grub/grub.cfg

The fix is easy. Let the system reboot while leaving the install media in place (obviously make sure you don’t boot from the install media again!). Log in to the system and run (as root/using sudo)

update-grub

Compare the grub.cfg before and after. Then test by removing the install media and rebooting.

Making static networking work in Ubuntu 18.04

Ubuntu 18.04 has switched to netplan for configuring the network interfaces. Netplan generates configurations for NetworkManager or systemd-networkd and effectively replaces ifupdown and the /etc/network/interfaces file.

In an install of Ubuntu Desktop, the default netplan configuration comes from /etc/netplan/01-network-manager-all.yaml which reads:

network:
  version: 2
  renderer: NetworkManager

This basically hands over all network control to NetworkManager. For a static setup we can change the configuration to:

network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s25:
      dhcp4: no
      addresses: [aaa.aaa.aaa.aaa/24]
      gateway4: bbb.bbb.bbb.bbb
      nameservers:
        search: [example.co.uk]
        addresses: [xxx.xxx.xxx.xxx,yyy.yyy.yyy.yyy,zzz.zzz.zzz.zzz]

Where enp0s25 is my network interface in this case, the address has a netmask of 255.255.255.0 and the search is the default dns search domain(s) (note this can be vital for getting automounting to work if your setup just uses machine names and assumes the domain is the same).

Note that if you have a laptop you could put this in a file called, say 02_ethernet_interface.yaml and it should override the first configuration for that interface only. I think. Later configurations override earlier ones.

To test:

netplan try

This applies the configuration and then rolls it back in 120 seconds (by default). Press Enter to accept the new settings.

netplan apply

To apply the changes.

For a desktop I just deleted the first config file.

In theory you could probably use this to generate a configuration for NetworkManager (note that on a server you need to explicitly configure NetworkManager to bring up the interface on boot).

Connecting to NFS shares at boot using fstab in Debian 9 Stretch

Note – this fix in principle should work on most systemd distributions.

Problem – trying to get a Debian 9 system to mount an NFS share at boot. This was declared in /etc/fstab in the normal way, but kept failing on boot. However, once the system was up you could log in and do a mount -a, which would work fine. Reading around, it looks like a case of the system trying to mount before the network is up (and in this case the network should be reliable, as it’s an internal one between a VM and it’s host…)

Tried using the bg option first, which should mount in the background and come up eventually, but still got error on boot.

192.168.45.1:/export  /hostshare  nfs  bg,rw,soft  0   0

There is another option that in theory should help: _netdev. I haven’t tried this yet.

What does work is adding an option x-systemd.automount. This, unsurprisingly, tells systemd to try and mount the share on demand. So changing the line in fstab to read:

192.168.45.1:/export  /hostshare  nfs  rw,soft,x-systemd.automount  0   0

works. Booting the system gives no errors (on the console anyway). The share does not show as mounted until the local mountpoint is accessed, and then it works without complaint.

Footnotes

  1. The context for this is a VM running under VirtualBox. The VM is Debian 9, the host is Ubuntu 17.10. The VM has one network interface with the default NAT setup to talk to the outside world, and a second interface to talk to a host-only network. This allows you to SSH into the the guest from the host, and also allows this NFS setup. You can use the VirtualBox shared folder setup to transfer files, but I figured as both the host and guest were Linux NFS would be easier (and not require the Guest Extensions to be installed on the guest).
  2. Debian 9 wouldn’t successfully install on the laptop, but I needed it for an easy install of LALSuite (Debian is a reference system for this, Ubuntu isn’t and has dependency issues). Hence this rather complicated setup. Fortunately LALSuite is entirely command line based…
  3. Yes, Docker or similar would be more efficient. I’m not so familiar with it and it’s a bit of a pain to get it talking to the host filesystem. I’d argue that running a full VM is slightly more portable, although you’d need to change how the filesharing is set up on a Windows or Mac host.

Monitoring GPU temperatures with nvidia-smi and Check MK (OMD)

The Nvidia monitoring setup described at https://elwe.rhrk.uni-kl.de/howto/ worked in Check MK 1.2.8, but fails in 1.4. After some modification things now work – it required some modification of the check script /omd/yoursite/local/share/check_mk/checks/nvidia_smi. The two modifications needed were:

Remove the grouping of nvidia_smi.errors1 and 2 (I can live with this as our GTX1070 doesn’t report this anyway).

Remove the unicode degree characters from the temperature output, as this seems to cause the system to choke on the textual output.

Needed to delete and recreate the host to get it to work properly – possibly unicode characters hanging around in the generated graph definitions or similar?

#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# | ____ _ _ __ __ _ __ |
# | / ___| |__ ___ ___| | __ | \/ | |/ / |
# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
# | | |___| | | | __/ (__| < | | | | . \ | # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ | # | | # | Copyright Mathias Kettner 2012 mk@mathias-kettner.de | # +------------------------------------------------------------------+ # # This file is part of Check_MK. # The official homepage is at http://mathias-kettner.de/check_mk. # # check_mk is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation in version 2. check_mk is distributed # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with- # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. See the GNU General Public License for more de- # ails. You should have received a copy of the GNU General Public # License along with GNU Make; see the file COPYING. If not, write # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA. ####################################### # Check developed by ####################################### # Dr. Markus Hillenbrand # University of Kaiserslautern, Germany # hillenbr@rhrk.uni-kl.de ####################################### # Tweaked by Jamie Scott # University of Glasgow # Jamie.Scott@glasgow.ac.uk ####################################### # the inventory functions def inventory_nvidia_smi_fan(info): inventory = [] for line in info: if line[2] != 'N/A': inventory.append( ("GPU"+line[0], "", None) ) return inventory def inventory_nvidia_smi_gpuutil(info): inventory = [] for line in info: if line[3] != 'N/A': inventory.append( ("GPU"+line[0], "", None) ) return inventory def inventory_nvidia_smi_memutil(info): inventory = [] for line in info: if line[4] != 'N/A': inventory.append( ("GPU"+line[0], "", None) ) return inventory def inventory_nvidia_smi_errors1(info): inventory = [] for line in info: if line[5] != 'N/A': inventory.append( ("GPU"+line[0], "", None) ) return inventory def inventory_nvidia_smi_errors2(info): inventory = [] for line in info: if line[6] != 'N/A': inventory.append( ("GPU"+line[0], "", None) ) return inventory def inventory_nvidia_smi_temp(info): inventory = [] for line in info: if line[7] != 'N/A': inventory.append( ("GPU"+line[0], "", None) ) return inventory def inventory_nvidia_smi_power(info): inventory = [] for line in info: if line[8] != 'N/A' and line[9] != "N/A": inventory.append( ("GPU"+line[0], "", None) ) return inventory # the check functions def check_nvidia_smi_fan(item, params, info): for line in info: if "GPU"+line[0] == item: value = int(line[2]) perfdata = [('fan', value, 90, 95, 0, 100 )] if value > 95:
return (2, "CRITICAL - %s fan speed is %d%%" % (line[1], value), perfdata)
elif value > 90:
return (1, "WARNING - %s fan speed is %d%%" % (line[1], value), perfdata)
else:
return (0, "OK - %s fan speed is %d%%" % (line[1], value), perfdata)
return (3, "UNKNOWN - GPU %s not found in agent output" % item)

def check_nvidia_smi_gpuutil(item, params, info):
for line in info:
if "GPU"+line[0] == item:
value = int(line[3])
perfdata = [('gpuutil', value, 100, 100, 0, 100 )]
return (0, "OK - %s utilization is %s%%" % (line[1], value), perfdata)
return (3, "UNKNOWN - GPU %s not found in agent output" % item)

def check_nvidia_smi_memutil(item, params, info):
for line in info:
if "GPU"+line[0] == item:
value = int(line[4])
perfdata = [('memutil', value, 100, 100, 0, 100 )]
if value > 95:
return (2, "CRITICAL - %s memory utilization is %d%%" % (line[1], value), perfdata)
elif value > 90:
return (1, "WARNING - %s memory utilization is %d%%" % (line[1], value), perfdata)
else:
return (0, "OK - %s memory utilization is %d%%" % (line[1], value), perfdata)
return (3, "UNKNOWN - GPU %s not found in agent output" % item)

def check_nvidia_smi_errors1(item, params, info):
for line in info:
if "GPU"+line[0] == item:
value = int(line[5])
if value > 500:
return (2, "CRITICAL - %s single bit error counter is %d" % (line[1], value))
if value > 100:
return (1, "WARNING - %s single bit error counter is %d" % (line[1], value))
else:
return (0, "OK - %s single bit error counter is %d" % (line[1], value))
return (3, "UNKNOWN - GPU %s not found in agent output" % item)

def check_nvidia_smi_errors2(item, params, info):
for line in info:
if "GPU"+line[0] == item:
value = int(line[6])
if value > 500:
return (2, "CRITICAL - %s double bit error counter is %d" % (line[1], value))
if value > 100:
return (1, "WARNING - %s double bit error counter is %d" % (line[1], value))
else:
return (0, "OK - %s double bit error counter is %d" % (line[1], value))
return (3, "UNKNOWN - GPU %s not found in agent output" % item)

def check_nvidia_smi_temp(item, params, info):
for line in info:
if "GPU"+line[0] == item:
value = int(line[7])
perfdata = [('temp', value, 80, 90, 0, 95 )]
if value > 90:
return (2, "CRITICAL - %s temperature is %dC" % (line[1], value), perfdata)
elif value > 80:
return (1, "WARNING - %s temperature is %dC" % (line[1], value), perfdata)
else:
return (0, "OK - %s temperature is %dC" % (line[1], value), perfdata)
return (3, "UNKNOWN - GPU %s not found in agent output" % item)

def check_nvidia_smi_power(item, params, info):
for line in info:
if "GPU"+line[0] == item:
draw = float(line[8])
limit = float(line[9])
value = draw * 100.0 / limit
perfdata = [('power', draw, limit * 0.8, limit * 0.9, 0, limit )]
if value > 90:
return (2, "CRITICAL - %s power utilization is %d%% of %dW" % (line[1], value, limit), perfdata)
elif value > 80:
return (1, "WARNING - %s power utilization is %d%% of %dW" % (line[1], value, limit), perfdata)
else:
return (0, "OK - %s power utilization is %d%% of %dW" % (line[1], value, limit), perfdata)
return (3, "UNKNOWN - GPU %s not found in agent output" % item)

# declare the check to Check_MK

check_info['nvidia_smi.fan'] = (check_nvidia_smi_fan, "%s fan speed" , 1, inventory_nvidia_smi_fan)
check_info['nvidia_smi.gpuutil'] = (check_nvidia_smi_gpuutil, "%s utilization" , 1, inventory_nvidia_smi_gpuutil)
check_info['nvidia_smi.memutil'] = (check_nvidia_smi_memutil, "%s memory" , 1, inventory_nvidia_smi_memutil)
#check_info['nvidia_smi.errors1'] = (check_nvidia_smi_errors1, "%s errors single" , 0, inventory_nvidia_smi_errors1)
#check_info['nvidia_smi.errors2'] = (check_nvidia_smi_errors2, "%s errors double" , 0, inventory_nvidia_smi_errors2)
check_info['nvidia_smi.temp'] = (check_nvidia_smi_temp, "%s temperature" , 1, inventory_nvidia_smi_temp)
check_info['nvidia_smi.power'] = (check_nvidia_smi_power, "%s power" , 1, inventory_nvidia_smi_power)

#checkgroup_of['nvidia_smi.errors1'] = 'hw_errors'
#checkgroup_of['nvidia_smi.errors2'] = 'hw_errors'

Notes on getting Ubuntu 16.04 to work with NIS

Note – this only sets up the system to use user and group logons, not automounting home directories. I haven’t figured out how to make this work in Ubuntu 16.

Install package nis

Probably a good idea to set network address statically in /etc/network/interfaces (NetworkManager should recognise this and then leave it alone)

Probably also a good idea to check that /etc/hosts has the domain name for the system, i.e.

127.0.1.1 domain.name.machinename machinename

Add yp server to /etc/yp.conf

Edit /etc/nsswitch.conf to add nis for passwd, group and shadow. Note that compat should include nis by default.

Add a dependency to make the rpcbind service start at boot

systemctl add-wants multi-user.target rpcbind.service

(See this Debian bug report or this Ubuntu one)

Note that this is not a complete fix – it is reported that if the network does not come up fast enough things still break.

For users that need to log on to the system, create home directories

mkhomedir_helper <username>

Remember to reboot to check everything is working:

yptest

if that fails check if the bind services are running

systemctl status rpcbind
systemctl status ypbind

Installing Jekyll on Debian 8 (Jessie)

Install ruby-full:

sudo apt-get install ruby-full

Install ruby-ffi

apt-get install ruby-ffi

Install Jekyll

gem install --http-proxy http://wwwcache.gla.ac.uk:8080 jekyll

install node.js

apt-get install nodejs

Should then work for normal user.

Quick test – (from https://www.digitalocean.com/community/tutorials/how-to-deploy-jekyll-blogs-with-git)

jekyll new awesomeblog

This will create an awesomeblog directory containing the configuration files, posts directory and other required bits.

cd awesomeblog
jekyll serve

Jekyll will build your blog, and after a few seconds you should be able to visit http://host:4000 in your browser. Or skip the serve bit and check in the _site subdirectory.

To get git working with this create the git repository, go into the hooks subdirectory and create a post-receive script like this (again from https://www.digitalocean.com/community/tutorials/how-to-deploy-jekyll-blogs-with-git)

#!/bin/bash -l
GIT_REPO=$HOME/repos/awesomeblog.git
TMP_GIT_CLONE=$HOME/tmp/git/awesomeblog
PUBLIC_WWW=/var/www/awesomeblog

git clone $GIT_REPO $TMP_GIT_CLONE
jekyll build --source $TMP_GIT_CLONE --destination $PUBLIC_WWW
rm -Rf $TMP_GIT_CLONE
exit

or /var/www/html/awesomeblog for apache on Debian 8.

Raspberry Pi networking notes for connecting directly to laptop

If running normal raspbian edit the file /etc/network/interfaces to add in two blocks:

iface eth0 inet dhcp

and

iface eth0 inet static
    address 169.254.210.230
    netmask 255.255.0.0

Comment out the block not in use. For networks that have a dhcp server running use the first block, for connecting to a Windows computer via a private network use the second (If Windows connects to a network, is set to obtain an address automatically and can’t get one then it self-assigns a 169.254.x.y address). Static address can be anything of the form 169.254.x.y.

Full example file:

# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

auto lo
iface lo inet loopback

auto eth0
allow-hotplug eth0

# Comment out this block when connected to laptop
#iface eth0 inet dhcp

# Comment out this block when connected to building network (or any network with dhcp)
iface eth0 inet static
   address 169.254.210.230
   netmask 255.255.0.0


allow-hotplug wlan0
iface wlan0 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

allow-hotplug wlan1
iface wlan1 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Installing MATLAB 2015b on Debian Jessie

Ran into a couple of problems here:

Default Debian behaviour is to mount cd’s with noexec option. Thus you get permission denied even as root when you try to run the install script. Solution; remount cd:

sudo mount -o remount,exec,ro /media/cdrom0

or whatever path the cd is mounted at. You need the ro otherwise it complains.

Other more general problem: sudo ./install just results in Installing... Finished and a silent fail. In the old days using gksudo fixed this but apparently it’s deprecated now. It does work when running as normal user, so tried:

sudo -E ./install

this worked correctly.