acpi イベントと udev イベントによって呼び出されると、スクリプトが誤って動作する

acpi イベントと udev イベントによって呼び出されると、スクリプトが誤って動作する

/etc/acpi/eventsには次のファイルがあります/etc/udev/rules.d

  • /etc/acpi/events/lidclose

    # Pass all events to our one handler script
    event=button/lid
    action=/etc/acpi/monitors.sh
    
  • /etc/udev/rules.d/80-monitor.rules

    # change monitor settings when monitor is plugged in or o$
    ACTION=="change", SUBSYSTEM=="drm", HOTPLUG=="1", RUN+="/etc/acpi/monitors.sh"
    
  • 今(実行可能で、ルートが所有しています)/etc/acpi/monitors.sh

    #!/bin/sh
    
    # default monitor is LVDS1
    STATE=internal
    INTERNAL=LVDS1
    EXTERNAL=HDMI3
    
    # functions to switch from LVDS1 to VGA and vice versa
    function internal {
        echo "Switching to internal"
        xrandr --output $EXTERNAL --off --output $INTERNAL --auto
        STATE=internal
    }
    function external {
        echo "Switching to external"
        xrandr --output $EXTERNAL --auto --output $INTERNAL --off
        STATE=external
    }
    function both {
        echo "Switching to both"
        xrandr --output $EXTERNAL --auto --right-of $INTERNAL --output $INTERNAL --auto --primary
        STATE=both
    }
    
    # functions to check if VGA is connected and in use
    function externalConnected {
        ! xrandr | grep "^$EXTERNAL" | grep disconnected >/dev/null
    }
    function lidOpen {
        ! cat /proc/acpi/button/lid/LID/state | grep closed >/dev/null
    }
    
    # actual script
    if ! [ $STATE == "both" ] && externalConnected && lidOpen
    then
        both
    fi
    
    if ! [ $STATE == "external" ] && externalConnected && ! lidOpen
    then
        external
    fi
    
    if ! [ $STATE == "internal" ] && ! externalConnected && lidOpen
    then
        internal
    fi
    

これで、rootとユーザーとしてスクリプトをテストしましたが、完全に機能しました。また、echo bla > /home/me/testここにいくつかのテスト出力を入れて、byが呼び出されると出力が生成され、udev実行acpidされます。唯一のことは何も起こらなかったことですxrandr

私は何を見逃していますか?エラーを見つけるためにスクリプト出力を記録するにはどうすればよいですか?

答え1

私の質問にコメントしてくださった方々の助けを借りて問題を把握し、スクリプトで修正しました。

これで、ノートブックを使用して自動画面切り替えを実行する方法に関する更新されたルーチンがあります。 acpid、kms、udevが必要です。

acpiとudevに対して次のルールを作成します。

/etc/acpi/events/lidclose

# Pass all events to our one handler script
event=button/lid
action=/etc/acpi/monitors.sh

/etc/udev/rules.d/80-monitor.rules

# change monitor settings when monitor is plugged in or o$
ACTION=="change", SUBSYSTEM=="drm", HOTPLUG=="1", RUN+="/etc/acpi/monitors.sh"

次に、/etc/acpi/monitors.sh を作成します。

#!/bin/sh

# specify the monitors to use
INTERNAL=LVDS1
EXTERNAL=HDMI3
USERNAME=oli

# set some variables needed to control the x server
export XAUTHORITY=/home/$USERNAME/.Xauthority
export DISPLAY=:0

# functions to switch from internal screen to external screen and vice versa or to use both screens together
function internal {
    echo "Switching to internal" >> /var/log/monitors.log
    xrandr --verbose --output $EXTERNAL --off --output $INTERNAL --auto >> /var/log/monitors.log 2>&1
}
function external {
    echo "Switching to external" >> /var/log/monitors.log
    xrandr --verbose --output $EXTERNAL --auto --output $INTERNAL --off >> /var/log/monitors.log 2>&1
}
function both {
    echo "Switching to both" >> /var/log/monitors.log
    xrandr --verbose --output $EXTERNAL --auto --right-of $INTERNAL --output $INTERNAL --auto --primary >> /var/log/monitors.log 2>&1
}

# functions to check if external monitor is connected and in use
function externalConnected {
    ! xrandr | grep "^$EXTERNAL" | grep disconnected >/dev/null
}
function lidOpen {
    ! cat /proc/acpi/button/lid/LID/state | grep closed >/dev/null
}

# actual script
if externalConnected && lidOpen
then
    both
fi

if externalConnected && ! lidOpen
then
    external
fi

if ! externalConnected && lidOpen
then
    internal
fi

それがうまくいくことを願っています。

答え2

Janoliverのソリューションほぼ完璧に動作します。小さな修正で、最終的に私のシステムのHOTPLUG変数の問題を修正しました。

/etc/udev/rules.d/80-monitor.rules:

# change monitor settings when monitor is plugged in or off
ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/etc/acpi/monitors.sh"

つまり、HOTPLUGに変更しますENV{HOTPLUG}

関連情報