第一次发帖,请多多包涵:)
我正在编写我的第一个 BASH 脚本,并使用 systemd 在计时器上调用它(也是我的第一个 systemd 单元!)。该脚本每天运行备份,并使用通知发送将通知发送到我的桌面。
我想将一些额外的日志记录定向到journalctl,但仅限于某些特定的单个命令。我用了 2>&1:
df -h | grep --color=never /mnt/Backups 2>&1
但是当我这样做时,无论备份成功还是失败,通过通知发送的桌面通知都会显示“成功”(systemd 完成正常)。我已经测试过删除 2>&1 和 notification-send 为我提供了脚本的 Borg 操作部分的正确通知建议(成功和失败都经过测试)。
那么 - 我如何开始然后停止该重定向,让它显示在journalctl中,并准确显示我的通知?
这是我的脚本的一部分:
df -h | grep --color=never /mnt/Backups 2>&1
SUCCESS=$?
echo $SUCCESS
## Use DESTOP Notifications.
if [ "${SUCCESS}" = "0" ]; then
notify-send -a Borg 'Operation was successful!' '~/.local/bin/borg-backup.sh' -u normal -i checkbox-checked-symbolic
else
notify-send -a Borg 'Operation was *NOT* successful' '~/.local/bin/borg-backup.sh' -u critical -i dialog-error
exit 1
fi
谢谢 :)
答案1
首先,我假设您希望 grep 的输出发送到 stderr? 2>&1 将 stderr 重定向到 stdout。您可能需要 grep 1>&2。
其次,重定向仅适用于该单个命令。它不会持续存在,因此启动和停止重定向不是问题。
第三,我没有得到:“成功”(systemd 完成得很好)。您所测试的只是 df -h 的输出提到 /mnt/Backups。其他一些事情可能会破坏这个过程。
第四,管道中进程的状态有时是意想不到的。每个进程的状态都记录在数组 PIPESTATUS 中。整个管道的状况很复杂。特别是,带有重定向的管道可以在子 shell 中执行(因此主 shell 保持其流不变)。在这种情况下,我准备相信您的成功与子 shell 本身的退出状态有关,而不是与管道中的最后一个命令有关。
我对这些东西很模糊,因为我对它不够信任,无法自己使用它。我对此的看法是检查文本,而不是状态,例如:(未经测试):
MOUNT="$( df -h | grep --color=never /mnt/Backups )"
echo 1>&2 "Mount test gets ${MOUNT:-Nothing}"
if [[ "${MOUNT}" = "/mnt/Backups" ]]; then ...
这种东西很难诊断。我正在学习使用RC=$?
保存命令状态、echo $?
显示命令状态、declare -p PIPESTATUS
显示状态数组和RP="$( declare -p PIPESTATUS )"
保存状态数组。
问题是所有这四个(包括对变量的赋值)也是命令,并导致状态重置为零。因此,您永远无法通过多个途径看到您的初始命令状态。状态是短暂的,数据是永恒的。
我最好的机制是让 grep 计算与 的匹配项grep -c
,并将返回的计数保存在变量中。您不必丢弃文件名,因为如果 grep 读取标准输入,它不会输出名称。
作为大文件的改进,请使用grep -l
.当它看到第一个匹配项时退出(grep -c
必须继续计数到最后)。grep -l
输出包含匹配项的文件名,因此测试针对""
, 或"(standard input)"
。