使用说明
Shell、PowerShell 与备份完成后,通知手机
为 Shell、PowerShell、备份与定时任务发送手机通知。保留任务退出码,单独检查通知受理、实际接收与失败。
更新于
先选公开通知、HTTPS,还是加密脚本通知
#已有公开 Topic 可以免配对发送无敏感信息的通知;私有 HTTPS 链接适合服务 Webhook,服务端读取输入后加密投递。下方脚本使用受保护 Topic:先用运行任务的同一用户配对 CLI,发送端本地加密消息。不要把私有日志原文发送到公开 Topic。
准备受保护脚本通知
#在 Windows、macOS 或 Linux 安装当前 CLI,并用运行任务的同一用户与手机配对。Android 推送需要 Google Play 服务。运行 ntfyx topics 找到本地别名;示例中的 Work 要替换成自己的别名。已有公开 Topic 或私有 HTTPS 链接也能发普通通知,区别见模式选择。
ntfyx version --json
ntfyx topics
ntfyx send "Build finished. Ready to review." --title "Build complete" --topic WorkShell:下载并阅读完整包装脚本
#这个小脚本原样运行传入命令一次,然后发送通用退出状态。它不发送命令参数或终端输出。先阅读下载文件,再用无害任务试一次;不能把 CLI 受理结果当作手机已经显示。
curl -fsSLo notify-after.sh https://ntfyx.me/examples/scripts/notify-after.sh
cat notify-after.sh
bash notify-after.sh Work bash -c 'printf "Example job finished\n"'验证失败退出码仍然保留
#下面任务故意退出 7。包装脚本应仍退出 7;即便通知发送失败,也只追加警告,不覆盖任务结果。每次测试后在手机对应 Topic 核对消息。
| 任务结果 | 通知结果 | 包装脚本退出码 |
|---|---|---|
| 成功 0 | 已受理 | 0 |
| 失败 7 | 已受理 | 7 |
| 失败 7 | 未确认 | 7,并显示警告 |
| 成功 0 | 未确认 | 0,并显示警告 |
bash notify-after.sh Work bash -c 'exit 7'
printf "Original command exit: %s\n" "$?"Linux cron:与手动运行保持同一身份
#cron 的环境较少。使用已配对用户的 crontab,明确 PATH 与所有绝对路径,把结果留在本机日志。先手动运行完全相同的命令。下方每天 09:00 运行一次无害任务,时区由原调度器决定;替换 YOUR_USER 与文件路径后再自行加入。macOS 沿用现有 launchd 调度。
PATH=/home/YOUR_USER/.local/bin:/usr/bin:/bin
0 9 * * * /bin/bash /home/YOUR_USER/notify-after.sh Work /bin/true >> /home/YOUR_USER/ntfyx-job.log 2>&1缺失通知与验证范围
#原有 shell 示例已在本地加密中继与 Web 接收端验证;这不是实体 iPhone、Android 或推送服务的送达证明。脚本退出、服务端受理和手机显示要分别观察。先完成一次自己的成功与失败演练,再接入日常任务。
Windows PowerShell:完整的退出通知脚本
#将下方保存为 notify-after.ps1,以已配对的 Windows 用户运行。它只包装原生可执行文件,运行一次任务后保存 $LASTEXITCODE,再单独发送通知。PowerShell 业务脚本要通过 powershell.exe 或 pwsh.exe -File 启动,并自己明确返回退出码。通知失败不能把任务失败改成成功;未能启动任务返回 127。命令参数和输出留在本机,不发送到手机。
# Save as notify-after.ps1. Runs a native executable once.
param(
[Parameter(Mandatory=$true)][string]$Topic,
[Parameter(Mandatory=$true)][string]$TaskExecutable,
[string[]]$TaskArguments = @(),
[string]$Ntfyx = 'ntfyx'
)
# Nonzero native exits are job results, not PowerShell exceptions.
$PSNativeCommandUseErrorActionPreference = $false
$ntfyxJobStatus = 127
try {
$ntfyxTask = Get-Command $TaskExecutable -CommandType Application -ErrorAction Stop
& $ntfyxTask.Source @TaskArguments
$ntfyxJobStatus = $LASTEXITCODE
} catch {
[Console]::Error.WriteLine('Task could not start; status 127.')
}
$ntfyxTitle = if ($ntfyxJobStatus -eq 0) { 'Task finished' } else { 'Task failed' }
try {
$ntfyxCommand = Get-Command $Ntfyx -CommandType Application -ErrorAction Stop
& $ntfyxCommand.Source send "Task exited with status $ntfyxJobStatus. Check the local log." --title $ntfyxTitle --topic $Topic | Out-Null
if ($LASTEXITCODE -ne 0) {
[Console]::Error.WriteLine('Notification not confirmed; job exit status is preserved.')
}
} catch {
[Console]::Error.WriteLine('Notification could not start; job exit status is preserved.')
}
exit $ntfyxJobStatus先测试成功、失败和通知失败
#在 PowerShell 运行这些无害子进程。前两次应分别返回 0 和 7;第三次故意使用不存在的通知命令,仍应返回 7 并显示通知警告。每次任务只执行一次。替换成自己的命令前,先确认手机收到相应状态。不要用 robocopy 等有特殊成功码的工具套用“非零全部失败”规则;这类工具应先按自己的语义转换结果。
.\notify-after.ps1 -Topic Work -TaskExecutable "$env:ComSpec" -TaskArguments @('/d', '/c', 'exit 0')
"Job exit: $LASTEXITCODE"
.\notify-after.ps1 -Topic Work -TaskExecutable "$env:ComSpec" -TaskArguments @('/d', '/c', 'exit 7')
"Job exit: $LASTEXITCODE"
.\notify-after.ps1 -Topic Work -TaskExecutable "$env:ComSpec" -TaskArguments @('/d', '/c', 'exit 7') -Ntfyx 'missing-ntfyx-test.exe'
"Job exit: $LASTEXITCODE"Windows 任务计划程序:固定身份与路径
#调度器不会继承交互终端的完整环境。在同一已配对账户下运行,使用 CLI、包装脚本和业务脚本的绝对路径,并在任务操作中设置工作目录。下面是 runner.ps1 示例,把 YOUR_USER 与业务路径替换成自己的真实路径。计划程序的“程序”填 powershell.exe 的完整路径,“参数”填 -NoProfile -File "C:\Jobs\runner.ps1",“起始于”填 C:\Jobs。按原系统策略允许脚本执行,不使用绕过策略参数;先手动执行同一操作,再查看任务历史和上次运行结果。
# C:\Jobs\runner.ps1; task.ps1 must exit with its own result.
$ntfyxRun = @{
Topic = 'Work'
Ntfyx = 'C:\Users\YOUR_USER\AppData\Local\Ntfyx\bin\ntfyx.exe'
TaskExecutable = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
TaskArguments = @('-NoProfile', '-File', 'C:\Jobs\task.ps1')
}
& 'C:\Jobs\notify-after.ps1' @ntfyxRun
exit $LASTEXITCODE备份:报告退出码,再单独验证可恢复
#把已经检查过的 notify-after.sh 放在任务目录。下面 runner 接受源目录与新的归档文件路径,只运行一次 tar,并原样返回备份退出码。目标文件必须不存在;独占创建输出,避免并行任务覆盖既有备份。失败可能留下部分归档,不能当作可用备份。先用临时样本目录演练;成功通知只表示 tar 返回 0,不证明备份内容完整或能够恢复。用自己的备份工具时保留它的退出语义,恢复演练放在单独临时目录。
#!/usr/bin/env bash
# Save beside notify-after.sh as backup-run.sh.
set -u
if [ "$#" -ne 3 ]; then
printf 'Usage: bash backup-run.sh TOPIC SOURCE_DIR NEW_ARCHIVE\n' >&2
exit 2
fi
ntfyx_topic="$1"
ntfyx_source="$2"
ntfyx_archive="$3"
if [ ! -d "$ntfyx_source" ] || [ -e "$ntfyx_archive" ] || [ -L "$ntfyx_archive" ]; then
printf 'Use an existing source directory and a new archive path.\n' >&2
exit 2
fi
ntfyx_script_dir="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" || exit 2
set -C # Refuse an existing output during redirection, including a racing writer.
bash "$ntfyx_script_dir/notify-after.sh" "$ntfyx_topic" \
tar -czf - -C "$ntfyx_source" . > "$ntfyx_archive"
ntfyx_backup_status=$?
exit "$ntfyx_backup_status"完成自己的自动化任务
#从可复制的完整示例开始,核对任务结果、发送回执和手机消息。通知成功与原任务成功分别判断。