Enabling other users to login from the xscreensaver lockscreen in Lubuntu 20.10

If Lubuntu 20.10 suspends to RAM, xscreensaver displays a lockscreen with login window when the system resumes. However, LXQt and SDDM currently do not provide a ‘Switch User’ option, so, if you are not the currently logged-in user and you do not know that user’s password, you will be stuck on the xscreensaver lockscreen. If you click on ‘New Login’ in the xscreensaver window, a message similar to the following is displayed and there is no way for a different user to login:

xscreensaver: 19:01:52: could not execute "gdmflexiserver": No such file or directory

To get around this problem so that other users can login, create the file /usr/local/bin/gdmflexiserver containing the following two lines:

#!/bin/bash
who | awk '!/root/{ cmd="/usr/bin/pkill -KILL -u " $1; system(cmd)}'

Make it executable:

$ sudo chmod +x /usr/local/bin/gdmflexiserver

Now, when the xscreensaver login window appears, if you do not know the currently logged-in user’s password you can click on the ‘New Login’ button instead and the SDDM greeter screen will be displayed so that another user can login. Note that clicking on ‘New Login’ will lose all the open windows and any running applications in the current user’s session, but at least a different user will not be prevented from logging-in and using the machine if the original user is not available to login then logout from his/her session. Of course, if the current user is still available, he/she can simply unlock the current session as usual via the xscreensaver lockscreen window.

Implementing a scheme for system-wide automatic Suspend to RAM in Lubuntu 20.10

Lubuntu 20.10 is installed on my family’s desktop PC (single-seat, multi-user). This version of the distribution uses the SDDM display manager and the LXQt desktop environment. Previously the machine had Lubuntu 18.04 installed, which used the LightDM display manager and the LXDE desktop environment.

In Lubuntu 18.04 each user could configure the power manager in their LXDE session to make the machine suspend to RAM if that user was logged-in but had not used the keyboard and mouse for a user-specified number of minutes. The problem with that approach was that, if two or more users happened to be logged-in simultaneously because a user did not log out and another user used ‘Switch User’ in LXDE to log-in, the power manager in a logged-in but unused session would eventually suspend the machine even though another user was still active in a different session. Very annoying. Secondly, if nobody was logged-in and the LightDM greeter screen was displayed, the machine would not suspend to RAM automatically after a period of inactivity; the only way to get the machine to suspend to RAM if nobody was logged-in was to suspend it manually from the greeter screen. I implemented my own fix for both problems in Lubuntu 18.04 (see my previous blog posts How to make LightDM suspend to RAM automatically from the login screen and lock screen in Lubuntu 18.04 and How to stop inactive user sessions triggering Suspend to RAM in a single-seat, multi-user installation of Lubuntu 18.04) but I had to use a different approach in Lubuntu 20.10 because it uses SDDM and LXQt.

The new scheme I implemented in Lubuntu 20.10 is partly an academic exercise because LXQt in Lubuntu 20.10 does not have a ‘Switch User’ option that would enable more than one user to be logged in simultaneously. LXQt Issue 14 and SDDM Issue 991 appear to be about this limitation. Furthermore, I think systemd may also be a factor (Lubuntu uses Version 246, which no longer includes seat_can_multi_session() that the version of SDDM in Lubuntu 20.10 may depend on for the ‘Switch User’ option). The disappearance of a ‘Switch User’ option has been reported previously for various Linux distributions using KDE and systemd 246, such as Arch Linux, Gentoo Linux and Kubuntu. Therefore it may be that all three packages would need to be altered in order for Lubuntu to provide a ‘Switch User’ option. Anyway, the scheme I have implemented in Lubuntu 20.10 could handle more than one user logged-in simultaneously if that were possible, as I catered for that possibility in case future updates to LXQt and SDDM have a ‘Switch User’ option. Even without a ‘Switch User’ option in LXQt, my scheme enables Lubuntu 20.10 to suspend to RAM automatically when no one is logged in and the SDDM greeter screen is displayed, which is also useful. Furthermore, my scheme also provides system-wide Suspend to RAM control, removing the need for users to touch the LXQt power manager settings in their individual user accounts.

Note that, as was the case in Lubuntu 18.04, Lubuntu 20.10 does not terminate all the user’s processes when the user logs out. This can be seen if you use the ‘ps -ef‘ command when logged in as a different user. Also, the user’s session is not closed; its state is always shown as ‘closing’ if you use the ‘loginctl list-sessions‘ and ‘loginctl session-status <ID>‘ commands. I suspect this behaviour is a ‘feature’ of systemd rather than Lubuntu itself, but I could be wrong. Anyway, in order to cater for this behaviour my scheme is more complex than it would be otherwise.

By the way, I believe this scheme would probably work in other Linux distributions that use systemd and have a desktop environment that can be configured to launch scripts automatically at login. In fact, the scheme could also be adapted for use in a distribution that does not use systemd. For example, in an installation that uses OpenRC the suspend.sh script (see further down) could be launched at boot from a script in the /etc/local.d/ directory. In distributions without systemd the logger command could be used to log messages in the system log file.

My scheme to provide system-wide automatic Suspend to RAM in Lubuntu 20.10 is detailed below. If new versions of LXQt, SDDM and systemd (whichever of those is required for a ‘Switch User’ option) are added to the Lubuntu repositories in future, hopefully the scheme detailed below already caters for that option.

1. Select ‘Preferences’ > ‘LXQt settings’ > ‘Power Management’ in each user’s LXQt account, click on ‘Idle’ and untick ‘Enable Idleness Watcher’ to prevent LXQt Power Manager in each user’s LXQt session from suspending to RAM independently.

Note: It is possible for the system administrator to configure this for all users via the command line instead. For example:

$ nano ~/.config/lxqt/lxqt-powermanagement.conf

Change ‘enableIdlenessWatcher=true‘ to ‘enableIdlenessWatcher=false‘:

[General]
__userfile__=true
backlightIdleness=0
backlightIdlenessOnBatteryDischarging=true
enableBatteryWatcher=false
enableIdlenessBacklightWatcher=false
enableIdlenessWatcher=false
enableLidWatcher=false
idlenessAction=-1
idlenessTime=@Variant(\0\0\0\xf\0\0\x3\xe8)
idlenessTimeSecs=900
runCheckLevel=1
$ $ ls -la ~/.config/lxqt/lxqt-powermanagement.conf
-rw-rw-r-- 1 fitzcarraldo fitzcarraldo 304 Feb  8 22:10 /home/bill/.config/lxqt/lxqt-powermanagement.conf
$ sudo cp ~/.config/lxqt/lxqt-powermanagement.conf /home/aquilino/.config/lxqt/lxqt-powermanagement.conf
$ sudo chown aquilino.aquilino /home/aquilino/.config/lxqt/lxqt-powermanagement.conf
$ sudo chmod 664 /home/aquilino/.config/lxqt/lxqt-powermanagement.conf

and so on for every user. For example, if the installation has accounts for five users with usernames aquilino, cholo, fitzcarraldo, molly and paul:

$ sudo updatedb; sudo locate lxqt-powermanagement.conf | grep .config                                      
/home/aquilino/.config/lxqt/lxqt-powermanagement.conf
/home/cholo/.config/lxqt/lxqt-powermanagement.conf
/home/fitzcarraldo/.config/lxqt/lxqt-powermanagement.conf
/home/molly/.config/lxqt/lxqt-powermanagement.conf
/home/paul/.config/lxqt/lxqt-powermanagement.conf

2. Install the X Windows utility xprintidle so it can be used in a Bash script to determine when a user is idle or active:

$ sudo apt install xprintidle

3. Create the script /usr/local/bin/check_if_idle.sh

An instance of this script will be launched when each user logs in to the desktop environment (see Step 4). Each instance of the script will run continuously and its purpose is to create periodically a file with a specific name, or periodically delete files with specific names, in the RAM-based /tmp/ directory. These zero-length files are used to inform the suspend.sh script (see Step 5) whether or not the applicable user has been using the keyboard or mouse within a specified timeout period (specified as 15 minutes in the script). From now on I will use the term ‘flag-files’ when referring to such files, as they are effectively Boolean flags to pass binary information from a Bash script in each user’s session to a Bash script that actually initiates suspending to RAM. If the active user’s session has been idle for the specified timeout period, the script deletes all that user’s flag-files in order to indicate to the suspend.sh script that the specific user is no longer an impediment to suspending to RAM. Similarly, when the user logs out, the applicable flag-file is deleted in order to indicate to the suspend.sh script that the user is no longer an impediment to suspending. The flag-file is not deleted if the user is logged in but not the active user, in order to indicate to the suspend.sh script that it must not suspend to RAM unless the active user has been idle for the specified timeout period (notice that the script check_if_idle.sh deletes all the user’s non-VT (Virtual Terminal, a.k.a. ‘TTY console’) flag-files when the active user has been idle for the specified timeout period).

$ sudo nano /usr/local/bin/check_if_idle.sh
#!/bin/bash
CurrentUser=$(whoami)
touch /tmp/not_idle_$CurrentUser$BASHPID
IdleAfter=900000 # consider idle after 900000 ms (15 min) of inactivity
while true; do
  State=$( loginctl session-status | grep -m 1 State | awk -F " " '{ print $2 }' )
  if [[ "$State" == "active" ]]; then
  IdleTimeMillisecs=$(xprintidle 2>/dev/null)
    if [[ $IdleTimeMillisecs -ge $IdleAfter ]]; then
      rm /tmp/not_idle_$CurrentUser* 2>/dev/null
    fi
    if [[ $IdleTimeMillisecs -lt $IdleAfter ]]; then
      touch /tmp/not_idle_$CurrentUser$BASHPID
    fi
  elif [[ "$State" == "online" ]]; then
    touch /tmp/not_idle_$CurrentUser$BASHPID
  elif [[ "$State" == "closing" ]]; then
    rm /tmp/not_idle_$CurrentUser$BASHPID 2>/dev/null
  fi
  sleep 1
done
$ chmod 755 /usr/local/bin/check_if_idle.sh

As far as I have been able to ascertain from systemd documentation, currently the following three session states are possible: “online” (session logged in, but session not active, i.e. not in the foreground), “active” (session logged in and active, i.e. in the foreground), “closing” (session nominally logged out, but some processes belonging to it are still around).

Note: I could have created a separate configuration file and made the Bash script read $IdleAfter from it, but I decided to keep things simple and specify the time-out period in the script itself.

4. Add the following command to LXQt Application Menu > Preferences > LXQt settings > Session Settings > Autostart > LXQt Autostart for each user (give it the name ‘Check_if_idle’) so that an instance of check_if_idle.sh is launched automatically when a user logs in:

/usr/local/bin/check_if_idle.sh

Note: It is possible for the system administrator to configure this for all users via the command line instead. For example:

$ nano ~/.config/autostart/Check_if_idle.desktop
[Desktop Entry]
Exec=/usr/local/bin/check_if_idle.sh
Name=Check_if_idle
OnlyShowIn=LXQt;
Type=Application
Version=1.0
$ ls -la ~/.config/autostart/Check_if_idle.desktop
-rw-rw-r-- 1 fitzcarraldo fitzcarraldo 118 Feb  9 13:27 /home/fitzcarraldo/.config/autostart/Check_if_idle.desktop
$ sudo cp ~/.config/autostart/Check_if_idle.desktop /home/aquilino/.config/autostart/Check_if_idle.desktop
$ sudo chown aquilino.aquilino /home/aquilino/.config/autostart/Check_if_idle.desktop
$ sudo chmod 664 /home/aquilino/.config/autostart/Check_if_idle.desktop

and so on for every user. For example, if the installation has accounts for five users with usernames aquilino, cholo, fitzcarraldo, molly and paul:

$ sudo updatedb; sudo locate Check_if_idle.desktop
/home/aquilino/.config/autostart/Check_if_idle.desktop
/home/cholo/.config/autostart/Check_if_idle.desktop
/home/fitzcarraldo/.config/autostart/Check_if_idle.desktop
/home/molly/.config/autostart/Check_if_idle.desktop
/home/paul/.config/autostart/Check_if_idle.desktop

5. Create the script /usr/local/bin/suspend.sh

This script will be a service launched at boot via a systemd unit file. Its purpose is twofold:

  • to check periodically if there has been keyboard and mouse activity while the SDDM greeter screen is displayed and to suspend to RAM if there has not been any activity within a specificed timeout period (which I have also specified as 15 minutes);
  • to check periodically for flag-files in the /tmp/ directory to ascertain if there has been any activity by logged-in LXQt users within a specified timeout period, and to ascertain if any user is logged in to a VT, and to suspend to RAM if neither of those are the case.
#!/bin/bash
rm /tmp/not_idle_* 2>/dev/null
rm /tmp/triggered_suspend_greeter 2>/dev/null
rm /tmp/triggered_suspend 2>/dev/null
IdleAfter=900000 # Consider SDDM Greeter idle after 900000 ms (15 min) of inactivity
while true; do
  sleep 30 # Do not delete this line or reduce the time
  NumLoggedInUsers=$(who -qs | grep -o '[0-9]\+')
  if [[ $NumLoggedInUsers -eq 0 ]]; then
    rm /tmp/not_idle_* 2>/dev/null
    AuthFile=$(find /var/run/sddm/ -type f)
    if IdleTimeMillisecs=$(DISPLAY=:0 XAUTHORITY=$AuthFile xprintidle 2>/dev/null) ; then
      Running_in_X_Windows=true
    else
      echo "Cannot calc Idle time for Greeter screen." # Log the problem in systemd journal.
      IdleTimeMillisecs=0
      Running_in_X_Windows=false
    fi
    if [[ $IdleTimeMillisecs -gt $IdleAfter ]] ; then
      touch /tmp/triggered_suspend_greeter
      systemctl suspend -i # Comment out when debugging
    fi
  else
    # Only suspend if all users have been idle for the time specified in /usr/local/bin/check_if_idle.sh
    if [[ `ls -1 /tmp/not_idle_* 2>/dev/null | wc -l` -eq 0 ]]; then
      touch /tmp/triggered_suspend
      systemctl suspend -i
    fi
  fi
done
$ sudo chmod 755 /usr/local/bin/suspend.sh

Note: I could have created a separate configuration file and made the Bash script read $IdleAfter from it, but I decided to keep things simple and specify the timeout period in the script itself.

6. Create the systemd unit file /etc/systemd/system/suspend.service so that systemd can launch the suspend.sh script at boot. Note that this service is different to, and independent from, systemd’s service for suspending to RAM (systemd-suspend.service).

[Unit]
Description=Suspend to RAM if idle for specified time

Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/suspend.sh
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target
$ sudo chmod 640 /etc/systemd/system/suspend.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable suspend.service

7. Add the following lines to the end of each user’s ~/.profile file:

# Stop /usr/local/bin/suspend.sh suspending to RAM if this user logs in to a VT
CurrentUser=$(whoami)
CurrentVT=$(tty | grep -o '[0-9]\+') # Will be zero if not run on a VT
rm /tmp/not_idle_$CurrentUser* 2>/dev/null
if [[ $CurrentVT -ne 0 ]]; then
  touch /tmp/not_idle_VT"$CurrentVT"_"$CurrentUser"
fi

This addition only creates a flag-file if the applicable user logs in to a VT, and the flag-file is created using a different naming convention to flag-files for LXQt processes in order to be able to distinguish between specific VT console use and pseudo-terminal use, to prevent the suspend.sh script from suspending to RAM while a user is logged in to a VT.

8. Add the following lines to the end of each user’s ~/.bash_logout file:

# Allow /usr/local/bin/suspend.sh to suspend to RAM after this user logs out from a VT session
CurrentUser=$(whoami)
CurrentVT=$(tty | grep -o '[0-9]\+')
if [[ $CurrentVT -ne 0 ]]; then
  rm /tmp/not_idle_VT"$CurrentVT"_"$CurrentUser" 2>/dev/null
fi

The flag-file uses a different naming convention to flag-files used for LXQt processes, in order to be able to indicate to the suspend.sh script that the specific VT user has logged out and therefore is no longer an impediment to suspending to RAM.

9. Create the file /usr/lib/systemd/system-sleep/automatic-suspend-scheme to log when the scheme causes the system to suspend to RAM and also when the system wakes from that suspension.

$ sudo nano /usr/lib/systemd/system-sleep/automatic_suspend_scheme
#!/bin/bash
# This hook script will run when suspending/hibernating and when resuming/thawing.
# Check $1 ('pre' or 'post') and $2 ('suspend', 'hibernate', or 'hybrid-sleep') to ascertain
# which is happening.
case $1/$2 in
  pre/*)
    # Put here any commands you want to be run when suspending or hibernating.
    if [[ -f /tmp/triggered_suspend_greeter ]]; then
      echo "Automatic Suspend Scheme - Suspend to RAM (No users logged in)." # Log the event in the systemd journal
    fi
    if [[ -f /tmp/triggered_suspend ]]; then
      echo "Automatic Suspend Scheme - Suspend to RAM." # Log the event in the systemd journal
    fi
    ;;
  post/*)
    # Put here any commands you want to be run when resuming from suspension or thawing from hibernation.
    if [[ -f /tmp/triggered_suspend_greeter ]]; then
      echo "Automatic Suspend Scheme - Resuming from Suspend to RAM (No users logged in)." # Log the event in the systemd journal
      rm /tmp/triggered_suspend_greeter
    fi
    if [[ -f /tmp/triggered_suspend ]]; then
      echo "Automatic Suspend Scheme - Resuming from Suspend to RAM." # Log the event in the systemd journal
      rm /tmp/triggered_suspend
    fi
    ;;
esac
$ sudo chmod 755 /usr/lib/systemd/system-sleep/automatic_suspend_scheme

10. Reboot and test

From now on, the installation should suspend to RAM if all logged-in LXQt users have been inactive for 15 minutes or more. This does not preclude any user selecting Leave > Suspend from the LXQt Application Menu to suspend to RAM manually. If no users are logged in — i.e. the SDDM greeter screen is displayed on the monitor — the installation will suspend to RAM if there is no keyboard and mouse activity for 15 minutes. This does not preclude any user clicking on the icon on the SDDM greeter screen to suspend the machine to RAM manually. The Bash scripts suspend.sh and check_if_idle.sh can be edited to alter the timeout period if a different timeout is desired. The scheme will not trigger suspending to RAM while someone is logged in via a VT (a.k.a. TTY console). I am the only person in my family who knows how to use a VT; all the other family members use only the LXQt desktop environment.

Caveat: The suspend.sh script can initiate suspending to RAM if no /tmp/not_idle_* files exist, so do not delete manually any of the not_idle_* files in the /tmp/ directory.

If you want to check what is happing to the sessions, processes and flag-files, the following commands are useful:

$ systemctl status suspend
$ ps -ef | grep check
$ ps -ef | grep suspend
$ ls /tmp/not_idle*
$ loginctl list-sessions
$ loginctl session-status <session number> | grep State

For example, below is some output from those commands when users paul and aquilino were using the machine. User paul booted the machine and logged-in on the SDDM greeter screen, then logged out to let user aquilino login on the SDDM greeter screen. Then user aquilino logged out and user paul logged in again on the SDDM greeter screen and entered the following commands in a pseudo-terminal (e.g. QTerminal) window:

$ systemctl status suspend
● suspend.service - Suspend to RAM if idle for specified time
     Loaded: loaded (/etc/systemd/system/suspend.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2021-02-11 16:25:53 GMT; 35min ago
   Main PID: 966 (suspend.sh)
      Tasks: 2 (limit: 4476)
     Memory: 1.5M
     CGroup: /system.slice/suspend.service
             ├─  966 /bin/bash /usr/local/bin/suspend.sh
             └─36254 sleep 30

Feb 11 16:25:53 aspirexc600 systemd[1]: Started Suspend to RAM if idle for specified time.
$ ps -ef | grep check
paul        1337       1  0 16:27 ?        00:00:01 /bin/bash /usr/local/bin/check_if_idle.sh
aquilino    4904       1  0 16:34 ?        00:00:01 /bin/bash /usr/local/bin/check_if_idle.sh
paul        9187       1  0 16:38 ?        00:00:01 /bin/bash /usr/local/bin/check_if_idle.sh
paul       37124    9236  0 17:01 pts/0    00:00:00 grep --color=auto check
$ ps -ef | grep suspend
root         966       1  0 16:25 ?        00:00:00 /bin/bash /usr/local/bin/suspend.sh
paul       38515    9236  0 17:02 pts/0    00:00:00 grep --color=auto suspend
$ ls /tmp/not_idle*
/tmp/not_idle_paul9187
$ loginctl list-sessions
SESSION  UID USER     SEAT  TTY
     12 1000 paul     seat0    
      3 1000 paul     seat0    
      8 1001 aquilino seat0    

3 sessions listed.
$ loginctl session-status 12 | grep State
           State: active
                  └─41171 grep --color=auto State
$ loginctl session-status 3 | grep State
           State: closing
$ loginctl session-status 8 | grep State
           State: closing

Then user paul pressed Ctrl+Alt+F2 to switch to VT2 (tty2), logged in as user paul and entered the commands:

$ ps -ef | grep check
paul        1337       1  0 16:27 ?        00:00:01 /bin/bash /usr/local/bin/check_if_idle.sh
aquilino    4904       1  0 16:34 ?        00:00:01 /bin/bash /usr/local/bin/check_if_idle.sh
paul        9187       1  0 16:38 ?        00:00:01 /bin/bash /usr/local/bin/check_if_idle.sh
paul       50191   48181  0 17:12 tty2     00:00:00 grep --color=auto check
$ ps -ef | grep suspend
root         966       1  0 16:25 ?        00:00:00 /bin/bash /usr/local/bin/suspend.sh
paul       50295   48181  0 17:12 tty2     00:00:00 grep --color=auto suspend
$ ls /tmp/not_idle*
/tmp/not_idle_paul9187  /tmp/not_idle_VT2_paul
$ loginctl list-sessions
SESSION  UID USER     SEAT  TTY
     12 1000 paul     seat0    
     15 1000 paul     seat0 tty2
      3 1000 paul     seat0    
      8 1001 aquilino seat0    

4 sessions listed.
$ loginctl session-status 12 | grep State
           State: online
$ loginctl session-status 15 | grep State
           State: active
                  └─50741 grep --color=auto State
$ loginctl session-status 3 | grep State
           State: closing
$ loginctl session-status 8 | grep State
           State: closing

Then user paul pressed Ctrl+Alt+F1 to switch back to his LXQt session and entered the following commands in the already open pseudo-terminal window:

$ ps -ef | grep check
paul        1337       1  0 16:27 ?        00:00:02 /bin/bash /usr/local/bin/check_if_idle.sh
aquilino    4904       1  0 16:34 ?        00:00:02 /bin/bash /usr/local/bin/check_if_idle.sh
paul        9187       1  0 16:38 ?        00:00:02 /bin/bash /usr/local/bin/check_if_idle.sh
paul       61359    9236  0 17:22 pts/0    00:00:00 grep --color=auto check
$ ps -ef | grep suspend
root         966       1  0 16:25 ?        00:00:00 /bin/bash /usr/local/bin/suspend.sh
paul       61473    9236  0 17:22 pts/0    00:00:00 grep --color=auto suspend
$ ls /tmp/not_idle*
/tmp/not_idle_paul9187  /tmp/not_idle_VT2_paul
$ loginctl list-sessions
SESSION  UID USER     SEAT  TTY 
     12 1000 paul     seat0     
     15 1000 paul     seat0 tty2
      3 1000 paul     seat0     
      8 1001 aquilino seat0     

4 sessions listed.
$ loginctl session-status 12 | grep State
           State: active
                  └─62165 grep --color=auto State
$ loginctl session-status 15 | grep State
           State: online
$ loginctl session-status 3 | grep State
           State: closing
$ loginctl session-status 8 | grep State
           State: closing

Then user paul pressed Ctrl+Alt+F2 to switch back to tty2, entered ‘exit‘ to log out of his VT session, then pressed Ctrl+Alt+F1 to switch back to his LXQt session and entered the following commands:

$ ps -ef | grep check
paul        1337       1  0 16:27 ?        00:00:03 /bin/bash /usr/local/bin/check_if_idle.sh
aquilino    4904       1  0 16:34 ?        00:00:03 /bin/bash /usr/local/bin/check_if_idle.sh
paul        9187       1  0 16:38 ?        00:00:03 /bin/bash /usr/local/bin/check_if_idle.sh
paul       92759    9236  0 17:48 pts/0    00:00:00 grep --color=auto check
$ ps -ef | grep suspend
root         966       1  0 16:25 ?        00:00:00 /bin/bash /usr/local/bin/suspend.sh
paul       92922    9236  0 17:48 pts/0    00:00:00 grep --color=auto suspend
$ ls /tmp/not_idle*
/tmp/not_idle_paul9187
$ loginctl list-sessions
SESSION  UID USER     SEAT  TTY
     12 1000 paul     seat0    
      3 1000 paul     seat0    
      8 1001 aquilino seat0    

3 sessions listed.
$ loginctl session-status 12 | grep State
           State: active
                  └─93554 grep --color=auto State
$ loginctl session-status 3 | grep State
           State: closing
$ loginctl session-status 8 | grep State
           State: closing

As you can see in the output above, even though user paul logged out of his first LXQt session (Session 3), and user aquilino logged out of his only LXQt session (Session 8), those two sessions did not end, remaining in the state ‘closing’. You can also see that user paul‘s VT session (Session 15) did close when he logged out on VT2 (tty2). Addiionally, you can see in the output above the flag-files that were created and deleted during that period.

The following command shows the entries in the systemd journal for the scheme’s service (suspend.service) since the system last booted:

$ journalctl -b -u suspend.service
-- Logs begin at Sat 2021-01-02 01:52:36 GMT, end at Sat 2021-02-13 01:16:09 GMT. --
Feb 13 00:24:18 aspirexc600 systemd[1]: Started Suspend to RAM if idle for specified time.

The above output shows no error messages since the service started at 00:24:18 when the system was last booted.

If you want to check the systemd journal to see when the scheme suspended the system to RAM automatically and was manually woken up from that sleep:

$ journalctl | grep "Automatic Suspend Scheme"

Add ‘-b‘ if you want to check only since the system last booted:

$ journalctl -b | grep "Automatic Suspend Scheme"
Feb 13 00:39:49 aspirexc600 systemd-sleep[1611]: Automatic Suspend Scheme - Suspend to RAM (No users logged in).
Feb 13 00:44:32 aspirexc600 systemd-sleep[1691]: Automatic Suspend Scheme - Resuming from Suspend to RAM (No users logged in).
Feb 13 01:01:59 aspirexc600 systemd-sleep[10470]: Automatic Suspend Scheme - Suspend to RAM.
Feb 13 01:04:52 aspirexc600 systemd-sleep[10556]: Automatic Suspend Scheme - Resuming from Suspend to RAM.

The following command shows entries in the systemd journal by the systemd suspend service (systemd-suspend.service) and systemd-sleep command since the system last booted, so it is possible to check both the times at which the automated scheme suspended and the times at which the system was manually suspended, and also the times at which the system was woken manually:

$ journalctl -b -u systemd-suspend.service
-- Logs begin at Sat 2021-01-02 01:52:36 GMT, end at Sat 2021-02-13 01:16:09 GMT. --
Feb 13 00:39:49 aspirexc600 systemd[1]: Starting Suspend...
Feb 13 00:39:49 aspirexc600 systemd-sleep[1611]: Automatic Suspend Scheme - Suspend to RAM (No users logged in).
Feb 13 00:39:49 aspirexc600 systemd-sleep[1609]: Suspending system...
Feb 13 00:44:32 aspirexc600 systemd-sleep[1609]: System resumed.
Feb 13 00:44:32 aspirexc600 systemd-sleep[1691]: Automatic Suspend Scheme - Resuming from Suspend to RAM (No users logged in).
Feb 13 00:44:32 aspirexc600 systemd[1]: systemd-suspend.service: Succeeded.
Feb 13 00:44:32 aspirexc600 systemd[1]: Finished Suspend.
Feb 13 01:01:59 aspirexc600 systemd[1]: Starting Suspend...
Feb 13 01:01:59 aspirexc600 systemd-sleep[10470]: Automatic Suspend Scheme - Suspend to RAM.
Feb 13 01:01:59 aspirexc600 systemd-sleep[10468]: Suspending system...
Feb 13 01:04:51 aspirexc600 systemd-sleep[10468]: System resumed.
Feb 13 01:04:52 aspirexc600 systemd-sleep[10556]: Automatic Suspend Scheme - Resuming from Suspend to RAM.
Feb 13 01:04:51 aspirexc600 systemd[1]: systemd-suspend.service: Succeeded.
Feb 13 01:04:51 aspirexc600 systemd[1]: Finished Suspend.
Feb 13 01:12:51 aspirexc600 systemd[1]: Starting Suspend...
Feb 13 01:12:51 aspirexc600 systemd-sleep[14964]: Suspending system...
Feb 13 01:15:50 aspirexc600 systemd-sleep[14964]: System resumed.
Feb 13 01:15:53 aspirexc600 systemd[1]: systemd-suspend.service: Succeeded.
Feb 13 01:15:53 aspirexc600 systemd[1]: Finished Suspend.

You can see above that the system automatically suspended to RAM at 00:39:49 after 15 minutes of inactivity on the SDDM greeter screen. Someone then pressed the space bar on the keyboard to wake the system at 00:44:32, and logged in to the LXQt desktop. The system suspended to RAM automatically again at 01:01:59 after that user had not touched the keyboard and mouse for 15 minutes in the active LXQt session. That user then woke the system manually again at 01:04:52, then manually suspended the system at 01:12:51 using the LXQt Application Menu (Leave > Suspend). Finally, at 01:15:50 the same user woke the system manually again.

11. Make /tmp/ RAM-based (optional)

By default, the Lubuntu 20.10 Installer creates the directory /tmp/ on the same disk partition as the root directory:

$ df -h /tmp
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2       916G  139G  731G  16% /

If your machine has plenty of RAM, if you want you could configure the system to mount a tmpfs filesystem on /tmp/ instead, as show below.

I decided to specify a tmpfs maximum size of 200MB for /tmp/ (tmpfs doesn’t reserve this memory, it allocates only the memory actually needed):

$ echo "tmpfs /tmp tmpfs rw,nosuid,nodev,size=200M" | sudo tee -a /etc/fstab
$ grep tmp /etc/fstab
tmpfs /tmp tmpfs rw,nosuid,nodev,size=200M

Note: If I had not included ‘,size=200M‘ in /etc/fstab, the maximum size for the tmpfs filesystem mounted on /tmp/ would have defaulted to half the available RAM in the machine.

Then I rebooted to check that /tmp/ is now in RAM:

$ df -h /tmp/
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           200M  4.0K  200M   1% /tmp
$ findmnt /tmp/
TARGET SOURCE FSTYPE OPTIONS
/tmp   tmpfs  tmpfs  rw,nosuid,nodev,relatime,size=204800k

The space used in /tmp/ will vary depending on what is running. For example, editing a large LibreOffice document will require space in /tmp/, so keep an eye on the amount of space used in /tmp/ and adjust the maximum size of the tmpfs partition if necessary.

Installing the Interactive Deep Colorization application in Linux

There are plenty of articles and videos on the Web regarding colourising old black and white photographs. Some of the resulting colourised photographs look amazing. Several Web sites offer free or commercial automated colourisation of B&W photographs using AI (artificial intelligence) techniques. The free-use sites watermark the result or limit the size of the original image. Some of the resulting colourised images are reasonable, others not so good.

Last year I scanned some 35 mm slides which are over 60 years old. The chemicals in some had degraded so much that the images are tinted red (‘redscale’ rather than ‘greyscale’!), too much to be able to fix using the GIMP. Out of curiosity I tried processing one of the scanned slides using some of the free online B&W photograph automated colourisers. The results in some cases were promising, alhough they would still require a lot of manual adjustment.

Scan of original 35 mm slide about 60 years old

Scan of original 35 mm slide about 60 years old

The image after processing using one of the free online B&W colouriser Websites

The image after processing using one of the free online B&W colouriser Websites

A few years ago Richard Zhang and colleagues at the University of California, Berkeley wrote software that uses similar AI techniques to colourise photographs but allows the user to manually influence the colourisation — see the Smithsonian Magazine article New App Makes It Easier to Colorize Old Photos for further information and a link to the GitHub repository of Jun-Yan Zhu with the team’s open-source software, written in Python. Zhang went on to join Adobe, and the software is now incorporated in Adobe PhotoShop Elements.

All my machines run Linux, and I wanted to try to install the open-source application from Jun-Yan Zhu’s GitHub repository. However, the Python code uses Qt4 but all my Linux installations use Qt5. Jun-Yan Zhu created a GitHub branch for the Python code to be modified for Qt5 but, to date, that branch still contains only Python code using Qt4:

https://github.com/junyanz/interactive-deep-colorization/tree/qt5

However, another GitHub user named Vishwaesh Rajiv cloned the code and ported it to Qt5 for use in a Docker container:

https://github.com/vwrj/interactive-deep-colorization

I decided to have a go at getting the application to work in Lubuntu 20.10 on my family’s desktop machine. Below are the results of my efforts, which unfortunately stalled because the machine only has 4 GB of RAM (the application apparently requires a lot of memory).

The installation instructions in the README.md file in both users’ repositories apply to the version using Qt4. Below is what I had to do to install the Qt5 version of the application from Vishwaesh Rajiv’s GitHub repository. Qt5 and PyQt5 are already installed in Lubuntu 20.10, so these are not included in the steps below (read Jun-Yan Zhu’s GitHub page for details). My family’s desktop machine does not have an NVIDIA GPU (it has an Intel IGP) so I used ‘CPU mode’ (see the README.md file for details).

user $ wget https://github.com/vwrj/interactive-deep-colorization/archive/master.zip
user $ unzip master.zip
user $ cp -r -p interactive-deep-colorization-master ideepcolor
user $ cd ideepcolor
user $ cp docker/ideepcolor_docker.py ideepcolor.py
user $ cp -r docker/ui_PyQt5/* ui/
user $ cp -r docker/data/* data/
user $ nano ideepcolor.py # Change the line 'from ui_PyQt5 import gui_design' to 'from ui import gui_design'
user $ bash ./models/fetch_models.sh
user $ sudo apt update
user $ sudo apt install caffe python3-caffe
user $ sudo apt install python3-opencv python3-sklearn python3-skimage
user $ sudo apt install python3-qdarkstyle
user $ sudo apt install python3-opencv

I used the following command in ~/ideepcolor/ to launch the application:

user $ python3 ideepcolor.py --cpu_mode --backend caffe --image_file test_imgs/parrot.jpg

From the output displayed in the terminal window the application seems to launch correctly:

[...]
Setting ab cluster centers in layer: pred_ab
Setting upsampling layer kernel: pred_313_us
b'test_imgs/parrot.jpg'
scale = 2.000000

but after a minute or two the memory used increases significantly (as seen in htop), no GUI is displayed and the terminal displays ‘Killed‘:

[...]
Setting ab cluster centers in layer: pred_ab
Setting upsampling layer kernel: pred_313_us
b'test_imgs/parrot.jpg'
scale = 2.000000
Killed

I could be wrong, but I assume the reason the application does not continue is because of insufficient RAM. When I get time I will try to install the various packages in Gentoo Linux on my main laptop with 16 GB RAM, to see if I can get it to work. If you are using a Linux installation that has Qt5 installed and your machine has plenty of RAM, you might be interested to try and install the Interactive Deep Colorization software to see if you can get it to work. If you do, please comment below.

A farewell to Sabayon Linux

After a hiatus of thirty-four months in the blog posts on the Sabayon Linux Website, a couple of posts on 20 November 2020 announced that the distribution was switching its base distribution from Gentoo Linux to Funtoo Linux (‘Sabayon and Funtoo Linux Merge Projects’), and that the distribution was rebranding (‘Sabayon project is rebranding to MocaccinoOS’) and moving to a completely different package manager named ‘Luet’. A new Website and forums for MocaccinoOS were started, and the Sabayon Linux forums and Wiki are no more.

Although my first experience of Linux was Ubuntu in 2006, it was Sabayon Linux in early 2007 that turned me into a full-time Linux enthusiast and got me interested in the Portage package manager and Gentoo Linux, which I have been using as my main OS for many years now. My interest in Sabayon Linux waned when it moved to a binary package manager (‘Entropy’), and later when it switched from OpenRC to systemd.

Unlike binary distributions, Gentoo Linux enables users to use whichever init system they choose. My Gentoo Linux installations use OpenRC rather than systemd but, occasionally, if a problem interested me, I tried to help Gentoo Linux users who had opted to use systemd. As Sabayon Linux was based on Gentoo Linux with systemd, I would occasionally install Sabayon Linux in virtual machines as a convenient way to investigate issues in Gentoo installations using systemd. Likewise I occasionally tried to help Sabayon Linux users if a problem interested me.

Despite no longer being a full-time user of the distribution, I remained one of the moderators of the Sabayon Linux forums until its demise, albeit not having much time to devote to the role in the last few years. Activity on the Sabayon Linux forums had been quite low for quite some time and I was not surprised to learn that the distribution’s developers had finally called it a day late last year and started a new project. I wish them success with the new distribution.

Moving from Lubuntu 18.04 to 20.10

The Lubuntu developers will no longer be supporting Lubuntu 18.04, the final release of Lubuntu to use LXDE, after April this year. I therefore decided to replace it with Lubuntu 20.10 on the family desktop machine (a single-seat, multi-user installation). Lubuntu 20.10 uses LXQt so it was not feasible to upgrade the existing installation, as explained on the official Lubuntu Website:

Note, due to the extensive changes required for the shift in desktop environments, the Lubuntu team does not support upgrading from 18.04 or below to any greater release. Doing so will result in a broken system. If you are on 18.04 or below and would like to upgrade, please do a fresh install.

Thus I had to install Lubuntu 20.10 from scratch. I downloaded the ISO file (1.8 GB) from the official Lubuntu Website and used the dd command to create a LivePendrive:

user $ sudo blkid # Ascertain which device is the pendrive.
user $ sudo dd bs=4M if=/home/fitzcarraldo/lubuntu-20.10-desktop-amd64.iso of=/dev/sdb conv=fdatasync status=progress

Some of my blog posts during the last three years covered various additions and fixes I made to the Lubuntu 18.04 installation on the family desktop machine. Below I explain how I implemented those, if necessary, in the fresh 20.10 installation.

Due to the automated backup routine I implemented in 2018, a permanently-connected external USB HDD (filesystem label ‘FREECOM HDD’) contained a backup of each users’ home directory from the Lubuntu 18.04 installation:

Lubuntu_home_folders_backup_LXDE/fitzcarraldo/
Lubuntu_home_folders_backup_LXDE/molly/
Lubuntu_home_folders_backup_LXDE/aquilino/
Lubuntu_home_folders_backup_LXDE/cholo/
Lubuntu_home_folders_backup_LXDE/paul/

I installed Lubuntu 20.10, overwriting the Lubuntu 18.04 installation. The resulting 20.10 installation had me as the sole user:

user $ whoami
fitzcarraldo
user $ groups
fitzcarraldo adm cdrom sudo dip plugdev lpadmin sambashare

All the files in my home directory are owned by fitzcarraldo.fitzcarraldo (user.group). I want all users to be members of the group ‘users‘ in addition to a group with their own username, so first I added myself to that group:

user $ sudo usermod -a -G users fitzcarraldo
user $ groups
fitzcarraldo adm cdrom sudo dip plugdev users lpadmin sambashare

Before using the groupadd and useradd commands I double-checked their options, as these can differ between distributions:

user $ groupadd --help
user $ useradd --help

Then I added the other users (N.B. GID and UID are not the same value per username):

user $ sudo groupadd -g 1002 molly 
user $ sudo useradd -m -c "Molly" -g molly -G adm,cdrom,dip,lpadmin,plugdev,sambashare,users -p strawberryfields -s /bin/bash -u 1001 molly
user $ sudo groupadd -g 1003 aquilino
user $ sudo useradd -m -c "Aquilino" -g aquilino -G adm,cdrom,dip,lpadmin,plugdev,sambashare,users -p paperbackwriter -s /bin/bash -u 1002 aquilino
user $ sudo groupadd -g 1004 cholo
user $ sudo useradd -m -c "Cholo" -g cholo -G adm,cdrom,dip,lpadmin,plugdev,sambashare,users -p mysweetlord -s /bin/bash -u 1003 cholo
user $ sudo groupadd -g 1005 paul
user $ sudo useradd -m -c "Paul" -g paul -G adm,cdrom,dip,lpadmin,plugdev,sambashare,users -p sweet16 -s /bin/bash -u 1004 paul

WARNING: Do not add other users to the sudo group, otherwise Muon Package Manager in Lubuntu 20.10 will not allow you to install any more packages (see [Bug 1875346] Re: Muon does not recognize user password).

Lubuntu 18.04 used the LightDM display manager, whereas Lubuntu 20.10 uses the less-sophisticated SDDM display manager. To display the avatar of each user on the SDDM login page I copied a portrait photograph of each user to the relevant SDDM directory:

user $ sudo cp /home/fitzcarraldo/Pictures/Portraits/fitzcarraldo.png /usr/share/sddm/faces/fitzcarraldo.face.icon
user $ sudo cp /home/fitzcarraldo/Pictures/Portraits/molly.png /usr/share/sddm/faces/molly.face.icon
user $ sudo cp /home/fitzcarraldo/Pictures/Portraits/aquilino.png /usr/share/sddm/faces/aquilino.face.icon
user $ sudo cp /home/fitzcarraldo/Pictures/Portraits/cholo.png /usr/share/sddm/faces/cholo.face.icon
user $ sudo cp /home/fitzcarraldo/Pictures/Portraits/paul.png /usr/share/sddm/faces/paul.face.icon

I also configured a different wallpaper for each user’s Desktop:

user $ sudo mkdir /home/molly/Pictures/Wallpaper
user $ sudo chown molly.molly /home/molly/Pictures/Wallpaper/
user $ sudo mkdir /home/aquilino/Pictures/Wallpaper
user $ sudo chown aquilino.aquilino /home/aquilino/Pictures/Wallpaper/
user $ sudo mkdir /home/cholo/Pictures/Wallpaper
user $ sudo chown cholo.cholo /home/cholo/Pictures/Wallpaper/
user $ sudo mkdir /home/paul/Pictures/Wallpaper
user $ sudo chown paul.paul /home/paul/Pictures/Wallpaper/
user $ cd Pictures/Wallpaper/
user $ sudo cp wallpaper2.jpg /home/molly/Pictures/Wallpaper/
user $ sudo chown molly.molly /home/molly/Pictures/Wallpaper/wallpaper2.jpg 
user $ sudo cp wallpaper3.jpg /home/aquilino/Pictures/Wallpaper/
user $ sudo chown aquilino.aquilino /home/aquilino/Pictures/Wallpaper/wallpaper3.jpg 
user $ sudo cp wallpaper4.jpg /home/cholo/Pictures/Wallpaper/
user $ sudo chown cholo.cholo /home/cholo/Pictures/Wallpaper/wallpaper4.jpg
user $ sudo cp wallpaper5.jpg /home/paul/Pictures/Wallpaper/
user $ sudo chown paul.paul /home/paul/Pictures/Wallpaper/wallpaper5.jpg

Note that, unlike Lubuntu 18.04, Lubuntu 20.10 does not have a ‘Switch User’ option, so it is not possible for users to switch between sessions without logging out. I actually prefer it this way, as other family members would usually switch user rather than logging out in Lubuntu 18.04, leaving open sessions.

Lubuntu 20.10 still does not automatically unmount the external HDD when a user logs out, thus making it impossible for the next user who logs in to access the external HDD (see Prevent Lubuntu 17.10 from leaving an external HDD mounted incorrectly for other users). The fix in this version of Lubuntu differs from the fix in 18.04; I added the following two lines to the end of /usr/share/sddm/scripts/Xsetup:

# Fix to make sure each user can access the external HDD
udisksctl unmount --block-device '/dev/disk/by-label/FREECOM\x20HDD'

Virus scan

I set up my automated system to scan files downloaded to the ~/Downloads directory as explained below.

user $ sudo apt install clamtk
user $ sudo apt install clamav
user $ sudo apt install clamav-daemon
user $ sudo apt install clamdscan
user $ sudo apt install inotify-tools
user $ sudo apt install kdialog # In Ubuntu this would be zenity instead.

I copied the script ~/.monitorDownloadsGUI listed below into each user’s home directory, and made the ownership <username>.<username> and the script executable:

#!/bin/bash

DIR=$HOME/Downloads

# Get rid of old log file, if any
rm $HOME/virus-scan.log 2> /dev/null

IFS=$(echo -en "\n\b")

# Optionally, you can use shopt to avoid creating two processes due to the pipe
shopt -s lastpipe
inotifywait --quiet --monitor --event close_write,moved_to --recursive --format '%w%f' $DIR | while read FILE
# Added '--recursive' so that a directory copied into $DIR also triggers clamscan/clamdscan, although downloads
# from the Web would just be files, not directories.
do
     sleep 1s
     # Have to check file length is nonzero otherwise commands may be repeated
     if [ -s $FILE ]; then
          # Replace 'date >' with 'date >>' if you want to keep log file entries for previous scans.
          date > $HOME/virus-scan.log
          clamdscan --move=$HOME/virus-quarantine $FILE >> $HOME/virus-scan.log
#         Use zenity in GNOME; kdialog in KDE and LXQt:
#          zenity --info --title="Virus scan of $FILE" --text="$(cat $HOME/virus-scan.log)"
          kdialog --title "Virus scan of $FILE" --msgbox "$(cat $HOME/virus-scan.log)"
     fi
done

I configured each user’s account to execute ~/.monitorDownloadsGUI at login. To do this in LXQt, in each user’s account I selected ‘Preferences’ > ‘LXQt settings’ > ‘Session Settings’ > ‘Autostart’.

Other useful packages

I installed the Elementary Icon Theme, as I saw some error messages about it not being installed:

user $ sudo apt install elementary-icon-theme

I installed a utility I find useful for searching for the location of a file, and ran the command to update its database of file names (you can run it at any time, or add it to e.g. crontab):

user $ sudo apt install mlocate
user $ sudo updatedb

I use Buku bookmark manager and Thunderbird e-mail client, so I installed those too:

user $ sudo apt install buku
user $ sudo apt install thunderbird
user $ sudo apt install thunderbird-locale-en

I added Buku to my crontab (the location of the binary has changed to /usr/bin/buku since I wrote my above-mentioned blog post on Buku in 2018):

1,21,41 * * * * rm /home/fitzcarraldo/ownCloud/Bookmarks/*.txt; sleep 30s && /usr/bin/buku -p --nc > /home/fitzcarraldo/ownCloud/Bookmarks/Buku_bookmarks_backup.txt

I prefer Signal to WhatsApp so I installed Signal Desktop by following the instructions at https://signal.org/download/#

Some of my family prefer the Google Chrome browser to Firefox, so I installed that:

user $ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
user $ sudo apt install ./google-chrome-stable_current_amd64.deb

I right-clicked on the Desktop and selected ‘Create Launcher’ to create the file ~/Desktop/Google_Chrome_Web_browser.desktop for each user (I edited it to change the icon, and ticked ‘Trust this executable’ if not ticked):

[Desktop Entry]
Name=Google Chrome Web browser
GenericName=Web browser
Comment=Google Chrome Web browser
Exec=google-chrome
Type=Application
Icon=google-chrome
Terminal=false

I right-clicked on the Desktop and selected ‘Create Launcher’ to create the file ~/Desktop/Firefox_Web_browser.desktop for each user (I edited it to change the icon, and ticked ‘Trust this executable’ if not ticked):

[Desktop Entry]
Name=Firefox Web browser
GenericName=Web browser
Comment=Firefox Web browser
Exec=firefox
Type=Application
Icon=firefox
Terminal=false

I right-clicked on the Desktop and selected ‘Create Launcher’ to create the file ~/Desktop/Signal.desktop (I edited it to change the icon, and ticked ‘Trust this executable’ if not ticked):

[Desktop Entry]
Name=Signal
GenericName=Signal messenger
Comment=Signal messenger
Exec=signal-desktop
Type=Application
Icon=signal-desktop
Terminal=false

All the family use Skype, so I downloaded the .deb file from https://www.skype.com/en/get-skype/download-skype-for-desktop/ and double-clicked on it to install it.

I right-clicked on the Desktop and selected ‘Create Launcher’ to create the file ~/Desktop/Skype_for_Linux.desktop (I edited it to change the icon, and ticked ‘Trust this executable’ if not ticked):

[Desktop Entry]
Name=Skype for Linux
GenericName=Skype messaging
Comment=Skype for Linux
Exec=skypeforlinux
Type=Application
Icon=skypeforlinux
Terminal=false

I also dragged some of the icons from the Desktop to the Panel in order to create quick-launch items on the Panel, useful when frequently used items on the Desktop are obscured by open windows.

I installed and configured the utility Neofetch that can be used to display system information in a terminal window:

user $ sudo apt install xterm
user $ sudo apt install neofetch

I right-clicked on the Desktop and selected ‘Create Launcher’ to create the file ~/Desktop/Neofetch.desktop (I edited it to change the icon, and ticked ‘Trust this executable’ if not ticked):

[Desktop Entry]
Name=Neofetch
GenericName=A command-line system information tool written in Bash
Comment=A command-line system information tool written in Bash
Exec=xterm -e /bin/bash -c "neofetch; exec /bin/bash"
Type=Application
Icon=/home/fitzcarraldo/Pictures/Icons/neofetch.png
Terminal=false

Firewall

UFW (Uncomplicated Fire Wall) was already installed in Lubuntu 20.10 but not enabled, so I enabled it:

user $ sudo enable ufw
user $ sudo ufw status verbose

I edited /etc/modules-load.d/modules.conf to add two firewall-related modules needed to enable Samba commands and wsdd (see further on) to function correctly:

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
iptable_raw
xt_pkttype

Bluetooth
The desktop machine has a USB Bluetooth adapter so I installed Blueman as it had not been installed by the Lubuntu 20.10 Installer:

user $ sudo apt install blueman
user $ sudo apt install --reinstall bluez

See also my blog post The phone name assigned automatically by Android on my new phone prevented Bluetooth pairing and connecting in Linux.

Samba

All the machines in my home network use broadcast NetBIOS name resolution and SMB (v2 and v3, not v1) for file sharing, so I installed the packages shown below and copied the smb.conf from the previous installation, and edited the UFW configuration file as explained in an earlier blog post.

user $ sudo apt install samba
user $ sudo apt install cifs-utils
user $ sudo apt install nbtscan
user $ sudo apt install smbclient
user $ sudo cp /media/fitzcarraldo/FREECOM\ HDD/Lubuntu_home_folders_backup_LXDE/fitzcarraldo/Samba/smb.conf /etc/samba/smb.conf

See the following blog posts for details:

As my home network includes a NAS, I also configured the user accounts to be able to mount the NAS shared folder for Windows applications running under WINE (see How to enable a Windows application in WINE to access a Samba share on a NAS (continued)):

~/Desktop/Mount_server1_user1_share.desktop

[Desktop Entry]
Name=Mount_server1_user1_share
GenericName=Mount server1 user1 share
Comment=Mount server1 user1 share
Exec=/home/fitzcarraldo/.mount_server1_user1_share.sh
Type=Application
Icon=/home/fitzcarraldo/Pictures/Icons/nuvola/128x128/devices/samba_mount.png
Terminal=true

~/.mount_server1_user1_share.sh

#!/bin/bash
mount_share () {
    echo
    echo "Enter your Linux account password below..."
    echo
    sudo ln -s /media/server1/user1 ~/$PREFIX/dosdevices/y:
    sudo mount.cifs //server1/user1/ -o user=user1,pass=<password of user1>,uid=$(id -u),gid=$(id -g) ~/$PREFIX/dosdevices/y:
}
echo
echo "This will mount the Samba share folder user1 on the server1 machine."
echo
echo
echo "== Select which WINEPREFIX you wish to use =="
echo
ls ~/.wine-* | grep .wine | awk -F'/' '{print NR " " substr($4, 1, length($4)-1)}'
NUMPREFIXES=$(ls ~/.wine-* | grep .wine | wc -l)
echo
read -p "Enter number (q to abort) and press ENTER: " CHOICE
if [ "$CHOICE" != "q" ] && [ "$CHOICE" -gt 0 ] && [ "$CHOICE" -le $NUMPREFIXES ]; then
    PREFIX=$(ls ~/.wine-* | grep .wine | awk -F'/' '{print NR " " substr($4, 1, length($4)-1)}' | grep "$CHOICE " | awk -F' ' '{print $2}')
    echo
    if [ ! -e ~/$PREFIX/dosdevices/y: ]; then
        mount_share
    else
        echo -n "~/$PREFIX/dosdevices/y: already exists. Is it OK to proceed anyway (y/n)? "
        read ANSWER
        if [ $ANSWER = "y" ]; then
            rm ~/$PREFIX/dosdevices/y:
            mount_share
        fi
    fi
    echo
fi
if grep -q "/media/server1/user1" /proc/mounts; then
    echo "Samba share //server1/user1 is mounted for WINEPREFIX ~/$PREFIX ."
else
    echo "Samba share //server1/user1 is not mounted."
fi
echo
echo "You may now close this window."
read ANSWER
exit

~/Desktop/Unmount_server1_user1_share.desktop

[Desktop Entry]
Name=Unmount_server1_user1_share
GenericName=Unmount server1 user1 share
Comment=Unmount server1 user1 share
Exec=/home/fitzcarraldo/.umount_server1_user1_share.sh
Type=Application
Icon=/home/fitzcarraldo/Pictures/Icons/nuvola/128x128/devices/samba_unmount.png
Terminal=true

~/.umount_server1_user1_share.sh

#!/bin/bash
echo
echo "This will unmount the Samba share folder user1 on the server1 machine."
echo
echo "Enter your Linux account password below..."
echo
sudo umount ~/.wine-*/dosdevices/y: 2>/dev/null
echo
if grep -q "/media/server1/user1" /proc/mounts; then
  echo "Samba share //server1/user1 is mounted."
else
  echo "Samba share //server1/user1 is not mounted."
fi
echo
echo "You may now close this window."
exit

WS-Discovery

As WS-Discovery is required to be able to browse SMB shares in File Explorer in Windows 10 installations these days, I also installed the WS-Discovery daemon. See an earlier blog post for details, including how to configure UFW: Using WS-Discovery to enable Windows 10 to browse SMB shares in my home network of Linux computers

user $ wget https://github.com/christgau/wsdd/archive/master.zip
user $ unzip master.zip
user $ sudo cp wsdd-master/src/wsdd.py /usr/bin/wsdd
user $ sudo cp wsdd-master/etc/systemd/wsdd.service /etc/systemd/system/

I added ‘--workgroup HOME‘ (the workgroup of all the machines in my home network) to /etc/systemd/system/wsdd.service and changed the group to ‘nogroup‘:

[Unit]
Description=Web Services Dynamic Discovery host daemon
; Start after the network has been configured
After=network-online.target
Wants=network-online.target
; It makes sense to have Samba running when wsdd starts, but is not required
;Wants=smb.service

[Service]
Type=simple
ExecStart=/usr/bin/wsdd --shortlog --workgroup HOME
; Replace those with an unprivledged user/group that matches your environment,
; like nobody/nogroup or daemon:daemon or a dedicated user for wsdd
User=nobody
Group=nogroup
; The following lines can be used for a chroot execution of wsdd.
; Also append '--chroot /run/wsdd/chroot' to ExecStart to enable chrooting
;AmbientCapabilities=CAP_SYS_CHROOT
;ExecStartPre=/usr/bin/install -d -o nobody -g nogroup -m 0700 /run/wsdd/chroot
;ExecStopPost=rmdir /run/wsdd/chroot

[Install]
WantedBy=multi-user.target

user $ sudo systemctl enable wsdd
user $ sudo systemctl start wsdd

I also installed a script to list WS-Discovery devices on my home network (see A Linux command-line utility to discover and list WSD-enabled computers and printers on a home network). I first copied the directory /media/fitzcarraldo/FREECOM HDD/Lubuntu_home_folders_backup_LXDE/fitzcarraldo/discover from the backup HDD to my new home directory, then I set up ~/discover/wsd-discover.sh:

user $ sudo apt install curl # curl is needed in wsd-discover.sh

As one of the awk commands in ~/discover/wsd-discover.sh would not work in Lubuntu 20.10 I changed the line:

cat /tmp/wsd-probe6.txt | awk -F "******" '{print $1 $3}' > /tmp/wsd-probe7.txt

to:

cat /tmp/wsd-probe6.txt | awk -F "\*\*\*\*\*\*" '{print $1 $3}' > /tmp/wsd-probe7.txt

The Desktop Configuration File (a.k.a. ‘Launcher’ in LXQt) ~/Desktop/Discover_WSD_devices.desktop contains the following:

[Desktop Entry]
Name=Discover_WSD_devices
GenericName=Discover WSD devices
Comment=Discover WSD devices
Exec=/home/fitzcarraldo/discover/wsd-discover.sh
Type=Application
Icon=/home/fitzcarraldo/Pictures/Icons/Crystal_Clear/png/actions/find.png
Terminal=true

I right-clicked on the Desktop and used ‘Create Launcher’ to create the above file. I edited it to change the icon, and ticked ‘Trust this executable’ if not ticked.

WINE

I installed WINE:

user $ sudo apt install wine

Then I copied across all my WINE prefix directories from the backup HDD and reconfigured them. For example, for MyPhoneExplorer:

user $ cd
user $ cp -r /media/fitzcarraldo/FREECOM\ HDD/Lubuntu_home_folders_backup_LXDE/fitzcarraldo/.wine-myphoneexplorer .
user $ export WINEPREFIX=~/.wine-myphoneexplorer
user $ winecfg
user $ cd ~/.wine-myphoneexplorer/drive_c/
user $ wine MyPhoneExplorer_Setup_v1.8.15.exe

Installing the Windows application creates a Desktop Configuration File on the Desktop. For example, the file ~/Desktop/MyPhoneExplorer.desktop contains:

[Desktop Entry]
Name=MyPhoneExplorer
Exec=env WINEPREFIX="/home/fitzcarraldo/.wine-myphoneexplorer" wine-stable C:\\\\windows\\\\command\\\\start.exe /Unix /home/fitzcarraldo/.wine-myphoneexplorer/dosdevices/c:/users/Public/Desktop/MyPhoneExplorer.lnk
Type=Application
StartupNotify=true
Path=/home/fitzcarraldo/.wine-myphoneexplorer/dosdevices/c:/users/Public/Start Menu/Programs/MyPhoneExplorer
Icon=5A9F_MyPhoneExplorer.0
StartupWMClass=myphoneexplorer.exe

user $ chmod 664 ~/Desktop/MyPhoneExplorer.desktop
user $ ls -la ~/Desktop/MyPhoneExplorer.desktop
-rw-rw-r-- 1 fitzcarraldo fitzcarraldo 436 Jan  2 02:54 /home/fitzcarraldo/Desktop/MyPhoneExplorer.desktop

ownCloud

As I use ownCloud on a server, I installed the ownCloud client (instructions are available on the ownCloud Web site):

user $ wget -nv https://download.owncloud.com/desktop/ownCloud/stable/latest/linux/Ubuntu_20.10/Release.key -O - | sudo apt-key add -
user $ echo 'deb https://download.owncloud.com/desktop/ownCloud/stable/latest/linux/Ubuntu_20.10/ /' | sudo tee -a /etc/apt/sources.list.d/owncloud.list
user $ sudo apt update
user $ sudo apt install owncloud-client

In order to be able to browse my ownCloud folder using WebDAV I installed davfs2:

user $ sudo apt install davfs2
user $ mkdir /home/fitzcarraldo/webdav

I added the following line in ~/.davfs2/secrets:

https://bsfitzgerald.ddns.net/owncloud/remote.php/webdav bsf <password for my account on my server>

I uncommented the following two lines in /etc/davfs2/davfs2.conf:

dav_user        davfs2            # system wide config file only
dav_group       davfs2            # system wide config file only

I added the following line to /etc/fstab:

https://bsfitzgerald.ddns.net/owncloud/remote.php/webdav /home/fitzcarraldo/webdav davfs noauto,user,rw 0 0

See also the following articles regarding configuring Ubuntu for WebDAV browsing:

I created the following Desktop Configuration Files to enable me to mount and unmount the WebDAV-shared folder by double-clicking on Desktop icons:

~/Desktop/Mount_server1_WebDAV_share.desktop

[Desktop Entry]
Name=Mount_server1_WebDAV_share
GenericName=Mount server1 WebDAV share
Comment=Mount server1 WebDAV share
Exec=mount /home/fitzcarraldo/webdav
Type=Application
Icon=/home/fitzcarraldo/Pictures/Icons/Crystal_Clear/png/devices/nfs_mount.png
Terminal=true

~/Desktop/Unmount_server1_WebDAV_share.desktop

[Desktop Entry]
Name=Unmount_server1_WebDAV_share
GenericName=Unmount server1 WebDAV share
Comment=Unmount server1 WebDAV share
Exec=fusermount -u /home/fitzcarraldo/webdav
Type=Application
Icon=/home/fitzcarraldo/Pictures/Icons/Crystal_Clear/png/devices/nfs_unmount.png
Terminal=true

Prevent suspending to RAM

I configured each user’s LXQt Power Management settings so none of the users’ accounts would suspend to RAM automatically. I may change this in future so I installed a script to enable me to prevent the installation suspending if desired (see How to move a mouse pointer automatically in Linux to simulate user activity):

user $ sudo apt install xdotool # My script to keep the mouse pointer moving automatically (when I run it) uses this.

I right-clicked on the Desktop and selected ‘Create Launcher’ to create the file ~/Desktop/Keep_mouse_moving.desktop below (and edited it to change the icon, and ticked ‘Trust this executable’):

[Desktop Entry]
Name=Keep_mouse_moving
GenericName=Keep mouse moving automatically
Comment=Keep mouse moving automatically
Exec=xterm -iconic -e "bash -c /home/fitzcarraldo/.keep_mouse_moving.sh"
Type=Application
Icon=input-mouse
Terminal=false

I created the script ~/.keep_mouse_moving.sh containing the following, which I can launch by double-clicking on the desktop icon when I wish:

#!/bin/bash
#
# Script to keep mouse pointer moving so that, for example, Suspend to RAM timeout does not occur.
# 
# The mouse pointer will move around its current position on the screen, i.e. around any position
# on the screen where you place the pointer. However, if you prefer it to move around the centre
# of the screen then change mousemove_relative to mousemove in the xdotool command below.
#
# Set LENGTH to 0 if you do not want the mouse pointer to move.
# Set LENGTH to 1 if you want the mouse pointer to move just a tiny fraction.
# Set LENGTH to e.g. 100 if you want to see more easily the mouse pointer move.
LENGTH=1
#
# Set DELAY to the desired number of seconds between each move of the mouse pointer.
DELAY=5
#
while true
do
#    if [[ `cat /proc/asound/card*/pcm*/sub*/status | grep RUNNING | wc -l` -ne 0 ]]; then
        for ANGLE in 0 90 180 270
        do
            xdotool mousemove_relative --polar $ANGLE $LENGTH
            sleep $DELAY
        done
#    fi
done

Automated backup of users’ home directories

I set up the same backup method that I implemented in the earlier Lubuntu installations (see Backing up users’ home directories in a Linux installation that uses systemd):

/etc/systemd/system/backup-to-usb-hdd.service

[Unit]
Description=Backup home directories of all users to USB HDD
DefaultDependencies=no
Before=shutdown.target halt.target
RequiresMountsFor=/home

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup_home_directories.sh

[Install]
WantedBy=halt.target shutdown.target

/usr/local/sbin/backup_home_directories.sh

#!/bin/bash

# This script backs up to an external USB HDD (NTFS) labelled "FREECOM HDD" the contents of the home directories
# of the users of this Lubuntu 20.10 installation if the system is shutting down but not rebooting.
# It is launched by a systemd service /etc/systemd/system/backup-to-usb-hdd.service.

# Find out if the system is rebooting (as opposed to being shut down):
REBOOT=$( systemctl list-jobs | egrep -q 'reboot.target.*start' && echo "rebooting" || echo "not_rebooting" )
if [ $REBOOT = "not_rebooting" ]; then
# Only execute the following steps if the system is shutting down but not rebooting:
   # Clean up if the backup did not complete last time:
    umount /media/usbhdd 2>/dev/null # Make sure you enter this line correctly.
    rm -rf /media/usbhdd/* # Make sure you enter this line correctly.
    # Unmount the external USB HDD if mounted by udisks2 with the logged-in username in the path:
    umount /media/*/FREECOM\ HDD 2>/dev/null
    # Find out the USB HDD device:
    DEVICE=$( blkid | grep "FREECOM\ HDD" | cut -d ":" -f1 )
    # Create a suitable mount point if it does not already exist, and mount the device on it:
    mkdir /media/usbhdd 2>/dev/null
    mount -t ntfs-3g -o async,noexec,nodev,noatime,nodiratime $DEVICE /media/usbhdd 2>/dev/null
    # Create the backup directory on the USB HDD if it does not already exist:
    mkdir /media/usbhdd/Lubuntu_home_folders_backup 2>/dev/null
    # Backup recursively all the home directories of all the users, and add a time-stamped summary to the log file:
    echo "********** Backing up Acer Aspire XC600 users' home directories **********" >> /home/fitzcarraldo/backup.log
    date >> /home/fitzcarraldo/backup.log
    # Log username of user shutting down the PC (may not be this user if Switch User was used):
    echo -ne "User who shutdown PC (may not be this user if Switch User has been used): " >> /home/fitzcarraldo/backup.log
    last | cut -d " " -f1 | head -1 >> /home/fitzcarraldo/backup.log
    sleep 2s
    # cp --recursive --update --preserve=all --no-dereference --force /home/ /media/usbhdd/Lubuntu_home_folders_backup 2>> /home/fitzcarraldo/backup.log
    rsync --ignore-errors --recursive --times --perms --links --protect-args --exclude '/*/.cache/mozilla' --exclude '/*/.cache/google-chrome' --exclude '/*/.cache/chromium' --delete-excluded --bwlimit=22500 /home/ /media/usbhdd/Lubuntu_home_folders_backup 2>> /home/fitzcarraldo/backup.log
    echo "Copying completed" >> /home/fitzcarraldo/backup.log
    date >> /home/fitzcarraldo/backup.log
    echo "********** Backup completed **********" >> /home/fitzcarraldo/backup.log
    cp /home/fitzcarraldo/backup.log /media/usbhdd/Lubuntu_home_folders_backup/fitzcarraldo/
    # Unmount the USB HDD so that udisks2 can subsequently re-mount it with the user's username in the path:
    umount /media/usbhdd
fi
exit 0

user $ sudo systemctl enable backup-to-usb-hdd
user $ sudo systemctl start backup-to-usb-hdd

Keyboard layouts

As I want to be able to switch between English, Brazilian Portuguese and Spanish keyboard layouts, I did the following:

I added the following lines to the file /usr/share/sddm/scripts/Xsetup:

#Make sure the keyboards I use are selectable on the SDDM greeter screen
setxkbmap gb,us,br,es
#

I edited the file /etc/X11/xorg.conf.d/00-keyboard.conf so that it contains the following:

# Read and parsed by systemd-localed. It's probably wise not to edit this file
# manually too freely.
Section "InputClass"
        Identifier "system-keyboard"
        MatchIsKeyboard "on"
        Option "XkbLayout" "gb,us,br,es"
        Option "XkbModel" "pc105"
        Option "XkbOptions" "grp:alt_shift_toggle"
EndSection

I right-clicked on the Panel for each user, selected ‘Manage Widgets’ and added the ‘Keyboard state indicator’ to the Panel.

Conclusion

The resulting Lubuntu 20.10 installation is working fine so far. It has a more contemporary look than the LXDE Desktop in Lubuntu 18.04. My family is already using it and, so far, there have been no adverse comments or problems.

The phone name assigned automatically by Android on my new phone prevented Bluetooth pairing and connecting in Linux

I recently installed Lubuntu 20.10 on a desktop machine, but Bluetooth did not work with my new phone (Samsung Galaxy Note 20 Ultra with Android 11). Bluetooth had worked fine in Lubuntu 18.04 on the same desktop machine with my previous Android phone (Samsung Galaxy Note 8 with Android 9).

The first thing I discovered was that, although the Lubuntu 20.10 Installer had installed Bluez, it had not installed a Bluetooth manager, so I installed Blueman:

$ sudo apt install blueman

Then, I re-installed Bluez just to be sure:

$ sudo apt install --reinstall bluez

The Bluetooth device was detected but Lubuntu 20.10 would not pair with my new phone.

The Bluetooth device was definitely unblocked:

$ rfkill --output-all
ID TYPE      DEVICE TYPE-DESC         SOFT      HARD
 1 wlan      phy0   Wireless LAN unblocked unblocked
 2 bluetooth hci0   Bluetooth    unblocked unblocked

Now, the phone name Android 11 had assigned automatically to my new phone was Fitzcarraldo’s Galaxy Note20 Ultra 5G. After trying many things, I began to wonder if the apostrophe in the phone name was causing the problem, so I changed the name in the phone (Settings > About phone > Edit) to Fitzcarraldo Galaxy Note20 Ultra 5G. Blueman/Bluez were then able to pair with, and connect to, the phone. Problem solved, but what a silly cause.

Deleted e-mails in an Office 365 Outlook account keep reappearing in the Thunderbird e-mail client

Whatever OS and e-mail client you use, if you search the Web you’ll find plenty of posts about deleted e-mails that reappear after you empty the ‘Trash’/’Deleted Items’/’Recycle bin’ folder. This problem seems to occur mostly with e-mail accounts that use the IMAP (Internet Message Access Protocol) or the Microsoft EWS (Exchange Web Services) protocols.

The obvious thing to check first in the e-mail client is if it has been configured to actually delete the e-mails on the server when you empty the ‘Deleted Items’ folder. Furthermore, internal files called ‘folder index files’ (.msf) in Thunderbird can sometimes become damaged, and these damaged files can also result in deleted e-mails reappearing. There is a ‘Repair Folder’ option in Thunderbird that sometimes fixes this problem. If that does not work, deleting the relevant folder’s .msf file and allowing Thunderbird to rebuild it sometimes fixes the problem. Anyway, I tried all the suggested approaches and more, as well as completely removing the account in Thunderbird (including ticking ‘Remove message data’ and manually deleting any remaining files for that account that remained in the Thunderbird directory). But nothing worked. However, I eventually cracked the problem as explained below.

Let’s just recap my situation:

  1. Of the many e-mails in a corporate Office 365 account that I had deleted over the last few months and emptied from the account’s ‘Deleted Items’ folder, five of them would keep reappearing in that account’s ‘Deleted Items’ folder in Thunderbird. This happened if I deleted the e-mails individually from the ‘Deleted Items’ folder and if I right-clicked on the folder and selected ‘Empty Deleted’.
  2. Whenever I logged in to the Office 365 Outlook account via a Web browser, the ‘Deleted Items’ folder was empty and it showed ‘Recover items deleted from this folder (0 items)’, i.e. no deleted messages existed.
  3. The Samsung e-mail client on my Samsung Galaxy Note 8 mobile phone showed the ‘Recycle bin’ for the same account was empty.

All the settings for the account in Thunderbird were correct. Completely removing the account from Thunderbird then adding the account again did not solve the problem, meaning that the problem could not be due to Thunderbird or the ExQuilla add-on Thunderbird uses to enable it to access the Office 365 Outlook account using Microsoft EWS. Even though my Samsung mobile phone’s e-mail client showed the Office 365 Outlook account’s ‘Recycle bin’ was empty, I selected ‘Email settings’ in the Samsung e-mail client, selected the account, scrolled down to ‘Empty Recycle bin’ and tapped it. The following message was displayed:

Empty Recycle bin?

This will permanently delete the items in the Recycle bin.

Cancel            Delete

I tapped ‘Delete’ and the Samsung e-mail client displayed ‘Success’. The five rogue e-mails then disappeared from the ‘Deleted Items’ folder in Thunderbird. The next time I logged in to the Office 365 Outlook account via a Web browser, the ‘Deleted Items’ folder was still empty but it displayed ‘Recover items deleted from this folder (5 items)’. I used the usual Office 365 Outlook procedure to recover the five e-mails and delete them permanently, resulting in ‘Recover items deleted from this folder (0 items)’ being displayed again in Office 365 Outlook in the browser window.

So, there you have it, the problem had nothing to do with Thunderbird or ExQuilla. If you access an Office 365 Outlook e-mail account via an e-mail client on a desktop or laptop and also via an e-mail client on a mobile phone, and you find that e-mails you deleted and emptied from the ‘Deleted Items’/’Trash’/’Recycle bin’ folder in the e-mail client on the desktop/laptop keep reappearing in that folder, try deleting them on all your devices, including your phone, even if the e-mails are not shown in the Office 365 Outlook account in a Web browser nor in the Office 365 Outlook account in a phone’s e-mail client.

Work-around in Linux to switch between single-sided and double-sided printing

I use Gentoo Linux on my laptop, and have drivers installed for quite a few printer manufacturers and models, as I work in multiple offices and they have a wide range of printers and MFPs. To date I have had no trouble printing single-sided (‘simplex’) and double-sided (‘duplex’) documents on the printers that support duplex printing. However, one of the offices I have been working in recently has a Konica Minolta bizhub C368, a floor-standing MFP, and the printer in this MFP did not enable me to switch between single-sided and double-sided printing even though Windows users in the same office could. This article explains how I managed to switch between the two printing modes.

A Linux driver for the bizhub C368 can be downloaded from the Konica Minolta Download Centre. I downloaded the tarball KMbeuUXv1_22_multi_language.tar.gz, extracted the contents to the directory ~/KMbeuUXv1_22_multi_language/ and followed the instructions in ‘BEU Linux CUPS Driver Guide.pdf‘:

user $ cd ~/KMbeuUXv1_22_multi_language
user $ su
root # ./install.pl
root # rc-service cupsd restart

I then used the CUPS Administration page in a browser window to set up the printer.

As I wanted the printer to be the default printer while I was working in that office, I edited the system-wide and user-specific lpoptions files to contain the printer name I had specified to CUPS when setting up the printer:

user $ cat ~/.cups/lpoptions
Default Konica_Minolta_bizhub_C368
root # cat /etc/cups/lpoptions
Default Konica_Minolta_bizhub_C368

I was then able to print from all the usual applications, except that the applications could only select single-sided printing, even though the printer supports double-sided printing and Windows users in the office could print double-sided. I could not find a setting for this in the CUPS Manager’s ‘Set Default Options’ page for the printer, so I edited the PPD file to change the relevant default option:

root # nano /etc/cups/ppd/Konica_Minolta_bizhub_C368.ppd

I changed the default printing option from:

*DefaultKMDuplex: 1Sided

to:

*DefaultKMDuplex: 2Sided

Then I could print double-sided pages, but selecting ‘single-sided’ in applications would still print double-sided. Now, I don’t know if there is a proper fix for this, but I could not find out how to do it. Therefore I opted for a work-around which is fine for my purposes. Here is what I did…

I created the shell script ~/Konica_Minolta_bizhub_C368.sh containing the following:

#!/bin/bash
echo
echo "Konica Minolta bizhub C368 printer"
echo
echo "Select single-sided or double-sided printing as the default"
echo
# Get the password entry over and done with now
echo "Enter your user account password."
sudo ls > /dev/null
echo
CHOICE=""
while [[ $CHOICE != "X" && $CHOICE != "x" ]]; do
    if [[ $CHOICE != "X" && $CHOICE != "x" ]]; then
        echo
        echo -n "[1]-sided, [2]-sided or e[X]it : "
        read -n1 CHOICE
        echo
    else
        break
    fi
    case $CHOICE in
        [1] ) sudo cp /home/fitzcarraldo/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.single-sided /etc/cups/ppd/Konica_Minolta_bizhub_C368.ppd
              echo "Single-sided printing has been selected"
        ;;
        [2] ) sudo cp /home/fitzcarraldo/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.double-sided /etc/cups/ppd/Konica_Minolta_bizhub_C368.ppd
              echo "Double-sided printing has been selected"
        ;;
        [Xx] ) echo; exit;;
        * ) echo; echo " Enter '1', '2' or 'X/x'"
    esac
done

I created the Desktop Configuration File ~/Desktop/Konica_Minolta_bizhub_C368.desktop containing the following:

[Desktop Entry]
Comment[en_GB]=Select single-sided or double-sided printing for Konica Minolta bizhub C368
Comment=Select single-sided or double-sided printing for Konica Minolta bizhub C368
Encoding=UTF-8
Exec=konsole -e sh /home/fitzcarraldo/Konica_Minolta_bizhub_C368.sh
GenericName[en_GB]=Select printing sides for KM bizhub C368
GenericName=Select printing sides for KM bizhub C368
Icon=/home/fitzcarraldo/Pictures/Icons/konica-minolta.png
MimeType=
Name[en_GB]=Konica_Minolta_bizhub_C368
Name=Konica_Minolta_bizhub_C368
Path=
StartupNotify=true
Terminal=true
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-DCOP-ServiceType=
X-KDE-SubstituteUID=false
X-KDE-Username=

I downloaded a Konica Minolta logo from the Web and used it for the icon for the Desktop Configuration File.

And finally I copied the PPD file to two files and edited them:

~/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.single-sided

which includes *DefaultKMDuplex: 1Sided

~/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.double-sided

which includes *DefaultKMDuplex: 2Sided

Now, if I want to switch between single-sided and double-sided printing I just double-click on the icon on my Desktop and a terminal window pops-up allowing me to select the new default:

Konica Minolta bizhub C368 printer

Select single-sided or double-sided printing as the default

Enter your user account password.
Password:

[1]-sided, [2]-sided or e[X]it :

Why does Thunderbird add ‘\A0’ and other strange-looking strings in e-mails I send?

I use Linux and have used the Thunderbird e-mail client since 2008. I used to use DavMail to enable Thunderbird to access various company Microsoft Exchange WebMail accounts but, several years ago, DavMail would no longer work with a particular Microsoft Exchange account so I switched to the Thunderbird add-on ExQuilla, for which I pay an annual licence fee. I do not know if the more recent versions of DavMail would work with this particular account but ExQuilla got me out of a hole so I stuck with it. Recently this particular corporation decided to stop using an in-house Microsoft Exchange server and switched to Microsoft 365.

Recently people receiving my e-mails sent using this particular account told me there were strange strings of characters in e-mails of mine that quote other e-mails. The most frequent occurrence is the three-character string ‘\A0’, although other strings are sometimes present too. The following e-mail extract illustrates the effect:

Hi Claudia,

I have had a look at your draft and agree with your assessment. Let’s sit down together and prepare a list of possible remedial measures.

Regards,
Fitzcarraldo

On 07/10/2020 13:02, Claudia wrote:
> Hi,
> \A0
> Could you please have a look at the draft I have attached.
> \A0
> There are several main issues requiring attention. The operation was basically run by one person \2013 (John) during the tests, which led to several issues.
> \A0
> He does not have the time to do everything by himself.\A0 The other staff who had assisted him during earlier tests were not present.

Notice various occurrences of ‘\A0’ and an occurrence of ‘\2013’.

I searched the Web to see if other Thunderbird users had come across this problem, and found several reports of similar problems, although not identical. The most promising page I found was in the Mozilla support forums for Thunderbird: Why do my sent messages magically add “�” at the end of my sentences?. However, none of the various fixes suggested in that thread worked in my case. My Thunderbird installation was configured to use ‘Unicode (UTF-8)’ text encoding for Outgoing Mail and Western (ISO-8859-1) for Incoming Mail ( ‘Edit’ > ‘Preferences’ > ‘General’ > ‘Language & Appearance’ > ‘Advanced…’ > ‘Text Encoding’). I changed the text encoding for incoming mail to ‘Unicode (UTF-8)’ but that made no difference. I ticked ‘When possible, use the default text encoding in replies’ but that also made no difference. Anyway, I left the settings like that and hoped an update to Thunderbird would fix the issue.

I was not sure if the problem started with an upgrade to Thunderbird, or whether the switch to Microsoft 365 was the cause. I suspect Microsoft 365 is the culprit because the problem does not occur when I use other e-mail accounts. Anyway, it is annoying and I have still not found a fix for it. One of the replies in the above-mentioned Thunderbird support thread is not identical to what I’m seeing, but it looks to be essentially the same problem:

Jorg K
2/4/18, 6:17 AM

There is NO bug in Thunderbird. Sadly some US ISP’s like AT&T and Bellsouth have started *corrupting* their customers’ e-mail.

If the customer sends in windows-1252 and includes for example special punctuation characters or a non-break space xA0, the ISP doesn’t correctly interpret the the message as windows-1252 but as UTF-8. In UTF-8, xA0 is not valid and gets replaced by the so-called replacement character, � (0xEF 0xBF 0xBD).

Since the e-mail is still windows-1252 encoded, the recipient’s client displays �.

See:
https://bugzilla.mozilla.org/show_bug.cgi?id=1427636
https://bugzilla.mozilla.org/show_bug.cgi?id=1435536

Affected users should complain heavily to their mail providers. As a workaround, they need to send all messages as UTF-8.

This seems to be a possible explanation of what I am experiencing, but it is impractical for me to check what text encoding all my contacts are using, or get them to switch to UTF-8 if they are not already using it in their e-mails. I noticed that there is actually a space in what look like blank lines in the e-mails I quote, and, if I delete that space, the ‘\A0’ no longer appears on those lines when I view the contents of e-mails in the Sent Items mailbox. I think that the space is, in fact, a non-breaking space (xA0), which is apparently invalid in UTF-8 and gets displayed as ‘\A0’ by Thunderbird (I’m currently using Version 78.4.2).

Trying to find and delete all the non-breaking spaces and other non-UTF-8 characters in a quoted e-mail is impractical. However, I found a somewhat cumbersome work-around to the problem of non-breaking spaces (and, I think, other non UTF-8 characters). When I click on the ‘Reply’ button in Thunderbird and a window pops up for me to compose my reply which includes a quoted e-mail or e-mails, I use Ctrl-C to copy all the contents of the window, then Ctrl-V to paste it back into the window. This seems to get rid of the character strings representing non-UTF-8 characters. It does add some extra blank lines in the quoted e-mail(s) in the window in which I am composing my e-mail, but those extra blank lines are normally not present when viewing the e-mail after it has been sent.

This work-around is not ideal as it relies on me remembering to do it when composing an e-mail in which I am quoting a previous e-mail or e-mails. But at least it gets rid of the multiple additional occurrences of ‘\A0’ (non-breaking space). It’s a pity there is no mechanism in Thunderbird to filter out non-UTF-8 characters such as a non-breaking space when quoting other e-mails. Even if Jorg K in the above-mentioned thread is correct and the cause of the problem does not lie in Thunderbird, I would rather Thunderbird act differently if the user has configured it to send e-mails using UTF-8 text encoding, and filter out non-UTF-8 characters rather than including strings of gobbledygook in the e-mail.

Migrating to libglvnd in Gentoo Linux on a laptop with NVIDIA Optimus

In a 2015 post I described how I configured my Gentoo Linux installation to switch between the closed-source NVIDIA driver and the open-source Intel driver on a Clevo W230SS laptop that has NVIDIA Optimus hardware (NVIDIA GeForce GTX 860M GPU plus Intel HD 4600 IGP). I did not want to use Bumblebee, preferring to use only the NVIDIA driver or only the Intel driver, switching between them by running a Bash script then logging out of KDE Plasma and back in again. Basically, the scheme a) swapped the xorg.conf file depending on which driver I wanted to use, and b) used the eselect opengl command to select the applicable OpenGL library. The latest versions of the files in my scheme are listed below if you’re interested (I use LightDM instead of KDM these days, as KDM is no more), otherwise just skip to the section after, titled ‘Migrating to libglvnd’.

Previous scheme using eselect opengl

~/Desktop/Select_NVIDIA_GPU.desktop

[Desktop Entry]
Comment[en_GB]=Run a script to configure your installation to use the NVIDIA GeForce GTX 860M GPU when you restart X Windows
Comment=Run a script to configure your installation to use the NVIDIA GeForce GTX 860M GPU when you restart X Windows
Exec=konsole -e sh /home/fitzcarraldo/nvidia.sh
GenericName[en_GB]=Configure your installation to use the NVIDIA GeForce GTX 860M GPU
GenericName=Configure your installation to use the NVIDIA GeForce GTX 860M GPU
Icon=/home/fitzcarraldo/Pictures/Icons/nvidia_icon.png
MimeType=
Name[en_GB]=NVIDIA GPU
Name=NVIDIA GPU
Path=
StartupNotify=true
Terminal=false
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

~/nvidia.sh

#!/bin/bash
echo
echo "Your installation is currently configured to use the following graphics processor:"
echo
GPU=`eselect opengl list | grep \* | awk '{ print $2 }'`
if [ "$GPU" = "nvidia" ]; then
  echo "NVIDIA GeForce GTX 860M"
  echo
  echo "You do not need to do anything. Please close this window."
elif [ "$GPU" = "xorg-x11" ]; then
  echo "Intel HD 4600 Integrated Graphics Processor"
  echo
  echo "This script will configure your installation to use the NVIDIA GeForce GTX 860M GPU all the time."
  echo
  echo "Enter your own password."
  echo
  sudo eselect opengl set nvidia
# See separate configuration of LightDM for NVIDIA GPU and Intel HD Graphics.
  sudo cp /etc/X11/xorg.conf.nvidia /etc/X11/xorg.conf
  echo
  echo "Now you should logout to restart X Windows."
fi
echo
echo -n "Press ENTER to end: "
read ACKNOWLEDGE

/etc/X11/xorg.conf.nvidia

Section "ServerLayout"
    Identifier     "Layout0"
    Screen      1  "nvidia" 0 0
    Inactive       "intel"
EndSection

Section "Monitor"
    Identifier     "Monitor0"
    Option         "DPMS"
    Option         "DPI" "96 x 96"
EndSection

Section "Device"
    Identifier     "nvidia"
    Driver         "nvidia"
    BusID          "PCI:1:0:0"
EndSection

Section "Device"
    Identifier     "intel"
    Driver         "modesetting"
    BusID          "PCI:0:2:0"
EndSection

Section "Screen"
    Identifier     "nvidia"
    Device         "nvidia"
    Monitor        "Monitor0"
    DefaultDepth    24
    Option         "UseDisplayDevice" "none"
    SubSection     "Display"
        Depth       24
        Virtual     1920 1080
    EndSubSection
EndSection

Section "Screen"
    Identifier     "intel"
    Device         "intel"
    Monitor        "Monitor0"
EndSection

~/Desktop/Select_Intel_HD_Graphics.desktop

[Desktop Entry]
Comment[en_GB]=Run a script to configure your installation to use Intel Integrated Graphics when you restart X Windows
Comment=Run a script to configure your installation to use Intel Integrated Graphics when you restart X Windows
Exec=konsole -e sh /home/fitzcarraldo/intel.sh
GenericName[en_GB]=Configure your installation to use Intel HD Graphics
GenericName=Configure your installation to use Intel HD Graphics
Icon=/home/fitzcarraldo/Pictures/Icons/intel-hd-icon.png
MimeType=
Name[en_GB]=Intel HD Graphics
Name=Intel HD Graphics
Path=
StartupNotify=true
Terminal=false
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

~/intel.sh

#!/bin/bash
echo
echo "Your installation is currently configured to use the following graphics processor:"
echo
GPU=`eselect opengl list | grep \* | awk '{ print $2 }'`
if [ "$GPU" = "xorg-x11" ]; then
  echo "Intel HD 4600 Integrated Graphics Processor"
  echo
  echo "You do not need to do anything. Please close this window."
elif [ "$GPU" = "nvidia" ]; then
  echo "NVIDIA GeForce GTX 860M"
  echo
  echo "This script will configure your installation to use the"
  echo "Intel HD 4600 Integrated Graphics Controller all the time."
  echo
  echo "Enter your own password."
  echo
  sudo eselect opengl set xorg-x11
# See separate configuration of LightDM for Intel HD Graphics and NVIDIA GPU.
  sudo cp /etc/X11/xorg.conf.intel /etc/X11/xorg.conf
  echo
  echo "Now you should logout to restart X Windows."
fi
echo
echo -n "Press ENTER to end: "
read ACKNOWLEDGE

/etc/X11/xorg.conf.intel

Section "Device" 
   Identifier  "Intel Graphics" 
   Driver      "intel" 
   Option      "AccelMethod" "sna" 
   Option      "TearFree" "true" 
EndSection

/etc/X11/xorg.conf.d/20-opengl.conf

Section "Files"
        ModulePath "/usr/lib/xorg/modules"
        ModulePath "/usr/lib64/xorg/modules"
EndSection

/etc/X11/Sessions/plasma (used by LightDM)

#!/bin/bash
#
# Make sure the following is in /etc/lightdm/lightdm.conf
# display-setup-script=/etc/X11/Sessions/plasma
#
GPU=`eselect opengl list | grep \* | awk '{ print $2 }'`
if [ "$GPU" = "nvidia" ]; then
    xrandr --setprovideroutputsource modesetting NVIDIA-0
    xrandr --auto
fi

Migrating to libglvnd

Well, the above scheme worked fine… until the recent decision by the Gentoo Linux developers to drop the app-eselect/eselect-opengl ebuild and switch the x11-base/xorg-server, media-libs/mesa and x11-drivers/nvidia-drivers to using the libglvnd library:

This package is masked and could be removed soon!
The mask comment indicates that this package is scheduled for removal from our package repository.
Please review the mask information below for more details.

Replaced by media-libs/libglvnd. Masked for removal in 30 days. Bug #728286

Affected packages	app-eselect/eselect-opengl

Author/Date		Matt Turner  (2020-08-11 00:00:00 +0000 UTC)

Without the eselect opengl command, my scripts were scuppered. So I decided to bite the bullet and switch to using libglvnd. It turned out not to be difficult, and I took the following steps to migrate:

  1. Deleted the file /etc/X11/xorg.conf
  2. Created the file /etc/X11/xorg.conf.d/01-nvidia-offload.conf containing the following:
    Section "ServerLayout"
        Identifier "layout"
        Option "AllowNVIDIAGPUScreens"
    EndSection
    
  3. Performed the usual ‘emerge -uvDN @world‘ to update and upgrade the relevant packages, which automatically unmerged app-eselect/eselect-opengl

If I had run into trouble with the installed app-eselect/eselect-opengl blocking the upgrade, I could have worked around that by doing the following:

root # emerge -C eselect-opengl
root # emerge -1v nvidia-drivers mesa xorg-server xorg-drivers

I removed all references to the libglvnd USE flag from /etc/portage/make.conf, and the only place libglvnd is declared explicitly now is in the file /etc/portage/package.use/world because I have a multilib installation:

root # grep libglvnd /etc/portage/package.*/*
/etc/portage/package.use/world:>=media-libs/libglvnd-1.3.1 abi_x86_32

The status of the applicable packages in my installation is now as follows:

root # eix -I nvidia-drivers
[I] x11-drivers/nvidia-drivers
     Available versions:  [M]340.108-r1(0/340)^mtd ~390.132-r4(0/390)^mtd 390.138-r1(0/390)^mtd 435.21-r6(0/435)^mtd 440.100-r2(0/440)^mtd 450.57-r1(0/450)^mtd {+X compat (+)driver gtk3 +kms +libglvnd multilib static-libs +tools uvm wayland ABI_MIPS="n32 n64 o32" ABI_RISCV="lp64 lp64d" ABI_S390="32 64" ABI_X86="32 64 x32" KERNEL="FreeBSD linux"}
     Installed versions:  450.57-r1(0/450)^mtd(22:04:56 14/08/20)(X driver kms libglvnd multilib tools wayland -compat -gtk3 -static-libs -uvm ABI_MIPS="-n32 -n64 -o32" ABI_RISCV="-lp64 -lp64d" ABI_S390="-32 -64" ABI_X86="32 64 -x32" KERNEL="linux -FreeBSD")
     Homepage:            https://www.nvidia.com/Download/Find.aspx
     Description:         NVIDIA Accelerated Graphics Driver

root # eix -I mesa
[I] media-libs/mesa
     Available versions:  20.0.8^t ~20.1.4^t ~20.1.5^t ~20.2.0_rc1^t ~20.2.0_rc2^t **9999*l^t {+X +classic d3d9 debug +dri3 +egl +gallium +gbm gles1 +gles2 +libglvnd +llvm lm-sensors opencl osmesa selinux test unwind vaapi valgrind vdpau vulkan vulkan-overlay wayland xa xvmc zink +zstd ABI_MIPS="n32 n64 o32" ABI_RISCV="lp64 lp64d" ABI_S390="32 64" ABI_X86="32 64 x32" KERNEL="linux" VIDEO_CARDS="freedreno i915 i965 intel iris lima nouveau panfrost r100 r200 r300 r600 radeon radeonsi v3d vc4 virgl vivante vmware"}
     Installed versions:  20.0.8^t(22:03:42 14/08/20)(X classic dri3 egl gallium gbm gles2 libglvnd llvm wayland zstd -d3d9 -debug -gles1 -lm-sensors -opencl -osmesa -selinux -test -unwind -vaapi -valgrind -vdpau -vulkan -vulkan-overlay -xa -xvmc ABI_MIPS="-n32 -n64 -o32" ABI_RISCV="-lp64 -lp64d" ABI_S390="-32 -64" ABI_X86="32 64 -x32" KERNEL="linux" VIDEO_CARDS="i965 intel -freedreno -i915 -iris -lima -nouveau -panfrost -r100 -r200 -r300 -r600 -radeon -radeonsi -vc4 -virgl -vivante -vmware")
     Homepage:            https://www.mesa3d.org/ https://mesa.freedesktop.org/
     Description:         OpenGL-like graphic library for Linux

[I] x11-apps/mesa-progs
     Available versions:  8.4.0 **9999*l {egl gles2}
     Installed versions:  8.4.0(13:53:51 02/05/19)(-egl -gles2)
     Homepage:            https://www.mesa3d.org/ https://mesa.freedesktop.org/ https://gitlab.freedesktop.org/mesa/demos
     Description:         Mesa's OpenGL utility and demo programs (glxgears and glxinfo)

Found 2 matches
root # eix -I xorg-server
[I] x11-base/xorg-server
     Available versions:  1.20.8-r1(0/1.20.8) **9999(0/9999)*l {debug dmx doc +elogind ipv6 kdrive +libglvnd libressl minimal selinux static-libs suid systemd +udev unwind wayland xcsecurity xephyr xnest xorg xvfb}
     Installed versions:  1.20.8-r1(0/1.20.8)(22:07:21 14/08/20)(elogind ipv6 libglvnd udev wayland xorg -debug -dmx -doc -kdrive -libressl -minimal -selinux -static-libs -suid -systemd -unwind -xcsecurity -xephyr -xnest -xvfb)
     Homepage:            https://www.x.org/wiki/ https://gitlab.freedesktop.org/xorg/xserver/xorg-server
     Description:         X.Org X servers

root # eix -I xorg-drivers
[I] x11-base/xorg-drivers
     Available versions:  1.20-r2 **9999*l {INPUT_DEVICES="elographics evdev joystick libinput synaptics vmmouse void wacom" VIDEO_CARDS="amdgpu ast dummy fbdev freedreno geode glint i915 i965 intel mga nouveau nv nvidia omap qxl r128 radeon radeonsi siliconmotion tegra vc4 vesa via virtualbox vmware"}
     Installed versions:  1.20-r2(22:05:41 14/08/20)(INPUT_DEVICES="evdev synaptics -elographics -joystick -libinput -vmmouse -void -wacom" VIDEO_CARDS="i965 intel nvidia -amdgpu -ast -dummy -fbdev -freedreno -geode -glint -i915 -mga -nouveau -nv -omap -qxl -r128 -radeon -radeonsi -siliconmotion -tegra -vc4 -vesa -via -virtualbox -vmware")
     Homepage:            https://wiki.gentoo.org/wiki/No_homepage
     Description:         Meta package containing deps on all xorg drivers

I can now delete the line display-setup-script=/etc/X11/Sessions/plasma in /etc/lightdm/lightdm.conf, and delete the script /etc/X11/Sessions/plasma, as the script no longer works and the xrandr commands in it are no longer necessary in any case. The files and scripts Select_NVIDIA_GPU.desktop, nvidia.sh, xorg.conf.nvidia, Select_Intel_HD_Graphics.desktop, intel.sh and xorg.conf.intel are also redundant now and can be deleted.

After rebooting, the LightDM login screen appears as usual and I can login to the Desktop Environment. I can connect an external monitor to the laptop via either VGA cable or HDMI cable and both methods work, and I can switch between the laptop monitor and the external monitor using KDE Plasma’s ‘System Settings’ > ‘Display Configuration’, so everything appears to be working correctly.

The command xrandr --listproviders (add ‘--verbose‘ to provide more information) lists both the NVIDIA and Intel video devices, so I assume everything is working correctly:

user $ xrandr --listproviders
Providers: number : 2
Provider 0: id: 0x47 cap: 0xb, Source Output, Sink Output, Sink Offload crtcs: 4 outputs: 4 associated providers: 0 name:Intel
Provider 1: id: 0x203 cap: 0x0 crtcs: 0 outputs: 0 associated providers: 0 name:NVIDIA-G0

It appears that the default is to use the Intel IGP:

user $ glxinfo | grep -E 'OpenGL (vendor|renderer)'
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 4600 (HSW GT2)
user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=Intel __GLX_VENDOR_LIBRARY_NAME=mesa glxinfo  | grep -E 'OpenGL (vendor|renderer)'
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 4600 (HSW GT2)

unless I use environment variables explicitly to specify that the NVIDIA GPU be used for a specific application:

user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 __GLX_VENDOR_LIBRARY_NAME=nvidia glxinfo  | grep -E 'OpenGL (vendor|renderer)'
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GTX 860M/PCIe/SSE2

Performance seems reasonable:

user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 __GLX_VENDOR_LIBRARY_NAME=nvidia __GL_SYNC_TO_VBLANK=0 glxgears
27197 frames in 5.0 seconds = 5439.292 FPS
27332 frames in 5.0 seconds = 5466.274 FPS
27857 frames in 5.0 seconds = 5571.184 FPS
27553 frames in 5.0 seconds = 5510.447 FPS
27128 frames in 5.0 seconds = 5425.556 FPS
^C

To run a program such as LibreCAD using the NVIDIA GPU I can do the following:

user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 __GLX_VENDOR_LIBRARY_NAME=nvidia librecad

I need to play around more to understand how to use nvidia-drivers and libglvnd with the NVIDIA Optimus hardware in this laptop, but at least I have managed to migrate from app-eselect/eselect-opengl to media-libs/libglvnd before the former is dropped from the Portage tree in the near future.