If you're on a system that uses logind, then loginctl
will tell you if the session is remote:
$ loginctl show-session $XDG_SESSION_ID -P Remote
yes
However, there are cases that XDG_SESSION_ID is not defined (including after sudo), so I wrote a script to check more things. It tries loginctl, ssh, remote X display and if all fails, connects to logind via D-Bus and attempts to discover the current session by using the current process PID as a key:
#!/usr/bin/env python3
from os import environ, getpid, system
from sys import argv, stderr
from dbus import SystemBus
from dbus.exceptions import DBusException
DEBUG=0
LOGIND = ('org.freedesktop.login1', '/org/freedesktop/login1')
MANAGER = '%s.Manager' % LOGIND[0]
SESSION = '%s.Session' % LOGIND[0]
SESSION_NOT_FOUND = '%s.NoSessionForPID' % LOGIND[0]
REMOTE = 'Remote'
LOGINCTL = 'loginctl show-session %s -P %s'
PROPERTIES = 'org.freedesktop.DBus.Properties'
DISPLAY = 'DISPLAY'
SSH='SSH_CLIENT'
def debug(msg):
if DEBUG: print(msg, file=stderr)
def try_loginctl():
debug('Trying loginctl...')
try:
r = system(LOGINCTL % (environ['XDG_SESSION_ID'], REMOTE))
# exit early if loginctl prints the result by itself
if r == 0: raise SystemExit
except KeyError:
pass
return False
def try_ssh():
debug('Trying ssh...')
return bool(environ.get(SSH))
def try_x():
debug('Trying X...')
try:
display = environ[DISPLAY]
return ':' in display and len(display.split(':', 1)[0]) > 0
except KeyError:
return False
def try_dbus():
debug('Trying dbus...')
bus = SystemBus()
logind = bus.get_object(*LOGIND)
try:
pid = getpid()
session_path = logind.GetSessionByPID(pid, dbus_interface=MANAGER)
except DBusException as e:
if e.get_dbus_name() == SESSION_NOT_FOUND:
return False
else:
raise
session = bus.get_object(LOGIND[0], session_path)
remote = session.Get(SESSION, REMOTE, dbus_interface=PROPERTIES)
return bool(remote)
def main():
global DEBUG
if '-d' in argv or '--debug' in argv:
DEBUG=1
remote = try_loginctl() or try_ssh() or try_x() or try_dbus()
print(remote and 'yes' or 'no')
main()