web-dev-qa-db-ja.com

USBデバイスのマウント時にアプリケーションを起動(GUI)

Ubuntu-gnome 16.04 LTS 4.4.0-62-genericを実行しています。

私は次のことをしたいと思います:いずれかを実行します...

  • (a)アプリケーション(GUI)[/path/to/my_app.desktop]
  • または(b)ターミナルのインタラクティブスクリプト[例:$ gnome-terminal -x /path/to/script.sh]

... any(USB)デバイスのマウントが認識されるたびに。

実行中のアプリケーション/スクリプトに応じてさまざまなユーザー入力が必要になるため、ユーザーのXサーバーでの実行は必須のようです。単にバックグラウンドで実行することはできません。

過去2日間、広範な調査を行い、udev-rulessystemd.services。私の繰り返し発生する問題は、後者のいずれかのアプローチがX-authentificationを必要とすることです。認証を実現する(複雑な)方法は確かにありますが、$ XAUTHORITY変数をエクスポートすることにより、生得的なシステムセキュリティに違反するという考えは好きではありませんルートからユーザーのセッションまで...

私は、次のことを実現する代替方法があるべきだと思います:

  1. 新しい(USB)デバイスがいつマウントされたかを検出する
  2. ユーザーのデスクトップ(つまり、ユーザーのXsession?)のUSER特権でアプリケーション/スクリプトを(ターミナルで)起動します
  3. (オプション:デバイス名を変数として渡します)

(マウント固有の.configファイルの作成?; org.gnome.desktop.media-handling ?;/home/$ USERNAME/media .mountsを監視する自動起動スクリプト?;/etc/fstabの編集; ...?)

ヒントをいただければ幸いです。

3
brunuser

(古い答え、さらに下の新しい答え)


USBドライブが接続されるたびに実行するスクリプトまたはコマンドを実行する

何らかの理由でudevルールまたはより複雑なものを使用したくない場合は、以下のスクリプトを使用します。

引数として実行するコマンドでスクリプトを実行するだけで、ジョブが実行されます。

スクリプト:

#!/usr/bin/env python3
import subprocess
import time
import sys

cmd = " ".join(sys.argv[1:])

def get_mountedlist():
    return [(item.split()[0].replace("├─", "").replace("└─", ""),
             item[item.find("/"):]) for item in subprocess.check_output(
            ["/bin/bash", "-c", "lsblk"]).decode("utf-8").split("\n") if "/" in item]

def identify(disk):
    command = "find /dev/disk -ls | grep /"+disk
    return "usb" in subprocess.check_output(["/bin/bash", "-c", command]).decode("utf-8")

mounted1 = get_mountedlist()
while True:
    time.sleep(4)
    mounted2 = get_mountedlist()
    if [d for d in mounted2 if all([not d in mounted1, d != "/", identify(d[0]) == True])]:
        subprocess.Popen(["/bin/bash", "-c", cmd])
    mounted1 = mounted2

使用するには

  1. スクリプトを空のファイルにコピーし、run_usbactions.pyとして保存します
  2. テストたとえば)コマンドでスクリプトを実行します:

    python3 /path/to/run_usbactions.py <command_to_run> <optional_args>
    

    私のテストでは、例えば:

    python3 /path/to/run_usbactions.py gedit file
    

    uSBドライブが接続されたら、geditでfileを開きます。

  3. すべてが正常に機能する場合は、スタートアップアプリケーションに追加します:ダッシュ>スタートアップアプリケーション>追加。コマンドを追加します。

    python3 /path/to/run_usbactions.py <command_to_run> <optional_args>
    

説明

  • 4秒に1回、関数get_mountedlist()で、スクリプトはlsblkの出力を読み取ります。

  • ---(追加パーティションまたはデバイスがマウントされている場合、コマンドの出力(例):

    find /dev/disk -ls | grep sdc1
    

    文字列usbを含め、マウントされたドライブをUSBドライブとして識別します。
    今見てみると、システムコールではなく、より「Python的な」方法で置き換えることができますが、古いスクリプトからコピーしたので、(まだ) 。

  • その後、if新しいドライブはusbであり、" ".join(sys.argv[1:])で設定されたコマンド(+可能な引数)が実行されます。




編集

(2017年12月29日)

Pyudevを使用する

私はpyudevを「満たした」ので、それがもたらす主要な単純化と明確な操作を共有すべきだと思いました。 USBデバイスの挿入時にアクションを実行する簡単なスクリプトは、次のようになります。

#!/usr/bin/env python3
import pyudev
import subprocess
import sys

cmd = " ".join(sys.argv[1:])

monitor = pyudev.Monitor.from_netlink(pyudev.Context())
monitor.filter_by('block')

for device in iter(monitor.poll, None):
    if all([
        device['ACTION'] == "add", 'ID_FS_TYPE' in device,
        device['ID_USB_DRIVER'] == "usb-storage",
        ]):
        print("added", device.get('ID_FS_LABEL'))
        subprocess.Popen(["/bin/bash", "-c", cmd])

使用法

pyudevがインストールされていることを確認します。

Sudo apt install python3-pyudev

以降の手順はまったく同じです。

3
Jacob Vlijm