我正在使用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
解释有两个层次:
bash
运行脚本会解释整个命令。下面$1
是单引号,因此不进行扩展。包含文字的字符串"$1"
将达到at
。时间到了,
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