如何使 crontab 与当前登录用户的会话交互?

如何使 crontab 与当前登录用户的会话交互?

问题

Crontab 确实可以工作——但只是放在一边,而不是与用户交互。如何让 crontab 通过自动感知的提示输出与当前登录的用户对话?例如,叫醒电话、闹钟,每分钟为用户 1 响一次,用户 1 不需要做任何事情来接收消息,除了在计算机前睁开眼睛和耳朵?

边注 计时,每分钟……——当然,这只是一个技术示例,实际上会选择更有意义和有用的计时。

想象一下这个

电脑 = 关闭

用户1 = 戴夫

戴夫:


*switching on computer*

*logs into his user account "dave"*

*lands in GUI desktop*

*starts mate-terminal*

检查谁已登录以及他们正在做什么:

dave@LocalMachine:~$ w
12:46:42 up  4:22,  2 users,  load average: 0.18, 0.44, 0.43
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
dave   tty7     :0               08:24    4:22m  6:57   0.31s mate-session

在 /tmp/ 中创建可执行 bash 脚本“alarm_clock”

dave@LocalMachine:~$ emacs -nw /tmp/alarm_clock && chmod +x /tmp/alarm_clock
#    Alarm clock displaying current time and ringing.
#
#    Copyleft 

答案1

^G特点

首先,当您这样做时echo '\a',收到铃声的终端会发出铃声。它只是一个八进制值为 007 的 ASCII 代码。它也相当于按 CTRL+G (`^G)。

来自 man 7 ascii:

       Oct   Dec   Hex   Char                        Oct   Dec   Hex   Char
       ────────────────────────────────────────────────────────────────────────
       000   0     00    NUL '\0' (null character)   100   64    40    @
       001   1     01    SOH (start of heading)      101   65    41    A
       002   2     02    STX (start of text)         102   66    42    B
       003   3     03    ETX (end of text)           103   67    43    C
       004   4     04    EOT (end of transmission)   104   68    44    D
       005   5     05    ENQ (enquiry)               105   69    45    E
       006   6     06    ACK (acknowledge)           106   70    46    F
       007   7     07    BEL '\a' (bell)             107   71    47    G

通常这个字符是不可见的:

$ echo -e "$(date) \a"
Tue Jan  2 18:31:38 IST 2024 

但是你可以通过在命令中添加-v/标志来看到它(--show-nonprintingcat使用 ^ 和 M- 表示法,LFD 和 TAB 除外):

$ echo -e "$(date) \a" |cat -v
Tue Jan  2 18:31:40 IST 2024 ^G

因此,当您将此 ascii 代码写入文件(而不是终端)时,您只需将八进制 007 字符的值写入该文件。只有当您将其写入终端时,您才会听到“嘟嘟”声。

-e不被使用echo

脚本的另一个问题是它不是以 Shebang ( #!) 开头,而是以注释开头。在这种情况下,您#!/bin/bash将被忽略,并且脚本可能会由 执行/bin/sh。看man 5 crontab

几个环境变量由 cron(8) 守护进程自动设置。 SHELL 设置为 /bin/sh [...]

/bin/sh您的计算机上可能有一些符合 POSIX 的 shell,其中的echo内置函数不支持该-e标志(POSIX 未定义该标志,通常只是一个扩展)。在这种情况下,它将使用-e作为您想要回显的字符串的一部分。如果您想确保使用bash,请将评论移至舍邦。

另外,对于这种情况,最好使用printf,例如:printf "$(date) \a\n"

将消息发送到实际终端

正如我们所说,当您将其写入文件时,您不会与任何终端交互,而只是将一些字符写入文件。如果你想将消息发送到终端,最好使用write(1),这会将消息发送到用户的最后一个活动 tty。例如:

printf "$(date)\a\n" | write <USER>

在这种情况下,用户将在其活动 shell 上收到一条消息,例如:

Message from root@locahost on pts/0 at 19:00 ...
Tue Jan  2 19:00:49 IST 2024 
EOF

或者,如果您想将消息发送给所有用户和终端,请使用wall(1)

printf "$(date)\a\n" | wall

相关内容