[2026-09-26 09:55:33] taiga-vault: family/how-to/vault-git-sync.md family/documents/vault-sync/2026-09-26-commit-skip-pipefail.md
This commit is contained in:
1 parent
041885fac9
commit
0daf3ae630
2 files changed
+111
No files matched your search
@@ -0,0 +1,101 @@
|
||||
---
|
||||
title: sync-vault-lib.sh — pipefail + grep -q молча пропускал коммиты (492 файла застряли)
|
||||
type: log
|
||||
namespace: family
|
||||
tags: [vault, sync, git, sync-script, pipefail, bug, fixed]
|
||||
date: 2026-09-26
|
||||
---
|
||||
|
||||
# `git status --porcelain | grep -q .` под `set -o pipefail` = коммиты молча не создаются
|
||||
|
||||
**Когда:** 2026-09-26 09:53 UTC, найдено и починено в cron-тике Taiga.
|
||||
**Статус:** **фикс применён** (`/opt/data/sync-vault-lib.sh`), синк проверен.
|
||||
|
||||
## Симптом
|
||||
|
||||
Каждый тик печатал `Pushed ✓` ×3 и `Already up to date.`, exit 0, три SHA равны —
|
||||
но рабочий каталог `/obsidian-syncthing` **не очищался**, и в нём накопилось
|
||||
**492 изменения**, включая реальную правку пользователя:
|
||||
|
||||
- 491 файл — смена режима `100644 → 100755` (класс «mode-flip», см.
|
||||
`2026-09-26-mode-flip-644-755.md`), включая папки `personal/` 199, `family/` 166, `work/` 108;
|
||||
- `personal/plans/music-tags-review/1-needs-decision.md` — 4 чекбокса `- [ ]` → `- [x]`
|
||||
(пользователь отмечал разобранные треки, вероятно с телефона).
|
||||
|
||||
То есть правки телефона **не доезжали до bare**, пока в клоне было мало изменений —
|
||||
коммит делался; как только изменений становилось много, коммит перестал создаваться вообще.
|
||||
|
||||
## Причина
|
||||
|
||||
В `/opt/data/sync-vault-lib.sh`:
|
||||
|
||||
```bash
|
||||
set -euo pipefail
|
||||
...
|
||||
if git status --porcelain | grep -q .; then # ← вот это
|
||||
git add -A 2>/dev/null || true
|
||||
...
|
||||
git commit ... || true
|
||||
else
|
||||
true # ← «нечего коммитить», молча
|
||||
fi
|
||||
```
|
||||
|
||||
`grep -q` выходит сразу после первого совпадения. При большом выводе `git status`
|
||||
(492 записи ≈ **23 КБ**) он продолжает писать в уже закрытый pipe, получает `SIGPIPE`,
|
||||
и **`pipefail` объявляет весь pipeline упавшим (exit 141)**. `if` уходит в `else` —
|
||||
ветка коммита не выполняется вообще. Ошибка полностью безмолвная: stderr у
|
||||
`add`/`commit` погашен, `Pushed ✓` печатается как ни в чём не бывало.
|
||||
|
||||
Порог — размер вывода: у коммита из 2 файлов (09:44:37) условие было истинным,
|
||||
у 492 файлов — ложным.
|
||||
|
||||
**Доказательство (воспроизведение):**
|
||||
|
||||
```bash
|
||||
cd /obsidian-syncthing
|
||||
bash -c 'set -euo pipefail; if git status --porcelain | grep -q .; then echo IF=TRUE; else echo IF=FALSE; fi'
|
||||
# → IF=FALSE (492 записи)
|
||||
bash -c 'set -eu; if git status --porcelain | grep -q .; then echo IF=TRUE; else echo IF=FALSE; fi'
|
||||
# → IF=TRUE (то же состояние, без pipefail)
|
||||
```
|
||||
|
||||
## Фикс
|
||||
|
||||
```bash
|
||||
STATUS="$(git status --porcelain 2>/dev/null || true)" # подстановка не даёт SIGPIPE
|
||||
if [ -n "$STATUS" ]; then
|
||||
git add -A 2>/dev/null || true
|
||||
MSG="$(printf '%s\n' "$STATUS" | awk 'NF{n++; if(n<=25) printf "%s ", $2} END{if(n>25) printf "(... +%d more)", n-25}' || true)"
|
||||
git commit -m "[$STAMP] $LABEL: $MSG" 2>/dev/null || true
|
||||
fi
|
||||
```
|
||||
|
||||
Две правки в одном месте:
|
||||
|
||||
1. **условие** через `$( )` вместо `| grep -q` — нет пайпа, нет SIGPIPE;
|
||||
2. **сообщение коммита** собирается одним `awk` (читает вход целиком) — раньше при массовом
|
||||
flip в сообщение и в `/tmp/vault-sync.log` попадали все ~500 путей; теперь первые 25 + `(... +N more)`.
|
||||
⚠️ Не заменять на `awk ... | head -25 | tr ...`: `head` рвёт пайп, `awk` получает SIGPIPE,
|
||||
подстановка падает под `set -e` — тик завершается `exit 141` (проверено, первая версия фикса
|
||||
так и падала).
|
||||
|
||||
## Проверка после фикса
|
||||
|
||||
```
|
||||
синк: exit 0, Pushed ✓ ×3
|
||||
bare = /vault = /obsidian-syncthing = 041885fa
|
||||
git status --porcelain пуст в обоих клонах, маркеров конфликта 0
|
||||
Push failed 0, Fetch failed 4 (все исторические, тик 09:40 до origin-guard)
|
||||
safe.directory 3 записи (без дублей), insteadOf 2 (без дублей)
|
||||
коммит 12a7566e: 492 файла, сообщение "... (+467 more)"
|
||||
чекбоксы [x] в bare HEAD и в /vault = 8 → правка телефона доехала
|
||||
```
|
||||
|
||||
## Связанное
|
||||
|
||||
- `2026-09-26-syncthing-clone-origin-url-flip.md` — flip `origin` в клоне (guard уже вшит)
|
||||
- `2026-09-26-syncthing-clone-root-objects-acl-confusion.md` — root-объекты и ACL (разбор
|
||||
другой сессии, решения за Alex): там же симптом «документ не доехал до телефона»
|
||||
- `2026-09-26-mode-flip-644-755.md` — откуда берутся `100644 → 100755`
|
||||
- `family/how-to/vault-git-sync.md`, skill `vault-sync-infrastructure`
|
||||
@@ -89,6 +89,16 @@ tags:
|
||||
>
|
||||
> **STATE 2026-09-04:** починена потеря git identity в контейнере Taiga (слетела при рекреации после crashloop 09-02) — коммиты молча не проходили ~1.5 суток, изменения телефона не доезжали до bare. Фикс: `sync-vault.sh` теперь идемпотентно ставит `user.name "Taiga"` / `user.email "taiga@hermes"` при каждом запуске. Накопленное закоммичено (`2b45264`). Подробно: `family/documents/vault-sync/2026-09-04-git-identity-loss-silent-commit-failure.md`.
|
||||
>
|
||||
> **STATE 2026-09-26 — `pipefail` + `grep -q` молча отменял коммиты в `sync-vault-lib.sh`.** При большом
|
||||
> числе изменений (492 файла ≈ 23 КБ вывода) `git status --porcelain | grep -q .` падал по `SIGPIPE`
|
||||
> (grep выходил после первого совпадения, git дописывал в закрытый pipe), `set -o pipefail` объявлял
|
||||
> pipeline упавшим (exit 141) → ветка `else` → **коммит не создавался вообще**, при этом тик печатал
|
||||
> `Pushed ✓` ×3 и exit 0. Так застряли 491 mode-flip и правка телефона (`1-needs-decision.md`, 4 чекбокса
|
||||
> `[x]`). Фикс: условие через `STATUS="$(git status --porcelain)"` + `[ -n "$STATUS" ]`, сообщение
|
||||
> коммита — одним `awk` (первые 25 путей, дальше `(... +N more)`). ⚠️ `awk | head -25` в подстановке
|
||||
> даёт тот же SIGPIPE → тик падает с exit 141, так делать нельзя. Проверено: коммит `12a7566e` (492 файла),
|
||||
> три SHA равны, `git status` пуст. Разбор: `family/documents/vault-sync/2026-09-26-commit-skip-pipefail.md`.
|
||||
>
|
||||
> **⛔ НОВАЯ проблема 2026-09-02 (не решена):** оба **Taiga-клиента** (`/storage/obsidian` и `/storage/obsidian-syncthing`) **отстали на месяц** — HEAD `ceea848` (2026-08-01) vs bare repo `2fab879` (2026-09-02). Причина: контейнер `hermes-taiga` в **crash-loop** (16339 рестартов) — `uv run hermes gateway run` не может докачать депы (pytz/markdown-it-py) с PyPI, т.к. весь HTTP идёт через **мёртвый `socks5://vless-proxy:1080`**, а `UV_CACHE_DIR=/tmp/uv-cache` пустеет на каждом рестарте. Taiga 3-phase sync (крон внутри агента) не выполняется => телефон видит устаревший vault. Подробно: `family/documents/vault-sync/2026-09-02-hermes-taiga-crashloop.md`. Фикс НЕ применён (ждёт Alex).
|
||||
|
||||
> **Триггер cron на маке (Eagle) — это launchd, НЕ Hermes cron:** `~/Library/LaunchAgents/com.sync-vault.plist` → `/Users/admin/scripts/sync-vault.sh`, `StartInterval=300` (5 мин). Скрипт `sync-vault-lib.sh` намеренно глушит dead remote (`git fetch` fail → `exit 0`), поэтому launchd показывает `last exit code = 0` даже при фактически стоящем sync. Системный crontab на маке пуст.
|
||||
|
||||
Reference in new issue
Block a user