用sudo设置其他用户的gsettings

时间:2013-11-29 19:55:25

标签: bash shell ubuntu sudo

在Ubuntu 13.10上,我将所有gsettings放在一个文件mygset.sh中。例如,mygset.sh包含许多行,例如

gsettings set com.canonical.Unity.Launcher favorites "['application://nautilus.desktop', 'application://firefox.desktop', 'application://chromium-browser.desktop', 'unity://running-apps', 'unity://expo-icon', 'unity://devices']"

我有一个主安装脚本,我必须使用sudo运行(例如,它执行sudo apt-get install)。 从该主安装脚本我想调用mygset.sh。但是,无论我怎么称呼它,它都不会改变我的用户的设置。我认为它正在改变root的设置。我尝试过(从masterinstall.sh开始运行sudo ./masterinstall.sh):

sudo -u "wang" ./mygset.sh
sudo -u "wang" bash -c ./mygset.sh

这些都不起作用(它们运行时没有错误并更改设置[我在脚本中用gsetting get检查]但不是用户“wang”)。

当我从命令行运行mygset.sh时(没有sudo:bash ./mygset.sh)。它完美地运作。为什么会出现这种差异?我可以在masterinstall.sh内解决这个问题?

6 个答案:

答案 0 :(得分:5)

默认情况下,sudo将uid和gid设置为您指定的用户,但不会更改环境设置等。

建议您首先尝试-H,将$HOME变量设置为目标用户:

sudo -u "wang" -H ./myget.sh

如果这不起作用,请尝试-i,它应该模拟初始登录。

我发现有时候工作的一个稍微不同的方法是使用su

sudo su - wang
/full/path/to/myget.sh
exit

您需要使用脚本的完整路径,因为su命令会更改当前的工作目录。

答案 1 :(得分:3)

我建议您编写一个“父”脚本,然后可以使用sudo启动masterinstall,然后再以本地用户身份再次运行myget。示例如下:

#!/bin/bash

sudo ./masterinstall.sh
./mygset.sh

答案 2 :(得分:2)

也许您应该以设置应更改的用户身份运行每个gsettings set ...

sudo -u wang dbus-launch --exit-with-session gsettings set com.canonical.Unity.Launcher favorites "['application://nautilus.desktop', 'application://firefox.desktop', 'application://chromium-browser.desktop', 'unity://running-apps', 'unity://expo-icon', 'unity://devices']" >/dev/null 2>&1

可能会因为没有创建 .dbus / session-bus 而抱怨错误。添加>/dev/null 2>&1会抑制它们。

请注意,更改unmountes加密家庭的设置将无法正常工作。

使用 pam_mount 自动映射远程共享时,脚本将停止并等待pam_mount密码。 您可以通过临时停用pam_mount来解决此问题:

# deactivate pam_mount   
sed 's/@include common-session-noninteractive/#@include common-session-noninteractive/g' -i /etc/pam.d/sudo 
sed 's/session\toptional\tpam_mount.so/#session\toptional\tpam_mount.so/g' -i /etc/pam.d/common-session

# do your settings

# reactivate pam_mount   
sed 's/#@include common-session-noninteractive/@include common-session-noninteractive/g' -i /etc/pam.d/sudo 
sed 's/#session\toptional\tpam_mount.so/session\toptional\tpam_mount.so/g' -i /etc/pam.d/common-session

答案 3 :(得分:2)

我有一个POST-Install脚本来设置我的gsetting。因为我将脚本作为sudo运行,因此EUID为0,因此我必须找到$ RUID(真实用户ID)。

这是我的方法:

#!/usr/bin/env bash
# Get the Real Username
RUID=$(who | awk 'FNR == 1 {print $1}')

# Translate Real Username to Real User ID
RUSER_UID=$(id -u ${RUID})

# Set gsettings for the Real User
sudo -u ${RUID} DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/${RUSER_UID}/bus" gsettings set org.gnome.desktop.interface clock-show-date false

exit

答案 4 :(得分:1)

尝试了很多不同组合的东西之后,这是唯一对我有用的命令:

sudo -H -u <user> DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<uid>/bus gsettings set...

在bash脚本中,您可以使用以下功能自动检测当前会话的用户和环境:

function run-in-user-session() {
    _display_id=":$(find /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
    _username=$(who | grep "\(${_display_id}\)" | awk '{print $1}')
    _user_id=$(id -u "$_username")
    _environment=("DISPLAY=$_display_id" "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$_user_id/bus")
    sudo -Hu "$_username" env "${_environment[@]}" "$@"
}

像这样使用它:

run-in-user-session gsettings set...

答案 5 :(得分:0)

gsettings 命令需要知道用户 dbus 会话的总线地址,因为 dconf 使用 D-Bus,因此 $DBUS_SESSION_BUS_ADDRESS 需要在使用 sudo 运行主脚本时从用户环境传递到 root 环境,然后从 root 的环境返回到用户的环境,同时使用 sudo 运行脚本中的 gsettings 命令。如果不担心安全问题,整个环境可以得到保护。

所以,在这种特殊情况下,从命令行:

sudo --preserve-env=DBUS_SESSION_BUS_ADDRESS ./masterinstall.sh

sudo -E ./masterinstall.sh

并且,从 masterinstall.sh 内部:

sudo -E -u wang ./mygset.sh

如果要直接在 masterinstall.sh 中更改 GNOME 设置:

sudo -E -u wang bash <<- EOF
    gsettings set ...
    gsettings set ...
    EOF

此外,在 gsettings 命令必须放在单独的脚本中的情况下,第三个脚本仅用作两个脚本的包装器(如已接受的答案),运行带有 sudo 的主脚本包装器脚本可能没问题,但在一般情况下,在一个脚本中以 root 身份运行多个命令而不以 root 身份运行可能需要多次输入 root 密码,具体取决于运行中间命令所需的时间,以及因此,以 root 身份运行主脚本并根据需要使用 sudo -u 更改脚本中的其他用户通常是一种更好的方法。