我有一个安装脚本,可以通过运行大约两打gsettings set
命令来自定义目标计算机。问题是,只有当您以正确的用户身份运行该命令时,这才有效。如果你以 root 身份运行它,它根本不起作用。
所以我发明了一个脚本函数,如下所示:
function GSET
{
echo "gsettings set '$1' '$2' '$3'"
sudo -u mango dbus-launch gsettings set "$1" "$2" "$3"
}
然后该脚本调用该函数数十次,这似乎有效(即设置现在实际上发生了变化),并且一切都很好。
好吧,不完全是:如果我在我尝试配置的机器上运行它,它似乎工作得很好。如果我尝试在chroot
环境中的构建服务器上运行它来创建安装映像...服务器dbus-daemon
上现在有十几个进程正在运行。每次我运行新的安装版本时,都会留下越来越多的无用进程在运行,直到最终服务器耗尽某种资源(PID 或其他东西),并gsettings
完全停止工作。
所以,我的问题是:什么是正确的怎样做gsettings
工作?我在某个地方看到了另一个答案,建议添加--exit-with-session
开关,但这根本就停止了命令的工作。有没有办法为所有设置启动一个守护进程,然后停止它或其他什么?
答案1
正如您所发现的,dbus-launch
每次运行时都会创建一个新的 D-Bus 守护进程。您可以dbus-launch
在完成后使用并杀死它:
# Make the function
GSET () {
sudo -u mango DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" gsettings set "$1" "$2" "$3"
}
# Launch the daemon
. <(sudo -u mango dbus-daemon --sh-syntax)
# Run as many commands as you need
GSET x1 y1 z1
GSET x2 y2 z2
...
# Kill the daemon
sudo -u mango kill "$DBUS_SESSION_BUS_PID"
您可以使用基于 shell 的事务方法来避免sudo
重复调用。就像是:
script=$(mktemp gset-transaction.XXXXXXXXXX)
create_transaction () {
printf '. <(dbus-launch --sh-syntax)\n' > "$script"
}
GSET () {
printf 'gsettings set "%s" "%s" "%s"\n' "$1" "$2" "$3" >> "$script"
}
commit_transaction () {
printf 'kill "$DBUS_SESSION_BUS_PID"\n' >> "$script"
sudo -u mango bash -c "$script"
# optionally:
# rm "$script"
}
create_transaction
GSET x1 y1 z1
GSET x2 y2 z2
...
commit_transaction