Blog post

Mastering Session-Based Script Execution in Linux

Mayank Sharma

-
December 19, 2024
Linux
Bash
Script
Sessions
Ubuntu
Shell

When managing Linux systems, there are often scenarios where scripts or commands need to be executed based on the type of user login. For example, you might want certain actions to run only during GUI logins (via a display manager) or SSH logins. One commonly used mechanism for detecting GUI sessions is the XDG_SESSION_TYPE environment variable. In this blog, we will explore how this variable works, its limitations, and how to ensure compatibility with various Linux display managers.

What is XDG_SESSION_TYPE?

XDG_SESSION_TYPE is an environment variable set by the display manager or session manager. It indicates the session type for the logged-in user. The values it typically holds are:

  • x11: Indicates an X11-based graphical session.
  • wayland: Indicates a Wayland-based graphical session.
  • tty: Indicates a terminal (TTY) session.

This variable is particularly useful for distinguishing between graphical and terminal sessions and is supported by most modern Linux display managers.

Supported Display Managers

Here’s how various popular display managers handle XDG_SESSION_TYPE:

  1. GDM (GNOME Display Manager):
    — Fully supports XDG_SESSION_TYPE.
    — Sets the variable to x11 or wayland based on the session.
  2. LightDM:
    — Supports XDG_SESSION_TYPE for most configurations.
    — Works well with multiple desktop environments like XFCE and MATE.
  3. SDDM (Simple Desktop Display Manager):
    — Modern display manager used with KDE Plasma and LXQt.
    — Sets XDG_SESSION_TYPE as expected.
  4. LXDM:
    — Limited modern support. While it often sets XDG_SESSION_TYPE, this may not be consistent across all distributions.
  5. XDM (X Display Manager):
    — An older display manager. It does not guarantee support for XDG_SESSION_TYPE.

Handling GUI and Non-GUI Logins

If you want to detect and handle logins differently based on the session type, you can use XDG_SESSION_TYPE in your scripts. Below is an example of a script that executes a command for GUI logins and skips terminal (TTY) logins:

#!/bin/bash # Command to run
on valid logins(passed as argument
while running this script) COMMAND= # Check
if the PAM event is
for opening a session [ " $PAM_TYPE " = "open_session" ];
then # Check
if login is a GUI session [[ " $XDG_SESSION_TYPE " == "x11" || " $XDG_SESSION_TYPE " == "wayland" ]];
then # Run the command
for GUI login $COMMAND else echo "Non-GUI session detected. Skipping command." else echo "Skipping
for PAM_TYPE= $PAM_TYPE "

Challenges with XDG_SESSION_TYPE

While XDG_SESSION_TYPE is reliable for many setups, there are some limitations:

  1. Older Display Managers (e.g., XDM):
    — XDM does not consistently set XDG_SESSION_TYPE.
  2. Inconsistencies Across Environments:
    — For some lightweight display managers like LXDM, the behavior may vary based on distribution-specific configurations.
  3. SSH Logins:
    — For SSH sessions, XDG_SESSION_TYPE is either unset or not relevant. You need to rely on other variables, like SSH_CONNECTION, to identify SSH logins.

Fallback Mechanisms for Better Compatibility

To handle cases where XDG_SESSION_TYPE is not set or behaves inconsistently, consider using fallback mechanisms like DISPLAY or loginctl.

Checking DISPLAY

The DISPLAY variable is typically set during GUI sessions. You can use this as a fallback:

[[ -n " $DISPLAY " ]];
then echo "GUI session detected." else echo "Non-GUI session detected."

Using loginctl

The loginctl command can provide detailed session information:

SESSION_TYPE=$(loginctl show-session $(loginctl | grep $PAM_USER | awk '{print $1}' ) -p Type --value) [[ " $SESSION_TYPE " == "x11" || " $SESSION_TYPE " == "wayland" ]];
then echo "GUI session detected."

Handling SSH Logins

SSH logins present a unique case where XDG_SESSION_TYPE may not provide useful information. To specifically handle SSH logins, you can use the SSH_CONNECTION variable, which is set during SSH sessions. For example:

[[ -n " $SSH_CONNECTION " ]];
then echo "SSH session detected." $COMMAND # Run the desired command
for SSH logins else echo "Not an SSH session."

Additionally, you can add your script to the PAM configuration file for SSH, typically located at /etc/pam.d/sshd. For instance:

session optional pam_exec.so /path/to/your/script

This ensures the script is executed during SSH login events. Always test your changes in a safe environment to avoid locking yourself out of the system.

Best Practices for Script Execution

  1. Log PAM Events for Debugging:
    — Include logging in your scripts to debug unexpected behavior:
    echo “$(date): PAM_TYPE=$PAM_TYPE
    SESSION_TYPE=$XDG_SESSION_TYPE
    SSH_CONNECTION=$SSH_CONNECTION” >> /tmp/script.log
  2. Use Conditional Execution:
    — Ensure your script only runs during open_session events to avoid redundant executions.
  3. Test Across Multiple Display Managers and SSH:
    — Validate your script in environments with different display managers and SSH configurations to ensure compatibility.

Conclusion

The XDG_SESSION_TYPE variable is a powerful tool for distinguishing between GUI and non-GUI sessions in Linux. While it’s widely supported across modern display managers like GDM, LightDM, and SDDM, older managers like XDM may require fallback mechanisms like DISPLAY or loginctl.

For SSH sessions, relying on the SSH_CONNECTION variable or integrating scripts directly into the /etc/pam.d/sshd configuration file ensures reliable execution. By combining XDG_SESSION_TYPE with robust fallback checks and thorough testing, you can create scripts that adapt seamlessly to various Linux environments.

Connect and Share

If you found this blog helpful, please like, share, and comment below with your thoughts or experiences! I’d love to hear how you handle session-based script execution in your setups. Feel free to connect with me on LinkedIn to discuss further and stay updated with more content like this!

Related Blog Posts