
Инструмент для наблюдения за сигналами ядра в реальном времени, использующий точки трассировки eBPF для потоковой передачи каждого сигнала, поданного на хосте Linux, с отображением отправителя, цели, статуса, задержки обработчика и прерываний системных вызовов.
sigwire
tail -fдля сигналов. Каждый сигнал, который генерирует любой процесс в системе — кто отправил, кому предназначен, какой сигнал, как он был вызван (kill(2), ядро, POSIX-таймер), перехватил ли его цель и как долго выполнялся обработчик, вырвал ли он заблокированный системный вызов с помощьюEINTR— декодируется из трассировочных точек ядра по сигналам и транслируется в реальном времени в ваш терминал. Безstrace -fдля одного PID, безptrace, без участия отслеживаемых процессов.
sigwire превращает механизм сигналов ядра в живую патч‑панель: каждая строка — это отправитель ──СИГНАЛ──▶ цель, окрашена по степени важности, помечена способом вызова, тем, перехватила ли цель сигнал (и как долго выполнялся обработчик), прервал ли он заблокированный системный вызов (↯ EINTR read), сворачивается в ×N при массовой отправке и отмечается ☠ когда это настоящее смертельное попадание. Боковая панель показывает статистику проходящих сигналов; поставьте на паузу и выберите строку, чтобы увидеть полную картину — диспозицию, адрес обработчика, флаги sigaction и сигналы, которые цель блокировала в этот момент.
Поскольку sigwire перехватывает трассировочные точки ядра, а не какой-то один процесс, один запуск отслеживает все сигналы на хосте одновременно — ваше приложение, супервизор, собственный механизм ошибок ядра — и ни один из них не знает, что за ним следят.
[!TIP] Две стороны каждого сигнала. sigwire отслеживает как
signal:signal_generate(взгляд отправителя — кто что вызвал, линия коммутации), так иsignal:signal_deliver(взгляд цели — перехватила ли она сигнал, с каким обработчиком и флагами, что блокировала, и прервала ли системный вызов). Ещё две точки подключения —rt_sigreturn(2)и точка выхода из системного вызова — замеряют время обработчика и перехватывают EINTR. Всё это объединяется в одну строку. Такое разделение — причина, по которой счётчик☠ fatalнамеренно консервативен (см. Что считается фатальным): генерация происходит до доставки, поэтому сторона отправителя не может знать судьбу сигнала — только сторона доставки может, и только для тех случаев, которые она наблюдает.
curl -fsSL https://yeet.cx | sh # install the yeet daemon (one time) yeet run github:yeet-src/sigwire # run the dashboard (the daemon does the privileged BPF load)
[Руководство по ручной установке](https://yeet.cx/docs/manual-installation) | только Linux
Ничего настраивать не нужно — сигналы представляют собой постоянный фоновый трафик на любом устройстве, так что строки сразу же появляются сверху. Хотите сгенерировать несколько самостоятельно? `kill -USR1 <pid>`, `Ctrl-C` фонового задания или запустите любое управляемое окружение и наблюдайте, как его сборщик мусора/планировщик отправляет сигналы собственным потокам (`↯ EINTR futex` прокручивается мимо).
## Управление
Лента по умолчанию следует за последним сигналом; выберите строку или приостановите, и она останется на месте, пока данные продолжают поступать.
| клавиша | действие |
| --- | ------ |
| `p` · `Space` | приостановить / возобновить ленту (заморозить для чтения) |
| `↑`/`↓`, `k`/`j` | приостановить и просмотреть строку — открывает панель сведений |
| `/` | нечеткий фильтр — сопоставляет процесс, pid, сигнал, источник и состояние; совпавшие символы подсвечиваются в реальном времени |
| `e` | фильтровать только **прерванные системные вызовы** (`↯ EINTR` / `↺ restarted`) |
| `s` | открыть **выбор сигналов** — отключить или показать любой сигнал в реальном времени |
| `Esc` | выйти на один уровень назад — очистить фильтр / закрыть выбор / сбросить выделение, затем выйти |
| `q` | выйти |
## Что вы видите
Каждая строка — это один сгенерированный сигнал, самый новый сверху:```
WHEN SENDER SIGNAL TARGET NOTE
now bash·4402──SIGINT───▶ node·8813 kill(2) ↯ EINTR read caught 41µs
1.2s systemd·1──────SIGTERM──▶ nginx·1291 kill(2) caught 1.2ms
3.4s kernel·8813──SIGSEGV──▶ chrome·8813 fault default ☠
4.1s postgres·507──SIGUSR1───▶ postgres·509 ×6 kill(2) caught 9µs
Каждая строка — это один блок: отправитель → цель — это comm·pid (отправитель — тот, кто подал сигнал, current; цель — кому он адресован), провод в середине содержит имя сигнала, окрашенное по степени серьёзности, ×N сворачивает пачку одинаковых сигналов в одну строку, а примечание справа указывает источник, затем — прерывание системного вызова, затем — диспозицию.
Каждая строка застывает в момент разрешения доставки и больше никогда не изменяется — поэтому пачка прокручивается как стабильный журнал, а не мерцающий агрегат.
Провод окрашен по степени серьёзности по той же 256-цветной палитре, что и остальная часть интерфейса:
| серьёзность | сигналы | цвет |
|---|---|---|
| kill | SIGKILL | ярко-красный |
| фатальные (с дампом ядра) | SEGV BUS ABRT ILL FPE TRAP SYS QUIT | красный |
| завершающие | TERM INT HUP PIPE ALRM … | янтарный |
| управление заданиями | STOP TSTP TTIN TTOU | жёлтый |
| продолжение | CONT | зелёный |
| пользовательские | USR1 USR2 | голубой |
| реального времени | SIGRTMIN+n | фиолетовый |
| служебные | CHLD URG WINCH … | серый |
Примечание — это источник (kill(2), tgkill, sigqueue, timer, kernel, fault); затем, если он прервал заблокированный системный вызов, — ↯ EINTR read (или ↺ restarted read, когда SA_RESTART автоматически возобновил его); затем диспозиция — caught 41µs (обработчик отработал, и сколько это заняло), default (нет обработчика, применено действие по умолчанию) или ⊘ ignored. ☠ отмечает настоящее смертельное попадание (см. Что считается фатальным).
[!NOTE]
↯ EINTR— за чем стоит следить. Сигнал, который приходит, пока поток застрял в медленном системном вызове (read,poll,accept,futex,nanosleep, …), выдёргивает его: системный вызов возвращает-1/EINTRи, если только обработчик не установилSA_RESTART, он не возобновляется — приложение должно повторить вызов. Забыть об этом — классическая, сводящая с ума, зависящая от времени ошибка («почему мойread()один раз не сработал?»). sigwire показывает это в реальном времени и указывает, какой системный вызов попал под удар. Нажмитеe, чтобы скрыть всё остальное и смотреть только на прерывания.
Справа находится агрегированное представление: главные сигналы по количеству, разбивка по источнику и подсчёт доставок — сколько было перехвачено, сколько привело к стандартному действию и сколько было проигнорировано.