Category Archives: Linux

DDC/CI monitor control on Linux

DDC/CI is a set of protocols for controlling monitor features like brightness, contrast, color temperature, input source, … over the display cable (VGA, DVI, HDMI, Display port, …).

The protocol is fairly old (1998) and nowadays most devices support it.

I’m currently using it to:

  • Adjust the brightness of my two monitors depending on my room lighting.
  • Switch the input source of my monitors for different devices (my laptop, a tower PC and a virtual machine with dedicated GPU). The big advantage here is that you don’t need to buy an expensive KVM switch to support 4K displays / high refresh rates.

How

Required packages

You must install the ddcutil package for your Linux distribution. The official website contains extensive information for troubleshooting.

Kernel modules

Ddcutil connects to your screen over an I2C connection, and requires the i2c-dev kernel module to be loaded.

You can load the module at runtime using sudo modprobe i2c-dev.

To make it persistent across reboots, you need to add the module to /etc/modules-load.d/i2c-dev.conf:

i2c-dev

Once the module is loaded, some files should appear in /dev/i2c-*.

Allow the user to use DDC

By default the i2c dev files are owned by root, preventing other users to control them. One solution to allow your user to control DDC without using sudo is to add a custom udev rule:

/etc/udev/rules.d/99-ddcutil-i2c.rules

KERNEL=="i2c-[0-9]*", GROUP="your-user", MODE="0660", PROGRAM="/usr/bin/ddcutil --bus=%n getvcp 0x10"
Udev

This rule automatically detects which i2c devices are DDC-capable, and allows members of the group “your-user” to control the file.

You can reload udev rules without rebooting by executing sudo udevadm trigger

If you have multiple users, you can create a new group and add your user to the group:

groupadd ddc
usermod -aG ddc $USER
Bash

Note: ddcutil --bus=%n getvcp 0x10 is used to get the current brightness of the monitor. This only work with the assumption that all monitors supporting DDC/CI control can be queried for their brightness, which is likely to be true for the immense majority of them.

Identify your monitor info

How to address your monitor

The following command queries general information on your connected displays:

ddcutil detect
# You should see entries like:
# Display 1
#    I2C bus:             /dev/i2c-0
#    EDID synopsis:
#       Mfg id:           DEL
#       Model:            DELL U2419H
#       Serial number:    833L1N6
#       Manufacture year: 2018
#       EDID version:     1.4
#    VCP version:         2.1
Bash

There are multiple methods to address your monitor:

  • By display number using --display
  • By model name using --model
  • By serial number using --sn
  • By i2c bus ID using --bus

The bus ID method is way faster than the others, but may be unreliable if your hardware changes often.

Which features can be controlled

The following command queries which display features can be get/set for a given monitor:

ddcutil capabilities --bus=0
# You should see something like:
# MCCS version: 2.1
# Commands:
#    Command: 01 (VCP Request)
#    Command: 02 (VCP Response)
#    Command: 03 (VCP Set)
#    Command: 07 (Timing Request)
#    Command: 0c (Save Settings)
#    Command: e3 (Capabilities Reply)
#    Command: f3 (Capabilities Request)
# VCP Features:
#    Feature: 10 (Luminosity)
#    Feature: 12 (Contrast)
#    Feature: 14 (Select color preset)
#       Values:
#          04: 5000 K
#          05: 6500 K
#          06: 7500 K
#          08: 9300 K
#          09: 10000 K
#          0b: User 1
#          0c: User 2
#    Feature: 16 (Video gain: Red)
#    Feature: 18 (Video gain: Green)
#    Feature: 1A (Video gain: Blue)
#    Feature: 60 (Input Source)
#       Values:
#          0f: DisplayPort-1
#          11: HDMI-1
#    Feature: AA (Screen Orientation)
#       Values:
#          01: 0 degrees
#          02: 90 degrees
#          03: 180 degrees
#          04: 270 degrees
Bash

You can get/set those features using:

  • Get: ddcutil --bus=0 getvcp $FEAT_ID
  • Set: ddcutil --bus=0 setvcp $FEAT_ID $VALUE

Script examples

Change brightness

ddc-setbrightness

#!/bin/bash
# Usage: ddc-setbrightness 50
ddcutil --bus=0 setvcp 10 "$1" &
ddcutil --bus=1 setvcp 10 "$1" &
wait
Bash

Since DDC commands can be slow to execute (especially without --bus addressing), it is best to run them in parallel and wait for completion.

Switch input sources

Very useful when you need to change input sources very often, and don’t have a dedicated button on the monitor (or for automating it).

ddc-switch-inputs

#!/bin/bash
# Usage: ddc-switch-inputs 1
case "$1" in
   1 )
      # Config 1: Main PC
      OUT=("0x0f" "0x20")
      ;;
   2 )
      # Config 2: Virtual machine
      OUT=("0x11" "0x21")
      ;;
   * )
      echo "Unknown input '$1'"
      exit 1
      ;;
esac

ddcutil --bus=0 setvcp 60 ${OUT[0]} &
ddcutil --bus=1 setvcp 60 ${OUT[1]} &
wait
Bash

Reduce eyestrain

ddc-daylight

#!/bin/bash
# Usage: ddc-daylight night
case "$1" in
   "day" )
      BRIGHTNESS=100
      TEMPERATURE=0x09
      ;;
   "evening" | "morning" )
      BRIGHTNESS=60
      TEMPERATURE=0x06
      ;;
   "night" )
      BRIGHTNESS=30
      TEMPERATURE=0x04
      ;;
   "dark" )
      BRIGHTNESS=0
      TEMPERATURE=0x04
      ;;
   * )
      echo "Unknown time of day '$1'"
      exit 1
      ;;
esac

ddcutil --bus=0 setvcp 10 $BRIGHTNESS &
ddcutil --bus=1 setvcp 10 $BRIGHTNESS &
ddcutil --bus=0 setvcp 14 $TEMPERATURE &
ddcutil --bus=1 setvcp 14 $TEMPERATURE &
wait
Bash

Updates:
2022-01-13: Replaced i2c-[0-9]+ with i2c-[0-9]* since udev doesn’t support the + extension. Thanks Hendrik W. !

Source: DDC/CI monitor control on Linux

Ubuntu/Linux Mint – Brother QL-800 Label Printer

First thing first, leave the USB off. When you first plug in the power, if the “Editor Lite” light is on, then hold the button until it turns off. Editor Lite causes it to mount as a mass storage device and not as a printer.

Next up, download the drivers from Brother’s website: https://support.brother.com/g/b/producttop.aspx?c=ca&lang=en&prod=lpql800eus or via my local mirror (ql800pdrv-3.1.5-0.i386.deb).

Install the usual way:

sudo dpkg -i ql800pdrv-3.1.5-0.i386.deb

This will add the drivers and add a new printer. If you get any /var/spool/lpd errors, try making the right directory ahead of time and re-install the deb file.

sudo mkdir -p /var/spool/lpd/ql800

Plug in that USB. Check in Printers or via the CUPS interface (http://localhost:631/printers/). The device URI should look something like usb://Brother/QL-800?serial=000W0H924252.

If you run into problems (check via dmesg or jounalctl -f), it could be a udev rule that you’re missing. Try adding a new udev rule, changing the Serial number (find that out via “dmesg | grep Serial” when first plugging the USB in).

sudo vi /etc/udev/rules.d/10-brother-printer.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="04f9", ATTRS{idProduct}=="209e", ATTRS{serial}=="000W0H924252", MODE="0664", GROUP="lp", SYMLINK+="usb/lp0"

Then restart udev and cups:

sudo udevadm control -R
sudo service cups restart

If you’re installing some other Brother, the vendor code should be good but you’ll need to replace the Product ID (209e) with your own. You can find this out by running “lsusb” (check the bold for the product ID).

Bus 003 Device 019: ID 04f9:209b Brother Industries, Ltd QL-800 P-touch Label Printer

Bonus! Using brother_ql – the Python package to control your Brother printer from the command line

Download and install from the website https://pypi.org/project/brother-ql/.

This should add it to the path (if not, the binaries should be in ~/.local/bin/brother_ql)

This next part you’ll need to figure out. I am using DK-1201 labels which are 29mmx90mm. I created a sample.png file which was exactly 306×991 pixels for testing. So my command line looks like this:

brother_ql --backend pyusb --model QL-800 --printer 'usb://0x04f9:0x209b/000W0H924252' print -l 29x90 sample.png

Note the change in the USB string — replace those with your product ID (if not QL-800) and serial number.

Source: Ubuntu/Linux Mint – Brother QL-800 Label Printer | 10pm.ca – Tidbits for the wandering Googler

How to Control (start/stop/mask/unmask) Services Using Systemd

How to Control (start/stop/mask/unmask) Services Using Systemd

Starting and Stopping Services

Services need to be stopped or started manually for a number of reasons: perhaps the service needs to be updated; the configuration file may need to be changed; or a service may need to be uninstalled, or an administrator may manually start an infrequently used service.

To start a service, first verify that it is not running with systemctl status. Then, use the systemctl start command as the root user (using sudo if necessary). The example below shows how to start the sshd.service service:

[root@host ~]# systemctl start sshd.service

The systemd service looks for .service files for service management in commands in the absence of the service type with the service name. Thus the above command can be executed as:

[root@host ~]# systemctl start sshd

To stop a currently running service, use the stop argument with the systemctl command. The example below shows how to stop the sshd.service service:

[root@host ~]# systemctl stop sshd.service

Restarting and Reloading Services

During a restart of a running service, the service is stopped and then started. On the restart of service, the process ID changes and a new process ID gets associated during the startup. To restart a running service, use the restart argument with the systemctl command. The example below shows how to restart the sshd.service service:

[root@host ~]# systemctl restart sshd.service

Some services have the ability to reload their configuration files without requiring a restart. This process is called a service reload. Reloading a service does not change the process ID associated with various service processes. To reload a running service, use the reload argument with the systemctl command. The example below shows how to reload the sshd.service service after configuration changes:

[root@host ~]# systemctl reload sshd.service

In case you are not sure whether the service has the functionality to reload the configuration file changes, use the reload-or-restart argument with the systemctl command. The command reloads the configuration changes if the reloading functionality is available. Otherwise the command restarts the service to implements the new configuration changes:

[root@host ~]# systemctl reload-or-restart sshd.service

Listing Unit Dependencies

Some services require that other services be running first, creating dependencies on the other services. Other services are not started at boot time but rather only on demand. In both cases, systemd and systemctl start services as needed whether to resolve the dependency or to start an infrequently used service. For example, if the CUPS print service is not running and a file is placed into the print spool directory, then the system will start CUPS-related daemons or commands to satisfy the print request.

[root@host ~]# systemctl stop cups.service
Warning: Stopping cups, but it can still be activated by:
   cups.path
   cups.socket

To completely stop printing services on a system, stop all three units. Disabling the service disables the dependencies. The ‘systemctl list-dependencies UNIT’ command displays a hierarchy mapping of dependencies to start the service unit. To list reverse dependencies (units that depend on the specified unit), use the –reverse option with the command.

[root@host ~]# systemctl list-dependencies sshd.service
sshd.service
● ├─system.slice
● ├─sshd-keygen.target
● │ ├─sshd-keygen@ecdsa.service
● │ ├─sshd-keygen@ed25519.service
● │ └─sshd-keygen@rsa.service
● └─sysinit.target
...output omitted...

Masking and Unmasking Services

At times, a system may have different services installed that are conflicting with each other. For example, there are multiple methods to manage mail servers (postfix and sendmail, for example). Masking a service prevents an administrator from accidentally starting a service that conflicts with others. Masking creates a link in the configuration directories to the /dev/null file which prevents the service from starting.

[root@host ~]# systemctl mask sendmail.service
Created symlink /etc/systemd/system/sendmail.service → /dev/null.
[root@host ~]# systemctl list-unit-files --type=service
UNIT FILE                                   STATE
sendmail.service                            masked
...output omitted...

Attempting to start a masked service unit fails with the following output:

[root@host ~]# systemctl start sendmail.service
Failed to start sendmail.service: Unit sendmail.service is masked

Use the systemctl unmask command to unmask the service unit.

[root@host ~]# systemctl unmask sendmail
Removed /etc/systemd/system/sendmail.service.

Enabling Services to Start or Stop at Boot

Starting a service on a running system does not guarantee that the service automatically starts when the system reboots. Similarly, stopping a service on a running system does not keep it from starting again when the system reboots. Creating links in the systemd configuration directories enables the service to start at boot. The systemctl commands create and remove these links.

To start a service at boot, use the systemctl enable command.

[root@root ~]# systemctl enable sshd.service
Created symlink /etc/systemd/system/multi-user.target.wants/sshd.service → /usr/ lib/systemd/system/sshd.service.

The above command creates a symbolic link from the service unit file, usually in the /usr/lib/systemd/system directory, to the location on disk where systemd looks for files, which is in the /etc/systemd/system/TARGETNAME.target.wants directory. Enabling a service does not start the service in the current session. To start the service and enable it to start automatically during boot, execute both the systemctl start and systemctl enable commands.

To disable the service from starting automatically, use the following command, which removes the symbolic link created while enabling a service. Note that disabling a service does not stop the service.

[root@host ~]# systemctl disable sshd.service
Removed /etc/systemd/system/multi-user.target.wants/sshd.service.

To verify whether the service is enabled or disable, use the systemctl is-enabled command.

Summary of systemctl Commands

Services can be started and stopped on a running system and enabled or disabled for an automatic start at boot time.

Useful Service Management Commands:

TASK COMMAND
View detailed information about a unit state. systemctl status UNIT
Stop a service on a running system. systemctl stop UNIT
Start a service on a running system. systemctl start UNIT
Restart a service on a running system. systemctl restart UNIT
Reload the configuration file of a running service. systemctl reload UNIT
Completely disable a service from being started, both manually and at boot. systemctl mask UNIT
Make a masked service available. systemctl unmask UNIT
Configure a service to start at boot time. systemctl enable UNIT
Disable a service from starting at boot time. systemctl disable UNIT
List units required and wanted by the specified unit. systemctl list-dependencies UNIT

Source: How to Control (start/stop/mask/unmask) Services Using Systemd

kubuntu – KDE – Dolphin: Open folder in new window instead of new tab

How to open folders (e.g. by click from desktop) in a new window instead of a new tab?

You can go under File Associations and set your favorite application for folder, when choosing Dolphin, you can go in Application properties and add the command line parameter --new-window before the %u

On Kubuntu 22, Open start menu, find Dolphin, right click and choose “Edit Application”. Then on the Application tab

 

Source: kubuntu – KDE – Dolphin: Open folder in new window instead of new tab – Ask Ubuntu

How to Install and Configure Fail2ban on Ubuntu 20.04

Fail2ban Configuration

The default Fail2ban installation comes with two configuration files, /etc/fail2ban/jail.conf and /etc/fail2ban/jail.d/defaults-debian.conf. It is not recommended to modify these files as they may be overwritten when the package is updated.

Fail2ban reads the configuration files in the following order. Each .local file overrides the settings from the .conf file:

  • /etc/fail2ban/jail.conf
  • /etc/fail2ban/jail.d/*.conf
  • /etc/fail2ban/jail.local
  • /etc/fail2ban/jail.d/*.local

For most users, the easiest way to configure Fail2ban is to copy the jail.conf to jail.local and modify the .local file. More advanced users can build a .local configuration file from scratch. The .local file doesn’t have to include all settings from the corresponding .conf file, only those you want to override.

Create a .local configuration file from the default jail.conf file:

sudo cp /etc/fail2ban/jail.{conf,local}

To start configuring the Fail2ban server open, the jail.local file with your text editor :

sudo nano /etc/fail2ban/jail.local

The file includes comments describing what each configuration option does. In this example, we’ll change the basic settings.

Whitelist IP Addresses

IP addresses, IP ranges, or hosts that you want to exclude from banning can be added to the ignoreip directive. Here you should add your local PC IP address and all other machines that you want to whitelist.

Uncomment the line starting with ignoreip and add your IP addresses separated by space:

/etc/fail2ban/jail.local
ignoreip = 127.0.0.1/8 ::1 123.123.123.123 192.168.1.0/24

Ban Settings

The values of bantimefindtime, and maxretry options define the ban time and ban conditions.

bantime is the duration for which the IP is banned. When no suffix is specified, it defaults to seconds. By default, the bantime value is set to 10 minutes. Generally, most users will want to set a longer ban time. Change the value to your liking:

/etc/fail2ban/jail.local
bantime  = 1d

To permanently ban the IP use a negative number.

findtime is the duration between the number of failures before a ban is set. For example, if Fail2ban is set to ban an IP after five failures (maxretry, see below), those failures must occur within the findtime duration.

 

/etc/fail2ban/jail.local
findtime  = 10m

maxretry is the number of failures before an IP is banned. The default value is set to five, which should be fine for most users.

/etc/fail2ban/jail.local
maxretry = 5

Email Notifications

Fail2ban can send email alerts when an IP has been banned. To receive emails, you need to have an SMTP installed on your server and change the default action, which only bans the IP to %(action_mw)s, as shown below:

/etc/fail2ban/jail.local
action = %(action_mw)s

%(action_mw)s bans the offending IP and sends an email with a whois report. If you want to include the relevant logs in the email, set the action to %(action_mwl)s.

You can also adjust the sending and receiving email addresses:

/etc/fail2ban/jail.local
destemail = admin@linuxize.com

sender = root@linuxize.com

Fail2ban Jails

Fail2ban uses a concept of jails. A jail describes a service and includes filters and actions. Log entries matching the search pattern are counted, and when a predefined condition is met, the corresponding actions are executed.

Fail2ban ships with a number of jail for different services. You can also create your own jail configurations.

By default, only the ssh jail is enabled. To enable a jail, you need to add enabled = true after the jail title. The following example shows how to enable the proftpd jail:

/etc/fail2ban/jail.local
[proftpd]
enabled  = true
port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(proftpd_log)s
backend  = %(proftpd_backend)s

The settings we discussed in the previous section, can be set per jail. Here is an example:

/etc/fail2ban/jail.local
[sshd]
enabled   = true
maxretry  = 3
findtime  = 1d
bantime   = 4w
ignoreip  = 127.0.0.1/8 23.34.45.56

The filters are located in the /etc/fail2ban/filter.d directory, stored in a file with the same name as the jail. If you have a custom setup and experience with regular expressions, you can fine-tune the filters.

Each time you edit a configuration file, you need to restart the Fail2ban service for changes to take effect:

sudo systemctl restart fail2ban

Fail2ban Client

Fail2ban ships with a command-line tool named fail2ban-client which you can use to interact with the Fail2ban service.

To view all available options, invoke the command with the -h option:

fail2ban-client -h

This tool can be used to ban/unban IP addresses, change settings, restart the service, and more. Here are a few examples:

  • Check the jail status:
    sudo fail2ban-client status sshd
  • Unban an IP:
    sudo fail2ban-client set sshd unbanip 23.34.45.56
  • Ban an IP:
    sudo fail2ban-client set sshd banip 23.34.45.56

Source: How to Install and Configure Fail2ban on Ubuntu 20.04 | Linuxize

vim – nvim norm command

1

In neovim 0.4.3-3 in normal mode this command :

:put=range(1,4)

will put numbered list from 1 to 4

but when i want to put numbers only in blank lines like this:

:g/^$/norm :put=range(1,14) 

it is not working as expected – only highlighting empty lines but put is not working, why ?

The :normal command only executes complete commands and your :put Ex command is missing an “Enter” at the end to actually execute it.

From :help :normal:

{commands} should be a complete command. If {commands} does not finish a command, the last one will be aborted as if <Esc> or <C-C> was typed. : command must be completed as well.

You can fix that by adding an extra “Enter” character at the end of your command, which you can enter with:

Ctrl+VEnter

It will display as a ^M in Vim:

:g/^$/norm :put=range(1,14)^M

(There are ways to avoid having to enter a literal “Enter” in your command. For instance, the :execute command is often used for that.)

But in this case there’s a much simpler solution, which is to drop the :normal altogether and just have :g run :put directly!

:g/^$/put=range(1,14)

The :g command will run an Ex command for each line it matches and :put is an Ex command, so you can just cut the middle man here.

Note that what this command does is append 14 new numbered lines after each blank line in your buffer. Not sure if that’s actually what you intended with it or not.

Source: vim – nvim norm command – Unix & Linux Stack Exchange