Wednesday 18 April 2018

crontab 的排错 - 最快的姿势

常看见有人问 crontab 的问题。我觉得有必要写这篇文章。

crontab 排错事项通常有三点:
1. 置顶 SHELL=/bin/bash ,因为默认 shell 可能不支持你放在 crontab 的语法。
2. 命令和 shell 脚本加上 echo yyy >> /tmp/xxx.log (别忘了 >> 和 > 的区别) 或 touch /tmp/yyy.log (别忘了删除), 来确认你要执行的 crontab 命令或 shell 脚本有运行至重点部分。
3. 环境变量。

新手最意想不到的排错正是第三种,环境变量。在交互模式有环境变量促使某些命令能运行, crontab 默认没有给以足够的环境变量。

让我说说如何在 xubuntu 利用 crontab 换背景图。

终端输入命令 crontab -e (如果是问 editor, 就选 vim.tiny),然后敲 i 进入 insert mode, 输入:

SHELL=/bin/bash
* * * * * (PID=$(pgrep xfce4-session); export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ|cut -d= -f2-); xfconf-query --channel xfce4-desktop --property /backdrop/screen0/monitor0/workspace0/last-image --set /home/xubuntu/Pictures/1.jpg)
* * * * * (sleep 5; PID=$(pgrep xfce4-session); export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ|cut -d= -f2-); xfconf-query --channel xfce4-desktop --property /backdrop/screen0/monitor0/workspace0/last-image --set /home/xubuntu/Pictures/2.jpg)

然后 Esc,然后 :wq 储存出去。然后每1分钟的第一秒会换背景图成 /home/xubuntu/Pictures/1.jpg,然后等 5 秒会变成 /home/xubuntu/Pictures/2.jpg,然后等多 50 秒又变回去 1.jpg, ... 周而复始。

上面的 export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ|cut -d= -f2-); 用途是什么 ?

用途是换背景图需要定义 DBUS_SESSION_BUS_ADDRESS 这个环境变量。

在终端交互模式输入 env 就能知道当前的变量,再和 crontab 的 env > /tmp/env.log 做个比较,就能知晓 crontab 默认的环境变量是很少的。

如何知晓换背景图需要 DBUS_SESSION_BUS_ADDRESS 这个关键的环境变量 ? 你可以用我独创的姿势:

a. declare -p > /tmp/d.sh
env > /tmp/d.sh 会卸掉引号所以不适合直接用, 所以才选择 declare -p > /tmp/d.sh。内容里的 declare -x 恰好就是 export 。

b. 在 /tmp/test.sh 输入 (eog 程序拿来看图, 只是例子):

  . /tmp/d.sh
  eog /home/xiaobai/Pictures/1.jpg

c. 最后不停测试如下。 如果成功显示图片,就删除 /tmp/d.sh 一半的内容; 反之则 undo 再删除另一半, 或一半的一半:
  env -i bash /tmp/test.sh
原理是 env -i 去除全部环境变量,然后 source (点号) 那新的环境变量让脚本使用。
d. 最后就能快速锁定出最关键的环境变量, 可以是多个环境变量, 比如 eog 需要 DBUS_SESSION_BUS_ADDRESS 和 DISPLAY。
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x DISPLAY=":0"
缺少 DBUS_SESSION_BUS_ADDRESS 并非看不见图片,而是延迟,所以环境变量缺少的后果可能并非那么直观。

最后,crontab 的默认环境变量可能会影响,且 env -i 并非完全没有环境变量,你必须考量这种可能性。

No comments:

Post a Comment