Skip to content

audit-texlive-tags.sh cannot tell a grep failure from zero matches #173

Description

@toshi0806

判断すること

audit-texlive-tags.sh の grep 呼び出しで、起動失敗を 0 件と区別するかどうか。

訂正: 当初この issue は「macOS で動かない(xargs -r が BSD にない)」として起票しましたが、誤りでしたxargs -r は macOS でも動きます。また PCRE 非対応の環境はスクリプト冒頭のチェックが正しく弾きます。残る論点は 2>/dev/null の 1 点だけなので、そこに絞って書き直しました。

現状の整理

grep の呼び出しが 2 箇所とも標準エラーを捨てています。

# 133 行目
| xargs -0 -r grep -EoHn "${image}:[A-Za-z0-9._-]+" 2>/dev/null \

# 142 行目
git ls-files -z | xargs -0 -r grep -oHnP "$pattern" 2>/dev/null || true

grep の終了コードは 3 種類あります。

code 意味 扱い
0 マッチあり 正常
1 マッチなし 正常。監査では「drift なし」
2 エラー(オプション不正、ファイル読めない等) 異常だが、いまは 1 と同じ扱い

2 が 1 に化けます。 grep が起動すらできなくても hits が空になり、監査は ok を出します。

実際に踏みました

#172extra_patterns の追加)の検証中の出来事です。正しいパターンを書いたのに 0 件が返り、パターン側の問題だと思い込んで切り分けに手間取りました。

$ git ls-files | xargs grep -oHnP '<正しいパターン>' 2>/dev/null
(0 件)

$ grep -oHnP '<同じパターン>' Dockerfile CHANGELOG.md
Dockerfile:8:2026e
CHANGELOG.md:6:2026d
CHANGELOG.md:11:2026a

2>/dev/null を外して初めて理由が見えました。

grep: invalid option -- P

原因は環境固有のもの(シェル関数として定義された grep が -P を通す一方、xargs が PATH から解決した /usr/bin/grep は BSD grep で通さない)でしたが、問題はそこではありません。エラーが出ていたのに、それが「一致しています」という結果として返ってきたことです。

なぜ問題か

監査の目的は上げ忘れの検出です。検出器が壊れているときに「異常なし」と答えるのは、最も避けたい失敗の形です。

同じ scripts/ 配下の audit-repo-protection.sh には、まさにこの配慮を書いたコメントがあります。

cd の失敗は握り潰さない。空の結果は「一致している」と区別が付かず、何も見ていない監査が ok を出すことになる

audit-texlive-tags.shcd "$repo_dir" || exit 1 にも同じ趣旨のコメントがあります。設計思想としては既に存在していて、grep の呼び出しにだけ及んでいません。

これは macOS 固有の話ではありません。Linux 上でも、権限やファイル名の問題で grep が 2 を返せば同じことが起きます。

選択肢

A. 終了コードを見て 2 を異常として扱う(推奨)

set +e
hits=$(cd "$repo_dir" && git ls-files -z | xargs -0 -r grep -EoHn "..." 2>&1)
rc=$?
set -e
if [ "$rc" -gt 1 ]; then
    log "  ERROR: ${name} — grep が失敗した: $(printf '%s' "$hits" | head -1)"
    errors=$((errors + 1))
    continue
fi

既に errors カウンタと ERROR 行の枠組みがある(clone 失敗で使っている)ので、そこに乗せられます。xargs は最後に起動した子プロセスの終了コードを返すため、複数回起動された場合に取りこぼす可能性は残りますが、現状の「常に無視」よりは確実に良くなります。

B. 標準エラーを捨てず、そのまま出す

| xargs -0 -r grep -EoHn "..." \

2>/dev/null を消すだけ。エラーはログに出ますが、終了コードは相変わらず区別されないので、気付けるかどうかは人の目次第です。1 文字の変更で済む代わりに保証は弱くなります。

C. 現状維持

実運用は GitHub Actions で、そこでは PCRE も揃っており、これまで問題は起きていません。

補足

|| true(142 行目)も同じ方向の問題を持ちます。set -eu の下でマッチなし(1)を通すために必要ですが、2 も一緒に通しています。A を採るなら、この || true は終了コードの判定に置き換わります。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions