通知发送在 Shell 会话中起作用,而不是在脚本中

通知发送在 Shell 会话中起作用,而不是在脚本中

我正在使用at/notify-send作为dunst自我提醒的一种形式。在互动bash环节中,我这样做:

$ echo 'notify-send "Test"' | at 12:45PM

运行正常,我看到通知在 12:45 PM 准时弹出,正如预期的那样。然而,在如下脚本中:

$ cat ~/.local/bin/remind
#!/bin/bash

echo 'notify-send "$1"' | at "$2"

$ remind "Test" "12:45PM"

我没有看到弹出通知。

该职位已在 注册at,如下所示:

$ at -l

所以我不确定问题可能是什么。notify-send在脚本之外工作正常,并且at正确找到了工作,但是在尝试第二种方法时仍然没有看到弹出窗口。

有任何想法吗?

答案1

解释有两个层次:

  1. bash运行脚本会解释整个命令。下面$1单引号,因此不进行扩展。包含文字的字符串"$1"将达到at

  2. 时间到了,at使用 运行先前回显的字符串sh。现在$1用双引号引起来,并且会扩展为空字符串,因为这显然运行时没有参数。您提供给脚本的任何东西都早已消失。最后的命令就像您在 shell 中sh输入的一样。运行它并查看会发生什么。notify-send ""

一个基本的解决方法是交换引号:

echo "notify-send '$1'" | at "$2"

这种方式bash会扩展$1,结果稍后运行时会变成单引号sh。这种方法不太可靠;如果注入单引号,代码就会中断。但在很多情况下,这种方法是可行的。


更强大的方法是这样的:

#/bin/bash

t="$1"
shift
m="$*"

<<<"notify-send ${m@Q}" at "$t"

重点是使用${variable@Q}语法。它使 Bash 扩展变量并正确地单引号结果,因此稍后可以安全地解析它(sh在本例中是)。

注意我从第一个参数获取时间。这样做的目的是能够在没有不方便的引号的情况下调用脚本,如下所示:

remind 15:10 Go to Yuma

相关内容