2 ポイント 投稿者 GN⁺ 2024-10-05 | 3件のコメント | WhatsAppで共有
  • 00:30にだけ自動テストが失敗した理由は、man -w が想定外の stderr文字列 gimme gimme gimme を一緒に出力したため
  • この文字列は manイースターエッグで、マニュアルページを指定せずに実行するか -w を使うと、ローカル時刻が00:30のときに現れる
  • 文句は ABBA の「Gimme! Gimme! Gimme! (A Man After Midnight)」に由来し、2011年のツイートの冗談が man-db のコードに反映された
  • man -w は manpath を出力し、終了コードも 0 のため自動化に使えたが、イースターエッグの出力がパースを壊す可能性があった
  • man-db はまず man -w で発動しないように修正し、その後 man-db 2.8.0 でイースターエッグを完全に削除することにした

00:30にだけ失敗するテスト

  • 自動テストはほとんどの時間では正常に動作していたが、00:30 に実行されたときだけ失敗した
  • 直接の原因は、stderr に想定していない文字列が追加されたことだった
gimme gimme gimme
  • テストで使っていたコマンドは man -w で、現在の manpath を取得するための用途だった

man に入っていたイースターエッグ

  • 問題の文字列は man コマンドに入っていた イースターエッグだった
  • 発動条件は次のとおりだった
    • マニュアルページを指定せずに man を実行する
    • または man -w を実行する
    • ローカル時刻が 00:30 である
  • 条件がそろうと stderrgimme gimme gimme が出力された
# date +%T -s "00:30:00"
00:30:00


# man -w
gimme gimme gimme
/usr/local/share/man:/usr/share/man:/usr/man
  • この場合でも終了コードは 0 のままだった

本来期待される動作

  • man -w の通常の出力は、マニュアルページの検索パスだけを返すことだった
# man -w
/usr/local/share/man:/usr/share/man:/usr/man


# echo $?
0
  • ページを指定せずに man を実行した場合は、どのマニュアルページが欲しいかを尋ね、終了コード 1 を返すのが期待動作だった
# man
What manual page do you want?


# echo $?
1
  • man -w は検索パスを出力するため、マニュアルページのインストール確認やテスト自動化の構成要素として使うことができた

コードとディストリビューションへの影響範囲

  • 該当文字列は RHEL、OpenSUSE、Fedora、Debian などで見つかっており、特定のディストリビューション固有の動作ではなかった
  • バイナリに対して文字列を grep し、存在有無を確認できた
  • 出力は man-dbsrc/man.c のコードで発生していた
time_t now = time (NULL);
struct tm *localnow = localtime (&now);
if (localnow &&
    localnow->tm_hour == 0 && localnow->tm_min == 30)
  fprintf (stderr, "gimme gimme gimme\n");

ABBA の曲とツイートに由来する文字列

  • gimme gimme gimme は ABBA の「Gimme! Gimme! Gimme! (A Man After Midnight)」に由来する文字列
  • Marnanel Thurman は 2011年のツイートで、00:01 に man を実行すると gimme gimme gimme を出力すべきだと冗談で提案した
  • man のメンテナーはその提案を実際のコードに入れた
  • コメントでは、最初のコミットは 00:01 に発動し、その後「half past twelve」というコミットメッセージとともに 00:30 に変更されたことが補足されている

修正と削除

  • man-db のメンテナー Colin Watson はまず、このイースターエッグが man -w では発動しないように 84bde8 コミット で修正した
  • その後 Colin Watson は、イースターエッグを完全に 削除するコミット を適用した
  • 削除されたイースターエッグは予定されていた man-db 2.8.0 でなくなる見込みだった
  • メンテナーは、このイースターエッグは一部の人には笑いを与えた一方で、別の人には煩わしく、6年もあれば十分長く続いたと判断した

3件のコメント

 
tribela 2024-10-07

こういう類いのイースターエッグを入れるのであれば、標準入出力が TTY かどうかを一度確認するのもよい方法です。シェルスクリプトなら [[ -t 1]] で確認できます。

 
y15un 2024-10-05

man が「男性」と訳されてしまったんですね(笑)

 
GN⁺ 2024-10-05
Hacker Newsのコメント
  • 以前、遠隔診療が今ほど一般化する前に遠隔診療Webアプリを作っていて、患者がオンラインのアンケートに回答すると医師がその回答を見る機能があった。
    複数の診療科をオンボーディングする中で、質問の表示有無を条件付きで制御するかなり強力なロジックがあったのだが、新しい精神科クリニック向け機能を作業中、表示されるべき質問が出てこなかったので、デバッグ中に質問の横へ支離滅裂で少し怒ったようなデバッグ文言を大量に入れた。
    問題を直して片付けたつもりだったが、特定の回答の組み合わせで大きな赤文字の**I SEE YOU!!!**が表示される文言を1つ残してしまい、それを新しく開設された精神科クリニックの被害妄想評価アンケートに回答していた患者が見つけた。
    それ以来、デバッグの目印にはaaa111のようなものを使うようになった。

    • Googleではデバッグ用文字列にDO NOT SUBMITを入れることになっていて、デバッグ文字列が本番環境に出たあと、それを検査するボットが追加された。
      あの伝説的なWD事件のあとだったと記憶しているが、テストコードで“western digital”が“woodly doodly”に置き換わり、そのまま誤ってデプロイされたことがあった。
    • 昔、ギャンブルサイトで人々が特殊なファイルで賭けを大量アップロードできる機能を作っていたとき、似たようなことをしたことがある。
      開発中、それはごく特定の状況でしか壊れず、ローカル開発環境にしか当てはまらない奇妙な条件のように見えたので、“watch and amaze while the application eats itself!”のようなエラーメッセージを入れた。もともとはPlayStation版Discworldゲームで見たエラーに着想を得た文言だった。
      ところが本番に上がると、そのエラーを引き起こす条件は思ったほど特殊ではなく、お金が消えたと思って電話してきた何百人ものせいでカスタマーサポートが麻痺した。この機能を使う人たちは大金を賭ける高額ベッターだったので、経営陣もまったく喜ばなかった。
      幸い解雇はされず、すぐに修正したが、刃が首元まで来ているような気分だった。ほぼ20年前、最初の職場の1つでその週に本当に高い授業料の教訓を学んだ。
    • このファイルに長く残していたコメントがあったのだが、プロジェクトリードがかなりプロフェッショナルな人だったので消してしまった。コメントは# MULTIPASS!だった。
      https://github.com/workarea-commerce/workarea/blob/master/co...
      文脈はこうだ。The 5th Elementはすばらしい映画で、姉の飼い犬の名前がLeeloo Dallas Multipassで、その犬は私がいちばん好きだった犬だった。そしてProductMultipass検索クエリ機能を最初に作った開発者は私だった。
      面白いコメントは、ほかの開発者がその製品をもっと好きになる助けにもなるとわかった。
    • デバッグの目印にはたいてい自分のイニシャルとDEBUGを一緒に使う。
      コミット前にgrepで見つけやすいし、万一本番環境に入っても完全に正体不明の文字列にはならないからだ。
    • デバッグメッセージをコミットしてしまったことは間違いなくあるし、コードを書く人なら大半は一度くらいある気がする。
      幸い、そこまで恥ずかしい内容ではなかったし、今ではコミットしてプッシュする前の最後の確認として、必ずgit diffを見て、printやその言語での類似の出力を検索するようにしている。
      高校時代、友人には課題の下書きに不適切なタイトルを付ける癖があった。互いに添削しているときは笑えたが、結局一度タイトルを戻し忘れた。英語の授業で先生が課題を集めて回り始めると、友人は自分の紙を見て突然トイレに行くと言って飛び出し、コンピュータ室で最上部に24ポイントの下品な言葉がないコピーを刷り直してきた。私は笑い死にしそうだった。
  • ソフトウェアが無料で、メンテナーが報酬を受け取っていないなら、イースターエッグがいくつかあるくらいは小さな代償だと思う。
    もちろんColinは報酬を受け取っていたが、主にmanのメンテナンスの対価としてではなかった。
    昔勤めていた会社で、ある開発者が利用規約に、ユーザーが自分の魂を会社へ譲渡するという一文を入れたことがあった。経営陣や法務チームが約束どおり利用規約を確認しているか試す意図だったが、確認されず、多くの魂が捕獲された。

    • すると利用規約全体が無効になる可能性もある。
  • コーディングは楽しいものであるべきだし、コードを書くことも楽しくあるべきだ。こういう人たちはよくやったと思う。
    オープンソースは冷たく真面目であるべきだという考えは、企業が主導するようになってから生まれたにすぎない。自分が友人とプログラムを作るなら、向こう側にも人間がいると思い出せるように、あちこちにイースターエッグを入れると思う。

    • 隠されているのだから、ほとんどの人はそのイースターエッグに遭遇しない。
      遭遇する人は原文の投稿者のように偶然踏み抜くことになり、その原文では継続的インテグレーションのパイプラインが壊れていた。「向こう側にも人間がいる」と思い出させる道具としては、イースターエッグはあまりよくないと思う。
      少なくともエンターテインメント用ソフトウェアの外ではそうだ。
    • よく隠されたイースターエッグほど楽しくて満足感のあるものはあまりない。
      とくに作業対象が官僚的な手続きに囲まれているならなおさらだ。個人的にいちばん好きなのは、数年前にコンサルとして修正した政府アプリケーションのソースコードに隠しておいたRick Rollだ。非常に特定のサブシステムを作業する開発者だけが見つけられるが、見つければ文脈上なぜそこにあるのか理解できる。
    • ある人にとっては面白いイースターエッグでも、別の人にとっては自分の作業フローの中で実際の結果を生みうる非決定的な誤動作トリガーになり得る。
      生命安全やミッションクリティカルなアプリケーションに、工学プロセスの異なる複数の断片を統合したソフトウェアを信頼しにくくなる理由がまた1つ増える。
  • 今ではもう入っていない。
    man-db開発者のColin Watsonが、もう十分に面白かったし話も忘れられないだろうと判断して、イースターエッグを完全に削除した。
    https://git.savannah.gnu.org/cgit/man-db.git/commit/?id=b225...

    • このイシューの議論で、今では見つけられない美しいコメントを読んだことがある。
      こうしたイースターエッグは残しておくべきだという内容で、結局のところこういうものが人間と機械を区別してくれるのだと言っていた。
    • 古いRaspberry Piで今やってみたが、まだ残っている。Debian 9 Stretchベースだ。
  • 関連記事:
    Why does man print “gimme gimme gimme” at 00:30? (2017) - https://news.ycombinator.com/item?id=27994194 - 2021年7月、コメント211件
    Why does man print “gimme gimme gimme” at 00:30? - https://news.ycombinator.com/item?id=15747313 - 2017年11月、コメント159件
    Why does man print “gimme gimme gimme” at 00:30? - https://news.ycombinator.com/item?id=15746972 - 2017年11月、コメント1件
    Why does man print “gimme gimme gimme” at 00:30? - https://news.ycombinator.com/item?id=15742221 - 2017年11月、コメント1件

  • 面白いアイデアではあるが、通常の実行フローに入れるべきではない。ユーザーに迷惑がかかる
    元記事の投稿者が言うように、man -abbaだったならもっとよかったはず

    • 最初の返答を見ると、もともとはエラー時、つまりページを指定しなかったときだけ発動させるつもりだった
      しかし誤ってページ名ではなく--pathフラグでmanページを指定した場合にも発動してしまった
    • $ man --abba --format=json
      ["gimme", "gimme", "gimme"]
    • 削除された。参考: https://news.ycombinator.com/item?id=41738239
  • このアップデートのせいで自分のワークフローが壊れた

    • このアップデートのおかげで自分のワークフローが直った。深夜0時を過ぎてからmanが必要だったので
  • 古い電話システムを廃止する際、会社にFreePBXを導入した
    内線はそれほど多くなかったので、1xx、2xx、3xxを種類別の内線として使っても番号がかなり余っており、誰かが内線666に電話したら Michael Jackson の Thriller の最後に出てくる Vincent Price の不気味な笑い声を再生する小さなイースターエッグを入れた
    1〜2年後のある早朝、同僚から電話がハッキングされたようだというメッセージが届き、どこに電話しても不気味な声が聞こえると言っていた。確認してみると何かがおかしくなっていて、すべての通話が最後に追加した内線、666番に転送されていた
    当然ながら人々はそのイースターエッグを面白がらず、その笑い声に不快感を覚えた

  • なぜ引数なしでmanを呼び出すテストがあったのか、仮説があるのか気になる
    目的は単にmanがインストールされているか確認することなのだろうか? そうだとしても、普通はよく使うやり方でコマンドをテストする気がする

    • 返答を読むと、読み込むページを--pathで渡すときにもイースターエッグが誤って発動していたようだ
      その後この部分は修正され、さらに後になってイースターエッグ全体が削除された
    • Stack Overflow の質問自体が、別の人が公の場で自分の話をできるようにするための誘導質問だったように見える
    • リンク先の Stack Overflow 質問のコメントで詳しく触れられており、要するに manpath が欲しかったから: man -w
    • ビルドイメージが正しくインストールされていて、manが想定どおりの出力をするか確認するような自動テストだった可能性もある
  • manが正しく終了したかを判断するなら、終了コードを信頼すべきだと思う
    stderrの長さで判断するのは常に不安定だ