linuxsudo

The program executed by sudo obtains the wrong DBUS and env


I need to use getenv to determine whether the system is X11 or Wayland, and DBUS to realize the screen capture function. They work well without sudo. However, when using sudo, getenv gets the wrong value and gdbus cannot locate DBUS. I'm pretty sure this is a problem with sudo because I tried echo $WAYLAND_DISPLAY and sudo echo $Wayland_DISPLAY, d-feet and sudo d-feet. They are right when they don't use sudo. However, due to the requirements of other functions in the program, I have to use sudo. Is there any good idea?


Solution

  • Is there any good idea?

    By default, sudo runs the command in a new, fresh environment. From man sudo:

     -E, --preserve-env
                 Indicates to the security policy that the user wishes to preserve their
                 existing environment variables.  The security policy may return an error
                 if the user does not have permission to preserve the environment.
    
     --preserve-env=list
                 Indicates to the security policy that the user wishes to add the comma-
                 separated list of environment variables to those preserved from the user's
                 environment.  The security policy may return an error if the user does not
                 have permission to preserve the environment.  This option may be specified
                 multiple times.
    

    You can list the variables you want to preserve.

    sudo --preserve-env=DBUS_SESSION_BUS_ADDRESS,DISPLAY,WAYLAND_DISPLAY,other_variables,etc command
    

    The other simple way is to use env.

    sudo env DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" DISPLAY="$DISPLAY" etc.. command
    

    With modern Linux with systemd there is no need to use sudo, rather use systemd-run to execute you process (and also from root under a different user). Then systemd-run will automatically setup access to X11 or wayland or DBUS as that user. So just:

    # systemd-run --machine=kamil@.host --user -q -P xprop -root _NET_ACTIVE_WINDOW
    _NET_ACTIVE_WINDOW(WINDOW): window id # 0x6c0000e
    

    The .host --user makes it run as the specified username kamil in my case. Then xprop automatically finds DISPLAY or whatever I have, is it wayland or dbus, and runs in that context.