D-Bus

如何在不執行 X11 的情況下更改 GSettings?

  • January 6, 2018

我有一個安裝腳本,它通過執行大約兩打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開關的答案,但這只是停止了命令的工作。有沒有辦法為所有設置啟動一個守護程序,然後再停止它或其他什麼?

正如您所發現的,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

引用自:https://unix.stackexchange.com/questions/330353