bash 脚本不启动多次

bash 脚本不启动多次

所以我有一个 bash 脚本,如果电池电量低,它会通知我。

脚本在这里

#!/bin/bash

BATTERY=$(upower -e | grep 'BAT')

while :
do
    BATTERY_PERCENTAGE=$(upower -i $BATTERY | grep percentage | awk '{ print $2 }' | sed s/'%'/''/g)
    CABLE=$(upower -d | grep -n2 line-power | grep online | awk '{ print $3 }')

    if [[ "$BATTERY_PERCENTAGE" -lt "10" && $CABLE = "no" ]]; then
        notify-send --urgency=critical "WARNING: Battery is about to die"  "Plug in the power cable"
    fi

sleep 60

done

所以我目前正在使用dwm窗口管理器Arch Linux。问题是,如果我只是关闭窗口管理器,然后再次启动它,它实际上会关闭我正在使用的所有程序(例如 Flameshot 和 Dunst),但它无法杀死我的电池脚本。这是我在.xinitrc文件中运行的自动启动脚本。

# My .xinitrc file
# This file will run as autostart

dunst &
flameshot &
setxkbmap -option caps:escape &
sxhkd -c ~/suckless/dwm/sxhkdrc &
~/.fehbg &
~/scripts/battery-notification & 
xrdb ~/.Xresources &
exec dwm 

我通过 xorg 的 startx 运行这个文件。如果我执行 a ps -ef | grep battery-notification,它会显示超过 2 个实例(其中包括电池脚本和 grep)。

感谢您的回答:)

答案1

您可以在脚本中添加锁定文件机制。只需确保脚本退出时锁定文件被可靠地删除,例如通过设置陷阱:

#!/bin/bash

lockfile="/var/run/lock/batterystatus.lock"

if [[ -e "$lockfile" ]]; then exit 0; fi

trap 'rm -f "$lockfile"' EXIT
touch "$lockfile"

# ... your actual script code here

请注意,如果脚本以 终止SIGKILL,则trap不足以可靠地删除锁定文件。


经过 Kamil Maciorowski 的有益澄清后,这里是一个使用flock.

#!/bin/bash

lockfile="/var/run/lock/batterystatus.lock"
exec 100>"$lockfile"
if ! flock -n 100; then exit 0; fi

# ... your actual script here

如果需要,这将创建锁定文件,并重定向文件描述符100(选择几乎任意)(1)到锁文件。然后它尝试通过 来锁定该文件描述符flock。如果成功,锁定将一直保持到脚本退出为止。另一方面,如果另一个脚本实例已经锁定了该文件描述符,则该脚本将立即退出。

请注意,无需清理锁定文件 - 所执行的锁定flock与此处相关。这也意味着存在锁定文件的存在并不意味着脚本不应该启动——只有该文件上存在锁定才意味着不应该启动脚本。

这个想法取自这里。如需进一步阅读,请查看

  • bash集群:如果无法获取锁则退出(在这里您可以看到,您甚至可以使用脚本文件本身作为锁定文件 - 如前所述,只有锁定才起作用,而不是文件的存在/不存在)。

(1)如果你有 Bash > 4.1,你可以有 shell自动分配通过 -Syntax 的空闲文件描述符,如下所示:{variable-name}>redirection-target

exec {lockfd}>"$lockfile"
if ! flock -n "$lockfd"; then exit 0; fi

shell 将查找下一个空闲文件描述符(限制为仅使用描述符编号 > 9),并将实际使用的描述符存储在变量中$lockfd以供进一步使用。

答案2

我还没有尝试过,但这可能有效:

在 .xinitrc 脚本的顶部:

trap 'kill 0' EXIT

这将杀死进程组中的所有进程。您可能不想在最后执行 dwm。只需给它 dwm 而无需执行;这将使父 bash shell 保持打开状态,直到 dwm 终止。

答案3

You can add below commands to kill the battery script while logging in

ps -eaf | awk 'BEGIN{IGNORECASE=1}/battery/ && !/awk/{print "kill -9 "$2}'| sh

相关内容