Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 10911] ファイルの概要

このコミットは、Go言語のビルドスクリプトにおける一時ディレクトリの作成方法を修正し、特にLinux環境でのビルド問題を解決することを目的としています。mktempコマンドの挙動がOSによって異なるため、一時ディレクトリ名にテンプレート文字列(XXXXXX)を明示的に含めることで、クロスプラットフォームでの互換性と堅牢性を向上させています。

コミット

commit c037d3f25471245e7822d2b003d99b7a6ac1d1ac
Author: Russ Cox <rsc@golang.org>
Date:   Tue Dec 20 17:11:16 2011 -0500

    build: fix on Linux
    
    On other systems the temporary directory name
    will have a .XXXXXX in the middle of it.  Oh well.
    
    R=bradfitz
    CC=golang-dev
    https://golang.org/cl/5504049

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/c037d3f25471245e7822d2b003d99b7a6ac1d1ac

元コミット内容

build: fix on Linux

On other systems the temporary directory name
will have a .XXXXXX in the middle of it.  Oh well.

R=bradfitz
CC=golang-dev
https://golang.org/cl/5504049

変更の背景

Go言語のビルドシステムは、様々なオペレーティングシステム(OS)とアーキテクチャをサポートするように設計されています。ビルドプロセス中に一時的なファイルを格納するための一時ディレクトリが必要とされますが、その作成にはmktempというコマンドが利用されています。

このコミットが行われる前、mktemp -d -t go-buildという形式で一時ディレクトリが作成されていました。しかし、この形式はLinux環境において問題を引き起こしていました。mktempコマンドは、一時ファイルやディレクトリを作成する際に、指定されたテンプレート文字列の末尾にランダムな文字列を付加することで、一意性を保証します。多くのUnix系システムでは、テンプレート文字列の末尾にXXXXXXのようなプレースホルダーがない場合でも、自動的にランダムな文字列を付加してくれます。しかし、Linuxのmktempの実装では、テンプレート文字列にXXXXXXが含まれていないと、一意な名前を生成できず、エラーとなるか、予期せぬ挙動を示す可能性がありました。

この差異により、Linux環境でのGoのビルドが失敗したり、不安定になったりする問題が発生していました。このコミットは、このクロスプラットフォーム間のmktempの挙動の違いを吸収し、Linuxを含むすべてのサポート対象OSでビルドが安定して動作するようにするための修正です。

前提知識の解説

1. mktempコマンド

mktempは、シェルスクリプトなどで一時ファイルや一時ディレクトリを安全に作成するためのコマンドです。ファイル名やディレクトリ名にランダムな文字列を付加することで、他のプロセスとの名前の衝突を防ぎ、セキュリティ上のリスクを低減します。

  • -dオプション: 一時ファイルではなく、一時ディレクトリを作成することを指定します。
  • -t <prefix>オプション: 一時ファイル/ディレクトリ名のプレフィックス(接頭辞)を指定します。このプレフィックスの後にランダムな文字列が付加されます。
  • XXXXXX: mktempコマンドがランダムな文字列に置き換えるプレースホルダーです。このXXXXXXがテンプレート文字列に含まれていることが、一部のmktemp実装(特にLinux)では必須となります。

2. シェルスクリプトと環境変数

Goのビルドスクリプトはシェルスクリプトで書かれており、環境変数を利用してビルド設定を管理しています。

  • export VAR=value: 環境変数VARvalueを設定し、その変数を子プロセスにも引き継ぐことを意味します。
  • $(command): コマンド置換と呼ばれ、commandの実行結果を文字列として取得します。このコミットでは$(mktemp ...)の出力(作成された一時ディレクトリのパス)をWORK環境変数に設定しています。
  • trap "command" SIGNALS: 指定されたシグナル(EXIT, SIGINT, SIGTERMなど)が捕捉されたときにcommandを実行するよう設定します。ここでは、スクリプト終了時や中断時に一時ディレクトリを削除するためのクリーンアップ処理が記述されています。
  • set -e: スクリプト内でエラーが発生した場合(コマンドがゼロ以外の終了ステータスを返した場合)に、即座にスクリプトの実行を終了させる設定です。これにより、エラーの連鎖を防ぎ、デバッグを容易にします。

3. クロスプラットフォーム開発

Go言語は、Windows、Linux、macOS、FreeBSD、OpenBSD、NetBSD、Plan 9など、多岐にわたるOSとCPUアーキテクチャをサポートしています。このようなクロスプラットフォーム開発では、OSや環境によってコマンドの挙動やシステムコールの仕様が異なる場合があるため、それらの差異を吸収するようなコード設計が重要になります。mktempの挙動の違いは、まさにその典型的な例です。

技術的詳細

このコミットの核心は、mktempコマンドのテンプレート文字列の扱いにあります。

変更前:

export WORK=$(mktemp -d -t go-build)

変更後:

export WORK=$(mktemp -d -t go-build.XXXXXX)

mktempコマンドは、一時ファイルやディレクトリを作成する際に、指定されたテンプレート文字列の末尾にランダムな文字列を付加することで、一意な名前を生成します。このランダムな文字列が付加されるべき場所を明示的に示すのがXXXXXXというプレースホルダーです。

POSIX標準では、mktempのテンプレートは少なくとも3つのXで終わる必要があるとされています。しかし、実際のmktempの実装はOSによって微妙に異なります。

  • BSD系(macOS, FreeBSDなど): mktempは、テンプレート文字列の末尾にXXXXXXがなくても、自動的にランダムな文字列を付加して一時ファイル/ディレクトリを作成します。例えば、mktemp -d -t go-buildとすると、go-build.ランダム文字列のようなディレクトリが作成されます。
  • GNU Coreutilsのmktemp(Linuxで一般的): GNU版のmktempは、セキュリティ上の理由から、テンプレート文字列の末尾にXXXXXXが含まれていることを強く要求します。XXXXXXがない場合、mktempはエラーを返すか、または警告を発して期待通りに動作しないことがあります。これは、開発者が意図せず固定名の一時ファイルを作成してしまうことを防ぎ、名前の衝突や情報漏洩のリスクを低減するためです。

このコミットは、Linux環境でのmktempの厳格な要件に対応するために、テンプレート文字列go-buildの末尾に.XXXXXXを追加しました。これにより、mktempgo-build.XXXXXXをテンプレートとして認識し、XXXXXXの部分をランダムな文字列に置き換えて、go-build.ランダム文字列のような一意で安全な一時ディレクトリを生成できるようになります。

コミットメッセージにある「On other systems the temporary directory name will have a .XXXXXX in the middle of it. Oh well.」という記述は、この変更によって、Linux以外のシステムでも一時ディレクトリ名に.XXXXXXが明示的に含まれるようになるが、それは許容範囲である、という開発者の意図を示しています。これは、Linuxでの問題を解決するためのトレードオフであり、他のシステムでの挙動に大きな悪影響はないと判断されたことを意味します。

コアとなるコードの変更箇所

このコミットでは、Goのビルドスクリプトを構成する以下の15個のファイルが変更されています。すべてのファイルで、mktempコマンドの引数に.XXXXXXが追加されています。

  • src/buildscript.sh
  • src/buildscript_darwin_386.sh
  • src/buildscript_darwin_amd64.sh
  • src/buildscript_freebsd_386.sh
  • src/buildscript_freebsd_amd64.sh
  • src/buildscript_linux_386.sh
  • src/buildscript_linux_amd64.sh
  • src/buildscript_linux_arm.sh
  • src/buildscript_netbsd_386.sh
  • src/buildscript_netbsd_amd64.sh
  • src/buildscript_openbsd_386.sh
  • src/buildscript_openbsd_amd64.sh
  • src/buildscript_plan9_386.sh
  • src/buildscript_windows_386.sh
  • src/buildscript_windows_amd64.sh

例として、src/buildscript.shの変更差分を以下に示します。他のファイルも同様の変更です。

--- a/src/buildscript.sh
+++ b/src/buildscript.sh
@@ -19,7 +19,7 @@ do

 export GOOS='$GOOS'
 export GOARCH='$GOARCH'
-export WORK=$(mktemp -d -t go-build)
+export WORK=$(mktemp -d -t go-build.XXXXXX)
 trap "rm -rf $WORK" EXIT SIGINT SIGTERM
 set -e

コアとなるコードの解説

変更された行は以下の通りです。

変更前:

export WORK=$(mktemp -d -t go-build)

この行では、mktemp -d -t go-buildコマンドを実行し、その出力(作成された一時ディレクトリのパス)をWORK環境変数に設定しています。-dはディレクトリを作成することを示し、-t go-buildgo-buildをプレフィックスとする一時ディレクトリを作成することを示しています。しかし、Linuxのmktempでは、この形式では一意な名前を生成するためのXXXXXXプレースホルダーが不足しているため、問題が発生していました。

変更後:

export WORK=$(mktemp -d -t go-build.XXXXXX)

この行では、プレフィックスに.XXXXXXを追加しています。これにより、mktempコマンドはgo-build.の後にランダムな文字列を付加して、go-build.abcdefのような形式の一時ディレクトリ名を生成します。この.XXXXXXの追加は、特にGNU Coreutilsのmktemp(Linuxで広く使われている)の要件を満たし、クロスプラットフォームでの一時ディレクトリ作成の堅牢性を高めます。

この修正により、Goのビルドプロセスが一時ディレクトリを安全かつ確実に作成できるようになり、特にLinux環境でのビルドの安定性が向上しました。

関連リンク

参考にした情報源リンク