[インデックス 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
: 環境変数VAR
にvalue
を設定し、その変数を子プロセスにも引き継ぐことを意味します。$(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
を追加しました。これにより、mktemp
はgo-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-build
はgo-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環境でのビルドの安定性が向上しました。
関連リンク
- Go Gerrit Change-ID: https://golang.org/cl/5504049
参考にした情報源リンク
mktemp
man page (Linux): https://man7.org/linux/man-pages/man1/mktemp.1.htmlmktemp
man page (FreeBSD): https://www.freebsd.org/cgi/man.cgi?query=mktemp&sektion=1&format=html- POSIX
mktemp
specification: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/mktemp.html - GNU Coreutils
mktemp
documentation: (具体的なURLは変動する可能性があるため、mktemp GNU Coreutils
で検索することを推奨) - Go言語のビルドシステムに関する一般的な情報: https://go.dev/doc/install/source
- Go言語のクロスコンパイルに関する情報: https://go.dev/doc/install/source#environment