Узнавать, когда длинная команда в терминале закончилась

Хватит сидеть над сорокаминутной сборкой. Одна строка после любой команды отправит результат на телефон — в том числе если вы уже ушли.

Обновлено

Содержание

Вы запускаете обучение, полный набор тестов, docker build или ИИ-агента на длинную задачу. Дальше остаются два плохих варианта: сидеть и смотреть на полосу прогресса или уйти и вернуться через двадцать минут, чтобы узнать, что всё упало на девяностой секунде.

Есть третий вариант, и он занимает одну строку.

Та самая строка

Создайте канал в Echobell, скопируйте его webhook-URL и допишите это после того, что запускаете:

pnpm build; curl -sS -X POST https://hook.echobell.one/t/ВАШ_ТОКЕН \
  -H 'content-type: application/json' \
  -d '{"title":"сборка завершена","body":"echobell-web"}'

Обратите внимание: ;, а не &&. С && уведомление уходит только при успехе, а это ровно наоборот — сбой как раз тот случай, о котором хочется узнать.

Отправляйте и код возврата

Уведомление «готово» рассказывает половину истории. Захватите статус:

pnpm build; s=$?; curl -sS -X POST https://hook.echobell.one/t/ВАШ_ТОКЕН \
  -H 'content-type: application/json' \
  -d "{\"title\":\"сборка $([ $s -eq 0 ] && echo ok || echo СБОЙ)\",\"status\":\"$s\"}"

s=$? должно идти сразу после команды: что угодно между ними, включая сам тест [, перезапишет $?.

Сделайте из этого функцию shell

Набирать такое каждый раз бессмысленно. Положите в ~/.zshrc или ~/.bashrc:

notify() {
  "$@"
  local status=$?
  curl -sS -X POST "$ECHOBELL_HOOK" \
    -H 'content-type: application/json' \
    -d "{\"command\":\"$*\",\"status\":\"$status\",\"host\":\"$(hostname -s)\"}" \
    >/dev/null
  return $status
}

Задайте ECHOBELL_HOOK в профиле оболочки — а лучше держите его вообще вне репозитория с дотфайлами и экспортируйте из файла, который не коммитите. Дальше:

notify pnpm test
notify cargo build --release
notify python train.py

Завершающее return $status важно: оно делает notify прозрачным, так что notify make && ./deploy.sh ведёт себя так, как вы ожидаете.

С таким payload шаблоны канала могут быть такими:

Заголовок

{{command}} · {{status}}

Текст

на {{host}}

Звоните только при сбое

Большинство запусков проходит успешно, и слышать о них не нужно. Два канала решают это чисто: обычный для всего и звонящий с условием:

status != "0"

Направьте notify во второй канал для того, ради чего вы встанете с кровати, и успешные запуски останутся беззвучными.

Пережить закрытый ноутбук и оборвавшуюся SSH-сессию

Если команда идёт по SSH, закрытый ноутбук убивает оболочку, и уведомление не уйдёт никогда. Два решения:

tmux — запустите команду внутри сессии и отсоединитесь:

tmux new -d -s build 'notify pnpm build'

nohup — для разового случая:

nohup bash -c 'notify pnpm build' >/dev/null 2>&1 &

В обоих случаях процесс переживает ваше соединение, и уведомление приходит независимо от того, подключены вы или нет.

ИИ-агенты для кода

Та же схема покрывает CLI-агента, занятого длинной задачей:

notify codex exec "отрефактори модуль платежей и прогони тесты"

Для агентов, которые останавливаются посреди работы и ждут человека — согласование, запрос разрешения — уведомление о завершении не тот инструмент, ведь запуск не завершён. Этому случаю нужен собственный хук или колбэк агента, и он заслуживает скорее звонка, чем push. Как превратить согласования агента в телефонные звонки разбирает именно это, включая хук Notification в Claude Code и его матчер agent_needs_input.

Используйте оба: хук для «я застрял», функцию shell для «я закончил».

Чего не стоит класть в уведомление

Не вывод команды. Соблазнительно засунуть последние строки упавшей сборки в текст. Не надо: в логах сборки токены, строки подключения и клиентские данные встречаются чаще, чем принято думать, а текст уведомления оказывается на заблокированном экране. Отправьте код возврата и идите смотреть терминал.

Не URL канала — в публичный репозиторий дотфайлов. Любой, у кого есть URL, может писать в ваш канал. Держите его в файле вне версионирования и включите Только POST, чтобы случайный предпросмотр ссылки его не запустил.

Частые вопросы

Почему не terminal-notifier или notify-send?

Они показывают уведомление на машине, где идёт команда. Это работает, пока вы сидите рядом. Смысл этой схемы — как раз в случае, когда не сидите: удалённая машина, закрытый ноутбук, другая комната.

Работает ли это в Windows?

Схема да, синтаксис другой. В PowerShell эквивалент — Invoke-RestMethod -Method Post -Uri $env:ECHOBELL_HOOK -ContentType application/json -Body $json, а вместо $? используется $LASTEXITCODE.

Придёт ли уведомление на часы?

Да. Подписки доставляются на сопряжённые Apple Watch, и для «сборка готова» это, честно говоря, самый уместный формат.

А если команда идёт 12 часов?

В этой схеме ничего не истекает: curl выполнится, когда команда вернётся. Запускайте под tmux, чтобы обрыв связи не утащил процесс за собой.

Могут ли коллеги получать те же уведомления?

Да. Поделитесь каналом, и каждый подписчик выберет свой тип уведомления. Удобно на общей машине для обучения, где не одному человеку важно, что GPU снова свободен.

Итог

Одна функция shell, один канал и условие, если нужны только сбои. Настройка занимает пару минут и возвращает те двадцать, что уходят на разглядывание полос прогресса.

Скачайте Echobell для iPhone или возьмите в Google Play, а потом попробуйте на чём-нибудь достаточно долгом, чтобы отойти.


Связанные материалы