Stopping my laptop spontaneously resuming immediately after Suspend to RAM

If I selected ‘Suspend to RAM’ via the Desktop Environment in the Gentoo Linux installation on my Clevo W230SS laptop, the laptop did suspend but then immediately resumed automatically. The same thing happened if I suspended the laptop using either of the following commands from the command line:

root # pm-suspend

user $ qdbus org.kde.Solid.PowerManagement /org/freedesktop/PowerManagement Suspend

This behaviour was annoying, as it meant I had to shut down the laptop completely when I was not at my desk for a long time, rather than just being able to suspend the laptop.

Problem 1: USB devices

I usually have several USB devices connected to my laptop when I am at home or in the office, and I began to suspect that these USB connections were somehow causing Linux to resume as soon as it had suspended. Searching the Web turned up a Q&A page that seemed to confirm my suspicion: Why does my laptop resume immediately after suspend? I installed the utility acpitool mentioned on that Web page and used it with the ‘-w‘ option to check which wakeup-capable USB devices were currently enabled in my installation:

root # acpitool -w
   Device       S-state   Status   Sysfs node
  ---------------------------------------
  1. RP01         S4    *disabled  pci:0000:00:1c.0
  2. PXSX         S4    *disabled
  3. RP02         S4    *disabled
  4. PXSX         S4    *disabled
  5. RP03         S4    *disabled  pci:0000:00:1c.2
  6. PXSX         S4    *disabled  pci:0000:03:00.0
  7. RP04         S4    *disabled  pci:0000:00:1c.3
  8. PXSX         S4    *disabled  pci:0000:04:00.0
  9.            *disabled  platform:rtsx_pci_sdmmc.0
  10.           *disabled  platform:rtsx_pci_ms.0
  11. RLAN        S4    *disabled
  12. RP05        S4    *disabled
  13. PXSX        S4    *disabled
  14. RP06        S4    *disabled
  15. PXSX        S4    *disabled
  16. RP07        S4    *disabled
  17. PXSX        S4    *disabled
  18. RP08        S4    *disabled
  19. PXSX        S4    *disabled
  20. GLAN        S4    *disabled
  21. EHC1        S3    *enabled   pci:0000:00:1d.0
  22. EHC2        S3    *enabled   pci:0000:00:1a.0
  23. XHC         S3    *disabled  pci:0000:00:14.0
  24. HDEF        S4    *disabled  pci:0000:00:1b.0
  25. PEG0        S4    *disabled  pci:0000:00:01.0
  26. PEGP        S4    *disabled  pci:0000:01:00.0
  27. PEGA        S4    *disabled
  28. PWRB        S3    *enabled   platform:PNP0C0C:0
^C
root #

(I had to use Ctrl-C to get back to the command prompt.)

I then used the command ‘acpitool -W <device number>‘ on each of the three enabled devices (21, 22 and 28 above) in order to find out which of them needed to be disabled in order for my laptop to remain suspended when I suspended it. I found that I only needed to disable devices EHC1 (pci:0000:00:1d.0) and EHC2 (pci:0000:00:1a.0) to be able to suspend the laptop successfully:

root # acpitool -W 21 | grep 21
  Changed status for wakeup device #21 (EHC1)
  21. EHC1        S3    *disabled  pci:0000:00:1d.0
^C
root # acpitool -W 22 | grep 22
  Changed status for wakeup device #22 (EHC2)
  22. EHC2        S3    *disabled  pci:0000:00:1a.0
^C
root # pm-suspend

In this laptop these two devices are two internal USB root hubs:

user $ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/8p, 480M
        |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            |__ Port 1: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 480M
            |__ Port 3: Dev 5, If 0, Class=Mass Storage, Driver=usb-storage, 480M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M
        |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            |__ Port 1: Dev 6, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
            |__ Port 4: Dev 7, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
            |__ Port 4: Dev 7, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
        |__ Port 3: Dev 4, If 0, Class=Wireless, Driver=btusb, 12M
        |__ Port 3: Dev 4, If 1, Class=Wireless, Driver=btusb, 12M
        |__ Port 4: Dev 5, If 0, Class=Video, Driver=uvcvideo, 480M
        |__ Port 4: Dev 5, If 1, Class=Video, Driver=uvcvideo, 480M

The next challenge was to find out how to disable and re-enable the two devices automatically when I suspend and resume the installation. Further searching of the Web turned up another Q&A page which pointed me in the right direction: How to run a script when suspending/resuming?. It turns out that you need to put a script of the following form in the directory /etc/pm/sleep.d/:

#!/bin/bash

case "$1" in
    suspend)
        # executed on suspend
        ;;
    resume) 
        # executed on resume
        ;;
    *)
        ;;
esac

If you want the script to run when hibernating and thawing, the tests would be for ‘hibernate‘ and ‘thaw‘ instead of ‘suspend‘ and ‘resume‘.

The thread [SOLVED] Computer immediately resumes after suspend in the KDE Forums almost gave me the solution I needed. I created a file /etc/pm/sleep.d/01-toggle-usb-hubs containing the following:

#!/bin/sh
#
username=fitzcarraldo
userhome=/home/$username
export XAUTHORITY="$userhome/.Xauthority"
export DISPLAY=":0"
#
case "$1" in
    suspend|hibernate)
        # Unbind ehci-pci for the device 0000:00:1a.0
        echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci-pci/unbind
        # Unbind ehci-pci for the device 0000:00:1d.0
        echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci-pci/unbind
    ;;
    resume|thaw)
        # Bind ehci-pci for the device 0000:00:1a.0
        echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci-pci/bind
        # Bind ehci-pci for the device 0000:00:1d.0
        echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci-pci/bind
    ;;
    *)
        exit $NA
    ;;
esac

I obtained the device details from the output of the ‘acpitools -w‘ command listed earlier and by looking in the directory /sys/bus/pci/drivers/ehci-pci:

root # ls /sys/bus/pci/drivers/ehci-pci
0000:00:1a.0  0000:00:1d.0  bind  new_id  remove_id  uevent  unbind

Notice that the script tests for either ‘suspend‘ or ‘hibernate‘ to disable the two devices, and tests for either ‘resume‘ or ‘thaw‘ to enable the two devices.

I made the script executable:

root # chmod +x /etc/pm/sleep.d/01-toggle-usb-hubs


Problem 2: Blank X Windows display due to NVIDIA closed-source driver bug

However, a problem remained: My laptop has an NVIDIA GPU and, when resuming from suspension, the X Windows display (Virtual Terminal 7) was a blank screen with only the mouse pointer visible. Now, it so happens that I also experience this behaviour if I switch from Virtual Terminal 7 to e.g. Virtual Terminal 1 (Ctrl-Alt-F1) and then switch back to Virtual Terminal 7 (Ctrl-Alt-F7). Apparently this is due to a bug in the closed-source NVIDIA driver (I am currently using Gentoo package x11-drivers/nvidia-drivers-358.16-r1). However, if I first disable compositing before switching to another virtual terminal, the X Windows display on Virtual Terminal 7 is still visible when I switch back to Virtual Terminal 7. It turns out there is a known bug in the NVIDIA closed-source driver, as explained in the following KDE bug report and thread in the NVIDIA CUDA ZONE Forums:

KDE Bugtracking System Bug No. 344326 – Black or corrupted screen on resume from suspend

NVIDIA CUDA ZONE Forums – Black screen on resume from suspend with 325.15 and KWin 4.11 with enabled compositing

As the suggested work-around is to disable compositing before suspending to RAM, I created a script /etc/pm/sleep.d/02-toggle-compositing containing the following:

#!/bin/sh
#
username=fitzcarraldo
userhome=/home/$username
export XAUTHORITY="$userhome/.Xauthority"
export DISPLAY=":0"
#
case "$1" in
    suspend|hibernate)
        su $username -c "qdbus org.kde.kwin /KWin toggleCompositing" &
    ;;
    resume|thaw)
        su $username -c "qdbus org.kde.kwin /KWin toggleCompositing" &
    ;;
    *)
        exit $NA
    ;;
esac

As I have KDE 4 on this laptop, I made the script use the command ‘qdbus org.kde.kwin /KWin toggleCompositing‘ to disable/enable compositing, so replace that command with the appropriate command if you are not using KDE 4.

I made the script executable:

root # chmod +x /etc/pm/sleep.d/02-toggle-compositing

Now both the scripts in the directory /etc/pm/sleep.d/ run when I suspend or resume the laptop, and everything works as expected. Mission accomplished! :-)

KDE Connect on a hotel Wi-Fi network

KDE Connect

I am a fan of KDE Connect (see my 2014 post about an earlier version), but had previously been unable to use it with a hotel network. However today I managed to do that, and here is how I did it …

I first connected my laptop and my Samsung Galaxy Note 4 to the hotel’s Wi-Fi network, then used the ifconfig command in Linux on my laptop to find the IP address of my laptop on the hotel’s network. Note that the IP address one sees if one uses a Web site such as WhatIsMyIPAddress will be the laptop’s outward-facing IP address, not the IP address of the laptop on the hotel network. For example, the ifconfig command has just shown me that my current DHCP-allocated IP address is 10.154.245.40 on this hotel’s network for this session whereas the Web site WhatIsMyIPAddress is showing my IP address as 78.100.57.102.

By the way, I can also use the excellent Android utility Fing on my Galaxy Note 4 to find the IP address of my laptop on the hotel’s network. It is quite interesting to use Fing to see what other devices (their hostname and IP address) are currently connected to the hotel’s network.

Anyway, then I launched KDE Connect on the Galaxy Note 4, tapped and ‘Add devices by IP’, and entered the laptop’s IP address (10.154.245.40 in this specific case). I was able to pair with KDE Connect running on my laptop and send files from my phone to the laptop, and vice versa.

Netflix – Not fit for purpose?

One of my family has a Netflix account. The account is accessible from any of the desktop and laptop computers in the house, whichever OS they are running.

Recently we bought a so-called ‘smart TV’ (an LG 40UF770V 4K Ultra HD TV, as it happens), and are pleased with it. It runs WebOS 2.0 (yay, Linux!) and the LG Content Store contains a Netflix app, which we promptly installed. The app worked perfectly for several weeks but then stopped being able to access Netflix. When the app was launched, the usual screen with the Netflix logo and the ‘Loading’ rotating indicator would appear but, after a minute or so, an error message would be displayed informing us that Netflix error ‘ui-113’ had occurred. One of the on-screen options then offered by the app was to check the network connection, which we tried, but everything was reported to be working correctly. Not to mention that all the other apps that require an Internet connection work fine. In order to watch a film using Netflix over the Christmas period we had to resort to connecting a laptop to the TV via an HDMI cable and accessing Netflix in a Web browser on the laptop. It is ridiculous to have to resort to such measures to view content on smart TVs which have Netflix apps.

I searched the Web and discovered that many, many people experience the same problem with Netflix and smart TVs. As in our case, they had no trouble accessing their Netflix account on their home network with other devices such as computers, tablets and smart phones. I came across reports by owners of smart TVs made by LG, Philips, Samsung, Sony, Toshiba, and other manufacturers. People who had contacted the relevant TV manufacturer were often told the problem is caused by Netflix, and people who had contacted Netflix were often told the problem is caused by the TV manufacturer.

Netflix has a Help page for this error message, but none of the steps Netflix listed worked, and neither did any of the remedies suggested by others on the Web (including in various YouTube videos). Resetting the TV did not solve the problem. Neither did cycling the mains power to the TV, broadband modem and router (however long the power was off). Nor did changing the TV’s setting for the IP address of the DNS server to one of the well-known public DNS servers such as Google’s. Nor did suggestions such as un-installing and re-installing the Netflix app. Nor did configuring the router to perform port forwarding for Netflix on the TV (not that this should be necessary, but I tried it anyway). Several people wrote that the parental lock in their routers caused the problem, but the parental lock is definitely not enabled in my router. I also tried to access Netflix via the TV’s Web browser; it can log-in to the Netflix account but cannot play content as it does not support the Microsoft Silverlight plug-in or HTML5 required by Netflix.

Nothing we tried solved the problem, and two weeks of this messing around was exasperating. Some people reported that changing the DNS server address in the TV to Google’s DNS servers worked, whereas others reported it didn’t. Even if some lucky person managed to get Netflix working on their smart TV using a certain procedure, other people in the same country with the same model of TV could not, even if they used the same procedure.

In addition to people in a given country trying to get the Netflix app in their smart TV to access their Netflix account in that country, I came across posts by people wanting to access Netflix in a different country (mostly people not in the USA wanting to access US Netflix because it offers a wider range of films and programmes, but also expatriates wanting to access Netflix for their home country with their home-country Netflix account). So I tried recommendations to configure the TV to use a DNS server in the US that some people in the UK had recently indicated would give the Netflix app access to US Netflix rather than UK Netflix (even though we wanted to access UK Netflix from the UK). But that didn’t work either.

However, I didn’t give up. I trawled the Web for lists of DNS servers that some people claimed would give access to Netflix in the UK. I found various Web sites listing IP addresses for DNS servers and tried several of them. Eventually I found one that actually enables the Netflix app in the TV to work, but it accesses US Netflix instead of UK Netflix. Given that the Netflix app has not worked for several weeks, I’m not complaining, but it is not what we were trying to achieve (US Netflix does not provide all the UK TV series available on UK Netflix). Furthermore, according to some of the posts I’ve read, periodically you have to change the DNS server address in the TV because Netflix stops working with the existing address.

Now, I’m a technically-oriented person and it took me several hours over a two-week period to find a solution (well, a work-around). Someone with little or no IT knowledge in the same situation would be at a complete loss as to how to get their Netfix account working. In order for streaming media services to become as ubiquitous as e.g. terrestrial TV, they have to be reliable and be accessible easily to paying customers. Use of Geolocation, GeoDNS and other complex techniques should not cause such a headache to bona fide users. Someone with a Netflix account in his/her country of residence and who simply wants to access Netflix on a smart TV should not have to jump through hoops or hit a brick wall. Clearly this is happening to many people.

On top of that, people such as myself who have to travel internationally frequently because of their work need to be certain that, if they subscribe to a streaming media service, it will work in whatever country they happen to be in at the time (except if blocked by Great Firewalls or content filters on proxy servers, of course) and not be purposely or inadvertently prevented from working by the media service provider’s network concept.

I myself had considered signing up for a Netflix account so that I could view films and TV programmes during my overseas work trips, but, after having to struggle for days to help a family member access a valid Netflix account on a smart TV in the country where the account was set up, will definitely not be giving Netflix my business. In this day and age it is ridiculous that users should have to try umpteen DNS server addresses and reset TVs, routers and modems in order to access their account with a media provider. Services such as Netflix will never have my business until their networking and DRM are sorted out properly and made to work reliably. Until Netflix changes its network delivery model, its service will remain a curate’s egg in my opinion.

Automatically log off inactive users in Windows 10

Although I use Linux on my own machines, the family PC in my lounge runs Windows 10. It has five user accounts and the other members of my family never bother to log out (‘sign out’ in Windows 10 parlance), usually leaving a browser window open. If I logged in to my account and clicked on my icon in the top left corner of the Start Menu, ‘Signed in’ was shown below any of the other users who had not bothered to log out. I found this behaviour somewhat frustrating and resolved to configure the PC to log out a user after a specified period of inactivity by that user. Although it is generally not recommended to forcibly logout someone in case e.g. they have a document open, in my family’s case it would be unlikely to cause a problem and is preferable to leaving several accounts unnecessarily active (albeit requiring each user to re-enter their password in order to access the account, as the default setting for ‘Require a password on wake-up’ is ‘Yes’). Below I explain how I configured Windows 10 to log out each user automatically after a period of inactivity.

First I downloaded the application idlelogoff.exe using the following link:

http://ftp.intelliadmin.com/release/idlelogoff.exe

See the Web page Automatically log off inactive users for details of that application.

I used the Windows 10 File Explorer to copy the file to the root directory C:\ and then I created a batch file IDLELOGOFF.BAT by right-clicking on the Windows 10 Start Menu icon, selecting ‘Command Prompt (Admin)’ and entering the following commands in the Command Prompt window:

cd C:\
notepad IDLELOGOFF.BAT

I made the contents of the batch file IDLELOGOFF.BAT the following, so that a user would be logged out automatically after 900 seconds of inactivity in their session:

start /min C:\idlelogoff.exe 900 logoff

and I changed the owner of the batch file to Users by right-clicking on it in File Explorer and then clicking ‘Properties’ > ‘Security’ > ‘Advanced’ > ‘Owner: Change’ and specifying ‘Users’.

Then I created a standard shortcut to the batch file for each user by getting each user in turn to log in to their account and following the instructions on the Web page Windows 10 – How to Run Program Automatically at Startup. Basically, you press the Windows Key and the R key simultaneously and enter ‘shell:startup‘ to open the user’s Start-up folder, and from there you right-click and select ‘New’ > ‘Shortcut’.

After that, the application idlelogoff.exe should be started automatically the next time a user logs in. You can check by pressing Ctrl-Alt-Delete in each user’s session, selecting ‘Task Manager’, clicking on the ‘Processes’ tab and idlelogoff.exe should be in the list of background processes. If you then log in to your own account and click on your account icon in the top left corner of the Start Menu, you’ll notice ‘Signed in’ is shown below the other user’s icon. If you check again after fifteen minutes, you’ll see that the ‘Signed in’ has gone, indicating that the user has been forcibly logged off.

SDDM keyboard layout

I am using Plasma 5 in Gentoo Linux ~amd64 with OpenRC on my Compal NBLB2 laptop. The Display Manager I am using is SDDM, and the log-in screen was using the US keyboard layout, the only keyboard layout available in the log-in screen’s keyboard menu. Searching the Web told me that SDDM uses the keyboard layout specified in the file /etc/X11/xorg.conf.d/00-keyboard.conf. The trouble is, it doesn’t (at least not in my case). The file already existed in my installation, and its contents are listed below:

Section "InputClass"
    Identifier "keyboard"
    MatchIsKeyboard "yes"
    Option "XkbLayout" "gb,us,br,es"
    Option "XkbVariant" ""
    Option "XkbOptions" "grp:alt_shift_toggle"
EndSection

The X.Org keyboard layouts specified in the file are available once I have logged in to the Plasma 5 Desktop, but none of the four keyboards (gb, us, br and es) were displayed by SDDM in its log-in screen menu. Eventually I discovered it is possible to specify the keyboard layouts in the file /usr/share/sddm/scripts/Xsetup which, by default, contains only the following:

#!/bin/sh
# Xsetup - run as root before the login dialog appears

I edited the file to contain the list of keyboards I wanted SDDM to allow me to choose from on the log-in screen:

#!/bin/sh
# Xsetup - run as root before the login dialog appears
setxkbmap gb,us,br,es

Now the SDDM log-in screen displays the national flags of those four keyboard languages in its keyboard menu, and I can select which keyboard layout to use for typing my password to log in to the Plasma 5 Desktop.

NetworkManager: Failed to activate – The name org.freedesktop.NetworkManager was not provided by any .service files

Because I need to connect quickly and easily to numerous wired and wireless networks (DHCP or static IP addressing), I use NetworkManager in my Gentoo Linux amd64 installation running OpenRC and KDE 4. My Clevo W230SS laptop has an Intel Dual Band Wireless-AC 7260 Plus Bluetooth adapter card, and my installation uses the iwlwifi module:

# lspci -knn | grep Net -A2
03:00.0 Network controller [0280]: Intel Corporation Wireless 7260 [8086:08b1] (rev bb)
        Subsystem: Intel Corporation Dual Band Wireless-AC 7260 [8086:4070]
        Kernel driver in use: iwlwifi
# lsmod | grep iwl
iwlmvm                143919  0
iwlwifi                75747  1 iwlmvm

As I am using NetworkManager instead of netifrc, in accordance with the instructions in the Gentoo Wiki article on NetworkManager I do not have any net.* services enabled (not even net.lo):

# rc-update show -v
       NetworkManager |      default                 
                acpid |                              
            alsasound |                              
         avahi-daemon |                              
       avahi-dnsconfd |                              
               binfmt | boot                         
            bluetooth |      default                 
             bootmisc | boot                         
         busybox-ntpd |                              
     busybox-watchdog |                              
                clamd |                              
          consolefont |                              
           consolekit |      default                 
               cronie |      default                 
         cups-browsed |      default                 
                cupsd |      default                 
                 dbus |      default                 
                devfs |                       sysinit
               dhcpcd |                              
                dhcpd |                              
             dhcrelay |                              
            dhcrelay6 |                              
                dmesg |                       sysinit
              dropbox |                              
           fancontrol |                              
                 fsck | boot                         
                 fuse |                              
           git-daemon |                              
                  gpm |                              
              hddtemp |                              
             hostname | boot                         
              hwclock | boot                         
            ip6tables |                              
             iptables |                              
              keymaps | boot                         
            killprocs |              shutdown        
    kmod-static-nodes |                       sysinit
           lm_sensors |                              
                local |      default                 
           localmount | boot                         
             loopback | boot                         
      mit-krb5kadmind |                              
          mit-krb5kdc |                              
       mit-krb5kpropd |                              
              modules | boot                         
             mount-ro |              shutdown        
                 mtab | boot                         
                mysql |                              
                  nas |                              
         net.enp4s0f1 |                              
               net.lo |                              
             netmount |      default                 
           ntp-client |                              
                 ntpd |                              
           nullmailer |                              
              numlock |                              
  nvidia-persistenced |                              
           nvidia-smi |                              
              osclock |                              
              pciparm |                              
               procfs | boot                         
              pwcheck |                              
            pydoc-2.7 |                              
            pydoc-3.4 |                              
               rfcomm |                              
                 root | boot                         
               rsyncd |                              
            s6-svscan |                              
                samba |      default                 
                saned |                              
            saslauthd |                              
            savecache |              shutdown        
                 sntp |                              
                 sshd |      default                 
             svnserve |                              
                 swap | boot                         
            swapfiles | boot                         
              swclock |                              
               sysctl | boot                         
                sysfs |                       sysinit
            syslog-ng |      default                 
        teamviewerd10 |                              
         termencoding | boot                         
             timidity |                              
         tmpfiles.dev |                       sysinit
       tmpfiles.setup | boot                         
               twistd |                              
                 udev |                       sysinit
                  ufw | boot                         
              urandom | boot                         
       wpa_supplicant |                              
                  xdm |      default                 
            xdm-setup |

I have left the netmount service enabled in case I want to use network-attached file shares at home or in one of the various office locations where I work.

Networking works fine on my laptop with the many wired and wireless networks I have used except for one particular public wireless network (it is in an airport, has multiple Access Points, and its Access Points only support 802.11a/b/g, which may or may not be relevant) for which the following message would usually appear in a pop-up window when I tried to connect to the network from the KDE network management GUI after start-up:

Failed to activate
The name org.freedesktop.NetworkManager was not provided by any .service files

Error message displayed by KDE when trying to connect to one specific network

Error message displayed by KDE when trying to connect to one specific network


This occurred with both networkmanager-1.0.2-r1 and networkmanager-1.0.6, the two Stable Branch releases of NetworkManager currently available in Gentoo Linux.

The wireless network is not the only network at that particular location, and the ‘Failed to activate’ message occurred whichever network (wireless or wired) I tried to access at that location. When this problem occurred, it transpired that the NetworkManager service was not running (it had crashed):

$ nmcli d
Error: NetworkManager is not running.
$ rc-status
Runlevel: default
 dbus                   [  started  ]
 NetworkManager         [  crashed  ]
 netmount               [  started  ]
 syslog-ng              [  started  ]
 cupsd                  [  started  ]
 samba                  [  crashed  ]
 consolekit             [  started  ]
 cronie                 [  started  ]
 bluetooth              [  started  ]
 xdm                    [  started  ]
 cups-browsed           [  started  ]
 sshd                   [  started  ]
 local                  [  started  ]
Dynamic Runlevel: hotplugged
Dynamic Runlevel: needed
 xdm-setup              [  started  ]
 avahi-daemon           [  started  ]
Dynamic Runlevel: manual

(I am not bothered that Samba crashes in that particular location. It crashes even if a connection is established, because the public wireless network does not provide network file systems. Samba works fine when I connect the laptop to an office network or to my home network.)

Even if the ‘Failed to activate’ message occurred, sometimes (but not always) the laptop could still connect to networks after I restarted the NetworkManager service (albeit sometimes it was necessary to restart it more than once):

# /etc/init.d/NetworkManager restart

When it is possible to connect to networks, the NetworkManager service is of course running:

$ nmcli d
DEVICE    TYPE      STATE        CONNECTION           
sit0      sit       connected    sit0                 
wlp3s0    wifi      connected    Free_Airport_Internet
enp4s0f1  ethernet  unavailable  --                   
lo        loopback  unmanaged    --        
$ rc-status
Runlevel: default
 dbus                   [  started  ]
 NetworkManager         [  started  ]
 netmount               [  started  ]
 syslog-ng              [  started  ]
 cupsd                  [  started  ]
 samba                  [  crashed  ]
 consolekit             [  started  ]
 cronie                 [  started  ]
 bluetooth              [  started  ]
 xdm                    [  started  ]
 cups-browsed           [  started  ]
 sshd                   [  started  ]
 local                  [  started  ]
Dynamic Runlevel: hotplugged
Dynamic Runlevel: needed
 xdm-setup              [  started  ]
 avahi-daemon           [  started  ]
Dynamic Runlevel: manual

I searched the Web for the error message and, based on a recommendation on the Web page ‘nm-applet gives errors‘ claiming the problem is due to the iwlwifi driver when used with an Intel 7260 controller, I created a file /etc/modprobe.d/iwlwifi.conf containing the following line, and rebooted:

options iwlwifi power_save=0

However, the error message still occurred. So I changed the iwlwifi module options line to the following, as also recommended on that page, and rebooted:

options iwlwifi 11n_disable=1 power_save=0

However, the error message still occurred.

The default value for OpenRC’s rc_depend_strict variable is YES if rc_depend_strict is not declared in the file /etc/rc.conf, but I do not think that is the cause of the problem:

# Do we allow any started service in the runlevel to satisfy the dependency
# or do we want all of them regardless of state? For example, if net.eth0
# and net.eth1 are in the default runlevel then with rc_depend_strict="NO"
# both will be started, but services that depend on 'net' will work if either
# one comes up. With rc_depend_strict="YES" we would require them both to
# come up.
#rc_depend_strict="YES"

As already mentioned, sometimes just restarting the NetworkManager service once or more did enable the laptop to connect to the network. This made me wonder whether the problem had something to do either with the timing of the launch of the NetworkManager service or with the timing of the service establishing a connection. As netmount is the only other network-related service enabled at start-up, I checked the netmount service’s configuration file /etc/conf.d/netmount to see what it contained (it’s the same in both the latest stable openrc-0.17 and the latest testing openrc-0.18.2):

# You will need to set the dependencies in the netmount script to match
# the network configuration tools you are using. This should be done in
# this file by following the examples below, and not by changing the
# service script itself.
#
# Each of these examples is meant to be used separately. So, for
# example, do not set rc_need to something like "net.eth0 dhcpcd".
#
# If you are using newnet and configuring your interfaces with static
# addresses with the network script, you  should use this setting.
#
#rc_need="network"
#
# If you are using oldnet, you must list the specific net.* services you
# need.
#
# This example assumes all of your netmounts can be reached on
# eth0.
#
#rc_need="net.eth0"
#
# This example assumes some of your netmounts are on eth1 and some
# are on eth2.
#
#rc_need="net.eth1 net.eth2"
#
# If you are using a dynamic network management tool like
# networkmanager, dhcpcd in standalone mode, wicd, badvpn-ncd, etc, to
# manage the network interfaces with the routes to your netmounts, you
# should list that tool.
#
#rc_need="networkmanager"
#rc_need="dhcpcd"
#rc_need="wicd"
#
# The default setting is designed to be backward compatible with our
# current setup, but you are highly discouraged from using this. In
# other words, please change it to be more suited to your system.
#
rc_need="net"

As I am using NetworkManager rather than netifrc, I followed the instructions in the file’s comments and changed the file’s contents from:

rc_need="net"

to:

rc_need="networkmanager"

After making the above change, the console messages at boot-up included a new message:

* ERROR: netmount needs service(s) networkmanager

That message made sense: rc_need had been set to "networkmanager" and, obviously, netmount can only do its job if NetworkManager is running (AND a network connection has been established). However, notice that the name of the NetworkManager service initscript is /etc/init.d/NetworkManager, not /etc/init.d/networkmanager. In other words, the instructions in /etc/conf.d/netmount are wrong: the name of the service is actually ‘NetworkManager‘, not ‘networkmanager‘. So I changed /etc/conf.d/netmount to contain rc_need="NetworkManager" instead of rc_need="networkmanager" and, unsurprisingly, the above-mentioned error message no longer occurs. I have filed Gentoo Bugzilla Bug Report No. 564846 requesting that the comment in the configuration file be changed.

Nevertheless, the ‘Failed to activate’ message still occurred when I tried to connect to any network at that location by using the DE’s network management GUI, and therefore I still needed to restart the NetworkManager service manually in order to be able to connect to any network there. Although I am not yet sure of the root cause and solution, I have found a work-around which avoids me having to manually restart the NetworkManager service, as explained below.

Although OpenRC correctly launches the NetworkManager service, that service remains inactive until it actually establishes a network connection. This is not a bug, it is the way OpenRC and NetworkManager work (see the explanation in the Gentoo Forums thread NetworkManager has started, but is inactive). This is why the following console message appears during boot-up:

* WARNING: NetworkManager has already started, but is inactive

If you did not configure NetworkManager to connect automatically to a network, after logging-in to the DE you will need to use the DE’s network management GUI (plasma-nm in the case if KDE, nm-applet in the case of e.g. Xfce) to tell NetworkManager to connect to the desired network. However, I found that waiting that long before trying to connect is too late to avoid the ‘Failed to activate’ problem, i.e. NetworkManager crashes after a while. I do not know why this happens, but it usually happens only when I am at the location covered by one specific wireless network (which is why I wonder if the problem is a result of that network only supporting 802.11a/b/g). By configuring NetworkManager to connect automatically to the wireless network which seemed to trigger the problem, the NetworkManager service tries to connect earlier. It is possible to configure NetworkManager to do this either by using the DE network GUI and ticking ‘Automatically connect to this network when it is available’ for the relevant network connection, or by directly editing the relevant connection’s file in the directory /etc/NetworkManager/system-connections/.

Of the various wired and wireless connections I had configured on the laptop, I had named the problematic wireless network’s connection ‘Free_Airport_Internet’. So I edited the file /etc/NetworkManager/system-connections/Free_Airport_Internet and deleted the line ‘autoconnect=false‘ in the [connections] section of the file (the default value of the autoconnect variable is TRUE – see man nm-settings). I could instead have done this by using the DE’s network manager GUI and ticking ‘Automatically connect to this network when it is available’ for that network connection. Now, when the laptop boots, NetworkManager tries to connect to that network and the ‘Failed to activate’ problem is avoided. This works with or without the iwlwifi driver options I mentioned above, so, despite the claim on the Web page I referenced above, the root cause of the problem does not appear to be the iwlwifi driver. What I don’t understand is why the problem only seems to occur with one particular network (a public wireless network which happens to only support 802.11a/b/g), i.e. even if none of the NetworkManager connection files in my installation have been configured to try to establish a connection automatically, with all the other wireless networks I have used in other locations (I believe those all support at least 802.11a/b/g/n) I have been able to establish a connection manually by using the DE’s network management GUI.

The bottom line

If your installation uses NetworkManager and you experience the ‘Failed to activate’ message when trying to connect to networks from the DE’s network management GUI, check if the NetworkManager service is running. You can check by using the command ‘nmcli d‘ in a console. If it is not running, try to restart the NetworkManager service from the command line. If the connection is not already configured to start automatically, configure it to start automatically in order to try to make NetworkManager become active at an early stage.

POSTSCRIPT (November 6, 2015)

The two links below are to old bug reports regarding earlier versions of NetworkManager having trouble using wireless networks with multiple Access Points. I wonder if the problem I saw with NetworkManager crashing when not configured to connect automatically to the specific network I mentioned above is somehow related to those problems:

background scanning causes drivers to disassociate – WiFi roaming causes NetworkManager to lose routing

network-manager roams to (none) ((none)) – background scanning

Roaming to BSSID “(none)” certainly happens with this particular network too, as shown by the messages in the laptop’s system log from yesterday when I was using the laptop with that network (the laptop was stationary the whole time):

# cat /var/log/messages | grep "Nov  5 11" | grep NetworkManager | grep \(none\)
Nov  5 11:01:22 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID 04:C5:A4:C3:F9:EE (Free_Airport_Internet) to (none) ((none))
Nov  5 11:01:22 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)
Nov  5 11:13:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID B8:BE:BF:69:89:6E (Free_Airport_Internet) to (none) ((none))
Nov  5 11:13:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to 04:C5:A4:C3:F9:EE (Free_Airport_Internet)
Nov  5 11:15:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID 04:C5:A4:C3:F9:EE (Free_Airport_Internet) to (none) ((none))
Nov  5 11:15:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)
Nov  5 11:19:22 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID B8:BE:BF:69:89:6E (Free_Airport_Internet) to (none) ((none))
Nov  5 11:19:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)
Nov  5 11:49:50 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID B8:BE:BF:69:89:6E (Free_Airport_Internet) to (none) ((none))
Nov  5 11:49:50 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to 68:BC:0C:A1:3C:DE (Free_Airport_Internet)
Nov  5 11:51:51 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID 68:BC:0C:A1:3C:DE (Free_Airport_Internet) to (none) ((none))
Nov  5 11:51:51 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)

Today I’m using a hotel network in my hotel room, and that does not roam to BSSID “(none)”, but I don’t know if my room is within range of more than one Access Point:

# cat /var/log/messages | grep "Nov  6" | grep NetworkManager | grep \(none\)
#

Anyway, with the work-around described in this post I have not had any further trouble accessing the particular network, but it would be interesting to know the root cause.

Using a keyboard shortcut in Linux to add an e-mail signature giving current location and local time

In my previous post I showed how to find the current time at any town or city Worldwide from the command line in Gentoo Linux. My interest in a command to do this is not to use it on the command line per se, but to use the command in a keyboard shortcut to insert a signature at the end of my e-mails.

I have to travel internationally frequently because of my work, but I leave my laptop’s hardware clock set to UTC and the system clock set to the local time of my home town. This means that, irrespective of where I am in the World, the e-mail client (Thunderbird, in my case) uses the local time of my home town in e-mail headers and calenders. It is not practical to reconfigure Linux for each timezone I happen to be in (see my post Configuring the Linux clock), and, in any case, I want the file system’s timestamps to use one timezone only and all the timestamps in my e-mails and the e-mail client’s calender to use one timezone only, so there is less chance of me getting confused. I could have configured the installation to use UTC for the system clock, but I prefer the system clock to use the timezone of my home town. Of course, even though the system clock is always set to the timezone of my home town, on the Panel clock I select the timezone of the location where I happen to be, so that the Panel clock displays the local time in that timezone.

I wanted to be able to insert a signature at the end of each e-mail, stating my current location and the current time at that location, so that the person receiving the e-mail could tell from where in the World I sent the e-mail and the local time it was sent, as that local time could differ from the time shown in the e-mail header. For example, let us assume that Jane, who lives in the UK and whose system clock is configured for the timezone Europe/London, is making a brief visit to Perth, Australia and sends an e-mail to Dave in the UK at 06:36 on 11 October (Perth time). The e-mail below illustrates the type of signature I wanted to achieve.

Subject: Site visit
From: Jane <jane@acompany.com>
To: Dave <dave@acompany.com>
Date: Sat Oct 10 2015 23:36:40 GMT+0100 (BST)

Hello Dave,

This is to let you know that I have just arrived in Perth and will be
visiting site at 09:00 local time to speak to the client. Tomorrow p.m.
I have a meeting scheduled with our local project manager, so I would
appreciate it if you would e-mail the latest documentation to me. I will
not have spare time until I’m in my room at the hotel tonight but will
read the documents tomorrow a.m. in readiness for the meeting with
the local project manager. Thanks in advance.

Regards,
Jane
Current location: Perth (Australia)
Local time now: Sat Oct 11 06:36:31 2015 AWST

As you can see above, because the OS on Jane’s and Dave’s laptops is configured for the timezone Europe/London, the e-mail header shows the current time in the UK when the e-mail was sent, which was October 10, 23:36 British Summer Time (22:36 UTC), and the signature shows the corresponding local time in Perth, Australia, which was October 11, 06:36 Australian Western Standard Time. It becomes even more confusing if the computer of the person receiving the e-mail is configured for a third timezone. For example, let’s say Dave is based in Seattle, USA rather than the UK. His e-mail client would then display the time in that timezone when the e-mail was sent. This is usually my case, i.e. my Linux installation is configured for Timezone1 but I happen to be in Timezone2 when I send an e-mail to someone who is based in Timezone3 and whose OS is configured for that timezone.

I wanted to use a keyboard shortcut to add a signature to the end of my e-mails, as shown above. I therefore created the Bash script listed below, which I named timezone_signature_GeoNames.sh:

#!/bin/bash

location=$(kdialog --title "Current Location" --inputbox "Enter your location:")

localtime=$(perl /home/fitzcarraldo/now1.pl $location)
place=`echo $localtime | cut -d'|' -f1`
place=$place" "`echo $localtime | cut -d'|' -f2`
timezone=`echo $localtime | cut -d'|' -f4`

if [ $location != "" ]; then
  echo -n "Current location: "
  echo $place
  echo -n "Local time now:"
  /usr/sbin/zdump ${timezone} | cut -d' ' -f2-
fi
echo

Notice that the Bash script uses the GUI dialogues utility kdialog to display a pop-up window prompting me to enter the name of a town/city. As I am using KDE I opted to use a dialogues utility developed for use in KDE, but I could have used Zenity instead.

The Perl script now1.pl is a variant of the Perl script now.pl described in my previous post, modified very slightly in order to facilitate formatting of the output by the Bash script, and is listed below.

#!perl

use strict;
use warnings;

use DateTime;
use Geo::GeoNames;
use URI::Escape;
use Encode;

binmode STDOUT, ':encoding(UTF-8)';

my $city = decode("UTF-8", @ARGV ? shift : 'London');
# N.B. Replace London with your home town/city.

my $geo = Geo::GeoNames->new( username => '************' );
# N.B. Replace the asterisks with your GeoNames user name.

my $result = $geo->search(
q       => uri_escape_utf8($city),
maxRows => 1,
style   => 'FULL'
);

defined $result->[0] or die "Unrecognized city '$city'\n";

my $city_name    = $result->[0]->{name};
my $country_name = $result->[0]->{countryName};
my $time_zone    = $result->[0]->{timezone}{content};
my $time_now     = DateTime->now( time_zone => $time_zone );

#print "$city_name ($country_name) $time_now ($time_zone)\n";

print "$city_name|($country_name)|$time_now|$time_zone\n";

exit 0;

The only thing remaining was to configure a keyboard shortcut to launch the Bash script. I opted to use the key combination Ctrl-Alt-z for the shortcut. As I am using KDE I could have used KDE’s ‘System Settings’ > ‘Shortcuts and Gestures’> ‘Custom Shortcuts’ to specify the shortcut and the name of the script it launches. However, as I also use AutoKey for various shortcuts, I opted to use that instead, so I used the AutoKey GUI to create a shortcut named ‘Insert Current Time’ to use the following command:

output = system.exec_command("/home/fitzcarraldo/timezone_signature_GeoNames.sh")
keyboard.send_keys(output)

Use

I compose my e-mails as usual, and, after entering my name at the end of the e-mail, I press Ctrl-Alt-z. A window then pops up prompting me to enter my current location, which I do and then click on ‘OK’. The location and current time at that location are then added to the end of the e-mail, and it just remains for me to click on the ‘Send’ button in the e-mail client’s window. As the Perl script now1.pl uses the Internet to access the GeoNames database, my laptop must be connected to the Internet when I use the shortcut.

KDialog window that pops up when I use the keyboard shortcut

KDialog window that pops up when I use the keyboard shortcut

If the town/city name consists of more than one word (Rio de Janeiro, for example) then replace spaces with hyphens when you enter the location name in the pop-up window (Rio-de-Janeiro, for example) and then the keyboard shortcut will return the correct location and local time:

Current location: Rio de Janeiro (Brazil)
Local time now: Fri Oct 16 09:28:19 2015 BRT

Find the time now at any town or city Worldwide from the command line in Gentoo Linux

In my hunt for a command to return the current time at any town or city in the World, I recently found a Perl script now.pl posted in 2012 by Jim Monty on grokbase. The script uses a Perl module to access the database of the GeoNames Web site. To use the module you need to have a user account at the GeoNames Web site and be connected to the Internet. The script also uses the modules URI::Escape and DateTime.

In the case of Gentoo Linux, ebuilds for some of the Perl modules used by now.pl are not available in the main Portage tree, so I installed them from a Portage local overlay, as explained below.

First I created in my local overlay an ebuild for the Perl module Geo::GeoNames and then merged it:

# mkdir -p /usr/local/portage/dev-perl/Geo-GeoNames
# cd /usr/local/portage/dev-perl/Geo-GeoNames
# nano -w Geo-GeoNames-1.01.ebuild
# ebuild Geo-GeoNames-1.01.ebuild manifest
# emerge --ask Geo-GeoNames

The ebuild Geo-GeoNames-1.01.ebuild I created is listed below:

EAPI=5

MODULE_AUTHOR=BDFOY
inherit perl-module

DESCRIPTION="Provides a perl interface to the webservices found at http://api.geonames.org"

SLOT="0"
KEYWORDS="alpha amd64 ~arm hppa ia64 ~mips ppc ppc64 ~s390 ~sh sparc x86 ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~sparc-solaris"
IUSE=""

RDEPEND="
        dev-perl/Module-Build
        "
DEPEND="${RDEPEND}"

SRC_TEST=do

I’m not sure if I declared the correct dependencies in DEPEND and RDEPEND, but the Geo::GeoNames module is merged in my installation and functions correctly.

The Perl script also uses the Perl module URI::Escape, which I found out is part of the package dev-perl/URI in the Portage main tree and was already installed, so I did not need to do anything further as far as that was concerned.

Next I needed to install the Perl module Date::Time. Fortunately there is an ebuild for dev-perl/DateTime in the main Portage tree, so I merged that package directly:

# emerge --ask DateTime

Then I surfed to the GeoNames Web site and registered for a user account. My thanks go to the people who provide and maintain the site and database.

I then created a file /home/fitzcarraldo/now.pl containing the Perl script listed in Jim Monty’s post of Aug 19, 2012 on the Web page: [DateTime] Is there timezone data for any Indian cities such as Mumbai, Dehli, &c.?. My thanks also go to Jim Monty for posting his script.

My initial attempts at running now.pl resulted in an error message warning about a missing Mojo::UserAgent Perl module. I therefore needed to install the package Mojolicious but, unfortunately, the main Portage tree does not have an ebuild for it. I could have either added a third-party overlay (e.g. srcshelton) which contains a Mojolicious ebuild or downloaded the ebuild and put it in my local overlay. I opted for the latter, and merged it:

# mkdir -p /usr/local/portage/dev-perl/Mojolicious
# cd /usr/local/portage/dev-perl/Mojolicious
# cp /home/fitzcarraldo/Downloads/Mojolicious-5.30.ebuild .
# ebuild Mojolicious-5.30.ebuild manifest
# emerge --ask Mojolicious

Despite the examples given in Jim Monty’s post using now.pl with place names containing diacritics, in my case the script could not handle them, so I made a couple of small modifications, and the script I’m using is show below:

#!perl
use strict;
use warnings;

use DateTime;
use Geo::GeoNames;
use URI::Escape;
use Encode;

binmode STDOUT, ':encoding(UTF-8)';

my $city = decode("UTF-8", @ARGV ? shift : 'London');

my $geo = Geo::GeoNames->new( username => '***********' );
# N.B. Replace the asterisks with your GeoNames user name.

my $result = $geo->search(
q       => uri_escape_utf8($city),
maxRows => 1,
style   => 'FULL'
);

defined $result->[0] or die "Unrecognized city '$city'\n";

my $city_name    = $result->[0]->{name};
my $country_name = $result->[0]->{countryName};
my $time_zone    = $result->[0]->{timezone}{content};
my $time_now     = DateTime->now( time_zone => $time_zone );

print "$city_name ($country_name) $time_now ($time_zone)\n";

exit 0;

I made the script executable and ensured my user account could use it:

# chmod +x /home/fitzcarraldo/now.pl
# chown fitzcarraldo:fitzcarraldo /home/fitzcarraldo/now.pl

Now if I enter the name of a town or city anywhere in the World while my laptop is connected to the Internet, the script prints the town/city name, country, local time and the time zone’s name as given in the zoneinfo database (a.k.a. ‘Olsen database’, ‘tz database‘ and ‘IANA time zone database’):

$ cd
$ perl now.pl
London (United Kingdom) 2015-09-25T23:10:16 (Europe/London)
$ perl now.pl "London Canada"
London (Canada) 2015-09-25T18:10:22 (America/Toronto)
$ perl now.pl Paris
Paris (France) 2015-09-26T00:10:29 (Europe/Paris)
$ perl now.pl "New York"
New York (United States) 2015-09-25T18:10:41 (America/New_York)
$ perl now.pl Tokyo
Tokyo (Japan) 2015-09-26T07:10:50 (Asia/Tokyo)
$ perl now.pl "Mexico City"
Mexico City (Mexico) 2015-09-25T17:10:59 (America/Mexico_City)
$ perl now.pl "Kuala Lumpur"
Kuala Lumpur (Malaysia) 2015-09-26T06:11:09 (Asia/Kuala_Lumpur)
$ perl now.pl "São Paulo"
São Paulo (Brazil) 2015-09-25T19:11:29 (America/Sao_Paulo)
$ perl now.pl Maceio
Maceió (Brazil) 2015-09-25T19:11:39 (America/Maceio)
$ perl now.pl Maceió
Maceió (Brazil) 2015-09-25T19:11:48 (America/Maceio)
$ perl now.pl "Várzea Grande"
Várzea Grande (Brazil) 2015-09-25T18:12:04 (America/Cuiaba)
$ perl now.pl "Mos Eisley"
Unrecognized city 'Mos Eisley'

now.pl works by first using the Geo::GeoNames module to look up in the GeoNames database via the Internet the time zone for the town/city you have specified, then using the Date::Time module to look up the time in that time zone from the zoneinfo data in your installation, based on the time now in your installation’s system clock. In other words, if your system clock is, for example, 3 minutes ahead of actual time then the time returned by now.pl for the relevant time zone would also be 3 minutes fast. But if your system clock is correct, the script would return an accurate time for the requested town/city.

My interest in finding a command that returns the current time at any town or city around the Globe was because I wanted to create a keyboard shortcut to insert a signature in my e-mails, displaying my current location and the local time wherever I happened to be (I have to travel internationally frequently because of my work). In my next post I will explain how I created such an e-mail signature.

Gentoo Linux: Run a script at shutdown, but not when rebooting

In Gentoo Linux it is straightforward to run scripts automatically when the OS starts (boots) and stops (either shutting down or rebooting). You simply need to place an executable script file in the directory /etc/local.d/ with the suffix ‘.start‘ or ‘.stop‘, depending on whether you want the script to run at the beginning or end of your Linux session. The file /etc/local.d/README (complete with ‘sequentially’ misspelt) explains it better:

This directory should contain programs or scripts which are to be run
when the local service is started or stopped.

If a file in this directory is executable and it has a .start extension,
it will be run when the local service is started. If a file is
executable and it has a .stop extension, it will be run when the local
service is stopped.

All files are processed in lexical order.

Keep in mind that files in this directory are processed sequencially,
and the local service is not considered started or stopped until
everything is processed, so if you have a process which takes a long
time to run, it can delay your boot or shutdown processing.

Scripts with a ‘.stop‘ suffix are launched both when you shutdown your Linux installation and when you reboot it. However, sometimes you may not want to run a script when you reboot your installation. A typical example would be a script to backup your hard drive; you would probably only want it to run when you have finished for the day and you are shutting down and powering off your machine. So, how do you achieve that? I initially thought I would be able to use the ‘runlevel‘ command or the RUNLEVEL environment variable in a script (see man runlevel regarding both). But I could not get my script /etc/local.d/10-run_on_shutdown.stop to work using either. However, the command ‘who -r‘ (‘who --runlevel‘) does work for me in Gentoo Linux with OpenRC:

$ cat /etc/local.d/10-run_on_shutdown.stop
#!/bin/bash
if [ `who -r | awk '{print $2}'` = "0" ]; then
  echo "shutting down" >> /home/fitzcarraldo/test.txt
  date >> /home/fitzcarraldo/test.txt
elif [ `who -r | awk '{print $2}'` = "6" ]; then
  echo "rebooting" >> /home/fitzcarraldo/test.txt
  date >> /home/fitzcarraldo/test.txt
else
  echo "neither rebooting nor shutting down" >> /home/fitzcarraldo/test.txt
  date >> /home/fitzcarraldo/test.txt
fi
$

After rebooting, then shutting down and booting, then rebooting again, the contents of the file test.txt show that the above-mentioned simple script works as intended:

$ cat test.txt
rebooting
Sun  6 Sep 12:42:11 BST 2015
shutting down
Sun  6 Sep 12:46:04 BST 2015
rebooting
Sun  6 Sep 12:49:31 BST 2015
$

So the following script /etc/local.d/10-run_on_shutdown.stop will do the desired job:

$ cat /etc/local.d/10-run_on_shutdown.stop
#!/bin/bash
if [ `who -r | awk '{print $2}'` = "0" ]; then
  ######################################################################
  # Put Bash commands here to be executed on shutdown but not on reboot.
  ######################################################################
fi
$

Don’t forget to make the script executable:

# chmod +x /etc/local.d/10-run_on_shutdown.stop

Gentoo Linux installations without initramfs: Updating Intel CPU microcode

This post explains how I configured the Gentoo Linux (amd64) installation on my Clevo W230SS laptop to make it update the Intel CPU microcode using the kernel Microcode Early Update driver.

Back in April I installed Gentoo Linux Stable and built the kernel using the default manual configuration steps given in the Gentoo Handbook, and my installation therefore did not use an initramfs. The contents of the /boot directory were as listed below:

# ls -1 /boot
System.map-3.18.11-gentoo
config-3.18.11-gentoo
grub
lost+found
vmlinuz-3.18.11-gentoo

Contrast the above with the boot directory of the Gentoo Linux Testing (~amd64) installation on my Compal NBLB2 laptop, which does use an initramfs because I built the kernel using the optional genkernel utility:

# ls -1 /boot
System.map-genkernel-x86_64-3.18.11-gentoo
boot
grub
initramfs-genkernel-x86_64-3.18.11-gentoo
kernel-genkernel-x86_64-3.18.11-gentoo
lost+found

Since I wrote my earlier post on updating CPU microcode, the use of a kernel module and initscript to update CPU microcode has been dropped (in Gentoo Linux, at least). This is because updating CPU microcode relatively late in the boot process may cause problems if some processes have started before the update has taken place. The only safe way to update CPU microcode is to use the kernel’s built-in Microcode Early Update driver (METHOD 2 in my earlier post).

Now, new versions of the relevant Gentoo Linux ebuilds (microcode-ctl-1.28-r1, microcode-data-20150121-r1 and iucode_tool-1.3) have recently been released (see Gentoo Bug Report No. 528712). If a Gentoo Linux installation does not use an initramfs, the microcode-data ebuild now includes an ‘initramfs‘ USE flag which you can set in order to create a minimal initramfs to load the CPU microcode at boot. Below I explain in detail how I configured my installation to update the CPU microcode early during boot.

Before doing anything at all, I checked the microcode version for my CPU (Intel Core i7-4810MQ @ 2.80GHz):

# grep microcode /proc/cpuinfo
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
# dmesg | grep microcode
[    0.262544] microcode: CPU0 sig=0x306c3, pf=0x10, revision=0x12
[    0.262641] microcode: CPU1 sig=0x306c3, pf=0x10, revision=0x12
[    0.262740] microcode: CPU2 sig=0x306c3, pf=0x10, revision=0x12
[    0.262841] microcode: CPU3 sig=0x306c3, pf=0x10, revision=0x12
[    0.262939] microcode: CPU4 sig=0x306c3, pf=0x10, revision=0x12
[    0.263038] microcode: CPU5 sig=0x306c3, pf=0x10, revision=0x12
[    0.263138] microcode: CPU6 sig=0x306c3, pf=0x10, revision=0x12
[    0.263236] microcode: CPU7 sig=0x306c3, pf=0x10, revision=0x12
[    0.263367] microcode: Microcode Update Driver: v2.00 , Peter Oruba

Fortunately I did not need to rebuild the kernel as I had already configured it back in April when I installed Gentoo, with a view to implementing early microcode updating at some point:

# grep CONFIG_BLK_DEV_INITRD /usr/src/linux/.config
CONFIG_BLK_DEV_INITRD=y
# grep CONFIG_MICROCODE /usr/src/linux/.config
CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=y
# CONFIG_MICROCODE_AMD is not set
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_MICROCODE_INTEL_EARLY=y
# CONFIG_MICROCODE_AMD_EARLY is not set
CONFIG_MICROCODE_EARLY=y
# grep CONFIG_INITRAMFS_SOURCE /usr/src/linux/.config
CONFIG_INITRAMFS_SOURCE=""

Then I set the initramfs USE flag and unmasked the ~amd64 ebuilds created by Gentoo developer SpanKY (microcode-ctl-1.28-r1.ebuild, microcode-data-20150121-r1.ebuild and iucode_tool-1.3.ebuild) as discussed in the above-mentioned Gentoo bug report:

# cat /etc/portage/package.use/microcode-data
sys-apps/microcode-data initramfs
# cat /etc/portage/package.accept_keywords/microcode-data
sys-apps/microcode-data ~amd64
sys-apps/iucode_tool ~amd64
# cat /etc/portage/package.accept_keywords/microcode-ctl
sys-apps/microcode-ctl ~amd64

Then I merged the packages:

# emerge --ask microcode-ctl microcode-data

This resulted in the following files:

# ls -la /lib/firmware/microcode.cpio
-rw-r--r-- 1 root root 663552 Aug 26 15:06 /lib/firmware/microcode.cpio
# ls -la /lib/firmware/intel-ucode
total 768
drwxr-xr-x  2 root root  4096 Aug 26 15:06 .
drwxr-xr-x 62 root root 16384 Aug 26 15:06 ..
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-03-02
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-05-00
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-05-01
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-05-02
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-05-03
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-06-00
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-06-05
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-06-0a
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-06-0d
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-07-01
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-07-02
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-07-03
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-08-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-08-03
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-08-06
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-08-0a
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-09-05
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-0a-00
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-0a-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0b-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0b-04
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-0d-06
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0e-08
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-0e-0c
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-0f-02
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-0f-06
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-0f-07
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0f-0a
-rw-r--r--  1 root root 28672 Aug 26 15:06 06-0f-0b
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-0f-0d
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-16-01
-rw-r--r--  1 root root 20480 Aug 26 15:06 06-17-06
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-17-07
-rw-r--r--  1 root root 24576 Aug 26 15:06 06-17-0a
-rw-r--r--  1 root root 14336 Aug 26 15:06 06-1a-04
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-1a-05
-rw-r--r--  1 root root 15360 Aug 26 15:06 06-1c-02
-rw-r--r--  1 root root 20480 Aug 26 15:06 06-1c-0a
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-1d-01
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-1e-04
-rw-r--r--  1 root root  7168 Aug 26 15:06 06-1e-05
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-25-02
-rw-r--r--  1 root root  3072 Aug 26 15:06 06-25-05
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-26-01
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-2a-07
-rw-r--r--  1 root root 16384 Aug 26 15:06 06-2d-06
-rw-r--r--  1 root root 17408 Aug 26 15:06 06-2d-07
-rw-r--r--  1 root root 13312 Aug 26 15:06 06-2f-02
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-3a-09
-rw-r--r--  1 root root 21504 Aug 26 15:06 06-3c-03
-rw-r--r--  1 root root 14336 Aug 26 15:06 06-3d-04
-rw-r--r--  1 root root 13312 Aug 26 15:06 06-3e-04
-rw-r--r--  1 root root 11264 Aug 26 15:06 06-3e-06
-rw-r--r--  1 root root 15360 Aug 26 15:06 06-3e-07
-rw-r--r--  1 root root 28672 Aug 26 15:06 06-3f-02
-rw-r--r--  1 root root 20480 Aug 26 15:06 06-45-01
-rw-r--r--  1 root root 23552 Aug 26 15:06 06-46-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 0f-00-07
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-00-0a
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-01-02
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-02-04
-rw-r--r--  1 root root  8192 Aug 26 15:06 0f-02-05
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-02-06
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-02-07
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-02-09
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-03-02
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-03-03
-rw-r--r--  1 root root  7168 Aug 26 15:06 0f-03-04
-rw-r--r--  1 root root 10240 Aug 26 15:06 0f-04-01
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-04-03
-rw-r--r--  1 root root  3072 Aug 26 15:06 0f-04-04
-rw-r--r--  1 root root  3072 Aug 26 15:06 0f-04-07
-rw-r--r--  1 root root  9216 Aug 26 15:06 0f-04-08
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-04-09
-rw-r--r--  1 root root  4096 Aug 26 15:06 0f-04-0a
-rw-r--r--  1 root root  3072 Aug 26 15:06 0f-06-02
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-06-04
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-06-05
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-06-08

(By the way, the file 06-3c-03 is the microcode file for my particular CPU: Family 06h, Model 03Ch, Stepping 03h, as determined from the CPU World Web site.)

Then I copied to the boot directory the cpio file created when I merged the packages:

# cp /lib/firmware/microcode.cpio /boot/

Then I added an initrd line to /boot/grub/grub.cfg as shown below:

# grep -B 15 -A 1 initrd /boot/grub/grub.cfg

### BEGIN /etc/grub.d/10_linux ###
menuentry 'Gentoo GNU/Linux' --class gentoo --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-525a90f1-8ad2-44a3-ade3-20f18a0a9595' {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1  f6ffc085-66fe-4bbe-b080-cec355749f85
        else
          search --no-floppy --fs-uuid --set=root f6ffc085-66fe-4bbe-b080-cec355749f85
        fi
        echo    'Loading Linux 3.18.11-gentoo ...'
        linux   /vmlinuz-3.18.11-gentoo root=/dev/sda5 ro  drm_kms_helper.edid_firmware=edid/1920x1080_Clevo_W230SS.bin i915.modeset=1 rcutree.rcu_idle_gp_delay=1
        initrd /microcode.cpio
}

After rebooting:

# grep microcode /proc/cpuinfo
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
# dmesg | grep microcode
[    0.000000] CPU0 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.049968] CPU1 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.065070] CPU2 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.080101] CPU3 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.268736] microcode: CPU0 sig=0x306c3, pf=0x10, revision=0x1c
[    0.268838] microcode: CPU1 sig=0x306c3, pf=0x10, revision=0x1c
[    0.268935] microcode: CPU2 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269034] microcode: CPU3 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269131] microcode: CPU4 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269230] microcode: CPU5 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269329] microcode: CPU6 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269448] microcode: CPU7 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269570] microcode: Microcode Update Driver: v2.00 , Peter Oruba

As you can see above, the microcode early update kernel driver updates the microcode version to 0x1c at boot (cf. 0x12 originally). If you have a different model of CPU to mine, of course the version in your case could be different.

Note that the line ‘initrd /lib/firmware/microcode.cpio‘ in the file grub.cfg does not work for me. It has to be ‘initrd /microcode.cpio‘ and the file microcode.cpio has to be in the /boot directory:

# ls /boot
System.map-3.18.11-gentoo  config-3.18.11-gentoo  grub  lost+found  microcode.cpio  vmlinuz-3.18.11-gentoo

Note also that the precise steps specified in Comment #41 of Gentoo Bug Report No. 528712 do not work for me and others (see Gentoo Forums thread microcode-data-20150121-r1 with USE=initramfs: kernel panic). If I build the kernel with CONFIG_INITRAMFS_SOURCE="/lib/firmware/microcode.cpio", delete the line ‘initrd /microcode‘ from grub.cfg, delete the file /boot/microcode.cpio and reboot, the kernel panics and the last two console lines are as follows:

[    3.142079] drm_kms_helper: panic occurred, switching back to text console
[    3.142879] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,5)

Unless Gentoo developer SpanKY explains how he managed to get the procedure he gave in Comment #41 of Gentoo Bug Report No. 528712 to work, it seems the normal behaviour when applying the steps he gave would be for the kernel to panic. Even Gentoo developer Daniel Pielmeier experienced a kernel panic when he applied SpanKY‘s steps (Comment #54 of Gentoo Bug Report No. 528712).

As the procedure I gave above works fine, I therefore reverted to using CONFIG_INITRAMFS_SOURCE="", copying /lib/firmware/microcode.cpio to /boot/microcode.cpio again and re-adding the line ‘initrd /microcode.cpio‘ in the file grub.cfg. However, if you did not have an initramfs and were able to get the precise procedure given in Comment #41 of Gentoo Bug Report #528712 to work, please post a comment here.

Follow

Get every new post delivered to your Inbox.

Join 67 other followers