web-dev-qa-db-ja.com

cronから開始されたGsettingsの編集が失敗する

死角がなければなりませんが、それが何なのかわかりません。

サウンドメニューからVLCを削除する小さなpythonスクリプトを作成しました。ターミナルやランチャーなど、思いつくものなら何でも実行できます。

スクリプトが実際に行うことは、現在の設定を取得するだけです。

gsettings get com.canonical.indicator.sound interested-media-players

リストを編集し、変更したリストを次の方法で設定します。

gsettings set com.canonical.indicator.sound interested-media-players "['newlist']"

これらのコマンドは、pythonスクリプトによって実行されます。ただし、cronjobから実行する場合crontab -e)gsettingsのみ-get- =一部は動作しますが、notgsettings -set-セクション。 getセクションがcronで正常に機能することを、スクリプトでデータ(元のファイルと編集済みのファイル)を外部ファイルに書き込むことで確認しました。

python問題ではありません

問題がpythonコードに関連しているかどうかを確認するために、変更されたサウンドメニュー項目リストを適用するbashスクリプトを作成しました。ストーリーは同じです。bashスクリプトはコマンドラインまたはランチャーから正常に実行され、notはcronから実行されますが、同じスクリプト内の他のコマンドは正常に実行されます。また、以下のスクリプトの最後にコマンドを追加すると、正常に機能し、スクリプトが独自の作業に満足しているように見えます。

Cronから開始したときにgsettingssetコマンドが機能しないのはなぜですか?

これはスクリプトです:

#!/usr/bin/python3
import subprocess

def read_soundmenu():
    # read the current launcher contents
    get_menuitems = subprocess.Popen([
        "gsettings", "get", "com.canonical.indicator.sound", "interested-media-players"
        ], stdout=subprocess.PIPE)
    return eval((get_menuitems.communicate()[0].decode("utf-8")))

def set_current_menu(current_list): # this takes no effect from cron
    # preparing subprocess command string
    current_list = str(current_list).replace(", ", ",")
    subprocess.Popen([
        "gsettings", "set", "com.canonical.indicator.sound", "interested-media-players",
        current_list,
        ])

current_list = read_soundmenu()
for item in current_list:
    if item == "vlc.desktop":
        current_list.remove(item)
set_current_menu(current_list)
6
Jacob Vlijm

解決策

盲点は私の知識の穴であることが判明しました。 pythonスクリプト(gsettings set)でspecificコマンドを実行しない理由は、cronが非常に制限された環境変数のセットを使用するためです。

Cronからgsettings *set*コマンドを実行するには(一般的に)、個人のcronファイルから実行するだけでは不十分です。環境変数DBUS_SESSION_BUS_ADDRESSは正しい実行に必要です。

利便性と柔軟性の理由から、変数をエクスポートし、実際のスクリプトを呼び出す「中間」スクリプトを作成して、 スタックオーバーフローに関するこの投稿 の情報に基づいて解決しました。 。実際のスクリプトはgsettingsを編集します。 (通常)プロセスは親の環境を継承するため、スクリプトは正常に実行されます。

#!/bin/bash

PID=$(pgrep gnome-session)
export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ|cut -d= -f2-);/path/to/script.py

(script.pyが実行可能であると仮定)

pythonスクリプトにDBUS_SESSION_BUS_ADDRESS変数を含める

pythonスクリプトでgsettingsを編集可能にするには、cronで実行し(そして中間スクリプトを不要にする)、以下の関数をスクリプトに含めることができます。スクリプトのgsettings set関数の前に呼び出す必要があります。

#!/usr/bin/env python3
import os
import subprocess

def set_envir():
    pid = subprocess.check_output(["pgrep", "gnome-session"]).decode("utf-8").strip()
    cmd = "grep -z DBUS_SESSION_BUS_ADDRESS /proc/"+pid+"/environ|cut -d= -f2-"
    os.environ["DBUS_SESSION_BUS_ADDRESS"] = subprocess.check_output(
        ['/bin/bash', '-c', cmd]).decode("utf-8").strip().replace("\0", "")
6
Jacob Vlijm