2P by GN⁺ | ★ favorite | 댓글 3개
  • 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년 트윗에서 man을 00:01에 실행하면 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년이면 충분히 오래 지속됐다고 판단함

댓글과 토론

이런 류의 이스터에그를 넣을거라면 표준입출력이 TTY인지 한 번 검사하는 것도 좋은 방법이죠. 셸스크립트라면 [[ -t 1]]로 검증 가능합니다.

man이 남성으로 번역됐군요ㅎㅎ

Hacker News 의견들
  • 예전에 원격진료가 지금처럼 대중화되기 전 원격진료 웹앱을 만들었고, 환자가 온라인 설문을 작성하면 의사가 답을 보는 기능이 있었음
    여러 진료과를 온보딩하면서 질문 표시 여부를 조건부로 제어하는 꽤 강력한 로직이 있었는데, 새 정신과 클리닉 기능을 작업하다가 보여야 할 질문이 안 보여서 디버깅 중 질문 옆에 말도 안 되고 약간 화난 디버그 문구를 잔뜩 넣었음
    문제를 고치고 정리했다고 생각했지만, 특정 답변 조합에서 큰 빨간 글씨로 I SEE YOU!!! 가 뜨는 문구를 하나 남겼고, 그걸 새로 열린 정신과 클리닉의 편집증 평가 설문을 작성하던 환자가 발견함
    그 뒤로 디버그 표식은 aaa111 같은 걸 쓰기 시작했음

    • Google에서 디버깅용 문자열에는 DO NOT SUBMIT을 넣도록 되어 있었고, 디버그 문자열이 운영 환경에 나간 뒤 이를 검사하는 봇이 추가됐음
      그 전설적인 WD 사건 이후였던 것으로 기억하는데, 테스트 코드에서 “western digital”이 “woodly doodly”로 바뀌었다가 실수로 배포된 일이 있었음
    • 예전에 도박 사이트에서 사람들이 특수한 파일로 베팅을 대량 업로드할 수 있는 기능을 만들 때 비슷한 일을 했음
      개발 중 아주 특정한 상황에서만 깨졌고 로컬 개발 환경에만 해당하는 이상한 조건처럼 보여서, “watch and amaze while the application eats itself!” 같은 오류 메시지를 넣었음. 원래 PlayStation용 Discworld 게임에서 본 오류에서 영감을 받은 문구였음
      그런데 운영에 올라가자 그 오류를 유발하는 조건이 생각보다 덜 특수했고, 돈이 사라진 줄 알고 전화한 수백 명 때문에 고객지원이 마비됨. 이 기능을 쓰는 사람들은 큰돈을 거는 고액 베터들이라 경영진도 전혀 좋아하지 않았음
      다행히 해고되지는 않았고 빠르게 고쳤지만, 칼날이 목 가까이 온 느낌이었음. 거의 20년 전 첫 직장 중 하나에서 그 주에 값진 교훈을 제대로 배웠음
    • 이 파일에 오래 남겨둔 주석이 있었는데, 프로젝트 리드가 꽤 프로페셔널한 사람이라 지워버렸음. 주석은 # 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임. 아주 특정한 하위 시스템을 작업하는 개발자만 찾을 수 있지만, 발견하면 문맥상 왜 거기 있는지 알 수 있음
    • 누군가에게는 재밌는 이스터 에그가, 다른 누군가에게는 자기 작업 흐름에서 실제 결과를 낳을 수 있는 비결정적 오동작 트리거가 될 수 있음
      생명 안전이나 임무 필수 애플리케이션에 서로 다른 공학 프로세스를 가진 여러 조각을 통합한 소프트웨어를 신뢰하기 어려운 이유가 또 하나 늘어남
  • 이제는 더 이상 들어 있지 않음
    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 --abba --format=json
      ["gimme", "gimme", "gimme"]
    • 제거됐음. 참고: https://news.ycombinator.com/item?id=41738239
  • 이 업데이트 때문에 내 작업 흐름이 깨졌음

    • 이 업데이트 덕분에 내 작업 흐름이 고쳐졌음. 자정 넘어서 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 길이로 판단하는 건 늘 불안정함