在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
内解决这个问题?
答案 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
更改脚本中的其他用户通常是一种更好的方法。