Warm Reboot on Linux with kexec (Remember QEMM?)

If you are old enough to remember QEMM from back in the ’90s, along with other tools we used to squeeze every last byte of memory under the 640KB limit, you may remember a rather cool feature it had – warm reboot.

What is a Warm Reboot?

Reboot involves the computer doing a Power-On Self Test (POST). This takes time, often as much as a few minutes on some servers and workstations. While you are setting something up and need to test frequently that things come up correctly at boot time, the POST can make progress painfully slow. If only we had something like the warm reboot feature that QEMM had back in the ’90s, which allowed us to reset the RAM and reboot DOS without rebooting the entire machine and suffer the POST time. Well, such a thing does actually exist in modern Linux.

Enter kexec

kexec allows us to do exactly this – load a new kernel, kill all processes, and hand over control to the new kernel as the bootloader does at boot time. What do we need for this magic to work? On a modern distro, not much, it is all already included. Let’s start with a script that I use and explain what each component does:

#!/bin/bash

systemctl isolate multi-user.target

rmmod nvidia_drm nvidia_modeset nvidia_uvm
rmmod nvidia

kexec --load=/boot/vmlinuz-$(uname -r) \
      --initrd=/boot/initramfs-$(uname -r).img \
      --command-line="$(cat /proc/cmdline)"

kexec --exec

Let’s look at the kexec lines first. uname -r returns the current kernel version. $(uname -r) bash syntax allows is to take the output of a command and use it as a string in the invoking command. On recent CentOS 8 here is what we get:

$ uname -r
4.18.0-193.6.3.el8_2.centos.plus.x86_64
$ echo $(uname -r)
4.18.0-193.6.3.el8_2.centos.plus.x86_64

The kernel and initial ramdisk usually have the kernel version in their names in /boot/:

$ ls /boot/
initramfs-4.18.0-193.6.3.el8_2.centos.plus.x86_64.img
vmlinuz-4.18.0-193.6.3.el8_2.centos.plus.x86_64

So in our warm reboot script, vmlinuz-$(uname -r) will expand to vmlinuz-4.18.0-193.6.3.el8_2.centos.plus.x86_64. Similar will happen with the initramfs file name.

Next, what is in /proc/cmdline ? This contains the boot parameters that our currently running kernel was booted with, as provided in our grub conifguration, for example:

$ cat /proc/cmdline
BOOT_IMAGE=(hd0,msdos2)/vmlinuz-4.18.0-193.6.3.el8_2.centos.plus.x86_64 root=ZFS=tank/ROOT quiet elevator=deadline transparent_hugepage=never

This is the minimum needed to boot the kernel. Once we have supplied this information, we initiate the shutdown and process purge, and hand over to the new kernel, using:

kexec --exec.

But what are the systemctl and rmmod lines about? They are mostly to work around finnickiness of Nvidia drivers and GPUs. If you execute kexec immediately, with the Nvidia driver still running, the GPU won’t reset properly and won’t get properly re-initialised by the driver when the kernel warm-boots. So we have to rmmod the nvidia driver. Legacy nvidia driver only includes the nvidia module. Newer versions also include nvidia_drm, nvidia_modeset and nvidia_uvm which depend on the nvidia module, so we have to remove those first. But before we do that, we have to make sure that Xorg isn’t running, otherwise we won’t be able to unload the nvidia driver. To make sure graphical environment isn’t running, we switch the runlevel target to multi-user.target (on a workstation we are probably running graphical.target by default). Once Xorg is no longer running, we can proceed with unloading the nvidia driver modules. And with that done, we can proceed with the warm boot and enjoy a reboot time saving.

How to Optimise Your Google Adwords Marketing Campaign

I recently put in place Google Adwords for my colleagues at the MySQL Consultancy, Shattered Silicon, and there are a few things that I think anyone using Google Adwords for advertising products and services should know in order to avoid wasting any of their marketing budget. All of these things are pretty obvious in hindsight, but if you dive in with no experience, you will likely find yourself wasting a lot of your marketing budget on advertising to an audience that isn’t looking to buy.

Location, Location, Location!

Advertise only in places where the companies can plausibly afford to engage your services. In broad terms, this means that if you are based in and doing business from an OECD country, unless you operate in a niche that bucks this rule, there is a good chance that clients who aren’t in another OECD country – can’t afford you. So make sure you set your advertising campaign to specifically target the countries that are of interest to you and specifically exclude the countries that are not. Of course this is not a hard rule – there could be benefit to including additional countries, e.g. if you have staff who speak the language.

There is another aspect of this – in countries where the economy isn’t doing great, there are more likely to be people looking for work in the industry you operate in who will click your advert on the off chance that you may be hiring. So unless you are struggling to hire remote workers, this is another reason to focus on locations where those expensive clicks are likely to be bringing you visits from prospective clients, rather than prospective employees or competitors.

Which brings us onto the next point.

Exclude Job-Seeker Terms

Unless you are looking to hire, exclude commonly used job-seeking terms, such as “hire”, “junior”, “senior”, “internship”, “training”, “position”, “opening” and any others you can think of. This significantly reduced the number of impressions and clicks which were never going to turn into sales.

Avoid Ambiguous Terms

It is worth investing some time into researching whether there there is a tool with a similar name to the service you are offering. For example, if you are advertising services of a MySQL administrator, you may find that most of the clicks you get are from people looking for the deprecated tool of the same name. Similarly, either avoid your advertising of MySQL performance tuning services or disambiguate it from the MySQL tuning tool.

Ideally, try to avoid such term completely or at the very least use specific rather than broad matching and add exclusions for the words used in things other than what you are trying to market.

No Freebies

Presumably, if you are spending your hard earned money on marketing to grow your business, you are running a commercial operation rather than a charity. So you should probably exclude terms like “free”, “trial”, “download” and other terms typically used in searches for things that people don’t expect to pay for.

Audience Age

Another very obvious optimisation, when you think about it, is optimising by age range. If you are selling a highly technical service aimed at business owners and CTOs, it is unlikely they will be younger than mid-20s or older than the retirement age. So exclude those age ranges from your advert targeting spec.

Use the Price Extension on your Advert

You may think that showing prices of 2-3 of your most popular products puts people off from clicking on your ad, but this is a good thing. If a price tag puts somebody off from your advert, there is a good chance they aren’t looking to buy anyway – so they might as well not cost you for the clicks.

Effect on Impressions, CPC and CTR

If you are doing it right, you will find that your total conversion cost will go down, but at first look counter-intuitively, your CPC will go up and your impression count will go down – because your competitors have already probably already gone through a similar exercise, and you are homing in on the actually valuable impressions that they are also competing for. The CPC in the case I have been working on almost doubled overnight once I applied all of the above optimisations. But the cost per conversion went down overall.

Hopefully, these thoughts will get your marketing efforts off to a smoother and cheaper start than it would have otherwise been.

HP G7 MicroServer ILO SSH Connectivity

I recently pressed a G7 MicroServer back into service, and disccovered that I couldn’t connect to it over SSH. This seemed odd given that I am quite certain I remember doing so before. A quick nmap scan showed that the ssh port was definitely open on the ILO:

Starting Nmap 6.40 ( http://nmap.org ) at 2020-06-07 23:06 BST
Nmap scan report for 192.168.0.2
Host is up (0.0086s latency).
Not shown: 992 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
111/tcp open rpcbind
427/tcp open svrloc
443/tcp open https
2068/tcp open advocentkvm
5988/tcp open wbem-http
5989/tcp open wbem-https

Increasing verbosity on ssh connection (ssh -v), yielded some interesting insight, specifically:

debug1: match: OpenSSH_5.2 pat OpenSSH_5* compat 0x0c000000

So it could in fact be that more modern ssh tries to connect with ciphers and protocol options that the now relatively ancient OpenSSH 5.2 doesn’t quite understand. So I quickly grabbed OpenSSH 5.2 portable, built it and tried with that, and – success! Doing it again with verbosity turned up showed what ciphers and MACs were used. I added the following to my ~/.ssh/config:

Host 192.168.0.2
Ciphers aes128-ctr
MACs hmac-md5

And lo and behold, ssh-ing to the ILO from recent ssh on EL8 now works!

Hopefully this will save somebody some time in the future, or prevent them from throwing away what is still a perfectly usable microserver.