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

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

このコミットは、Go言語のビルドスクリプトにおけるシバン(shebang)の記述方法を変更するものです。具体的には、#!/bin/bash から #!/usr/bin/env bash へと修正することで、スクリプトの移植性と実行環境の柔軟性を向上させています。

コミット

commit 670933048822c65559e370d6a5c0464980025479
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Wed Dec 21 11:11:55 2011 +0900

    build: make use of env

    R=rsc, golang-dev
    CC=golang-dev
    https://golang.org/cl/5504053

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

https://github.com/golang/go/commit/670933048822c65559e370d6a5c0464980025479

元コミット内容

このコミットは、Go言語のビルドシステムで使用される複数のシェルスクリプトにおいて、シバン(shebang)の記述を #!/bin/bash から #!/usr/bin/env bash へと変更しています。これにより、スクリプトの実行時にbashインタプリタのパスを環境変数PATHから動的に解決するようになります。

変更の背景

この変更の背景には、シェルスクリプトの移植性と柔軟性の向上が挙げられます。従来の #!/bin/bash という記述は、bashインタプリタが /bin/bash という固定パスに存在することを前提としています。しかし、システムによっては bash/usr/local/bin/bash/opt/local/bin/bash など、異なるパスにインストールされている場合があります。このような環境では、スクリプトが正しく実行されないか、あるいは手動でシバンを修正する必要がありました。

#!/usr/bin/env bash と記述することで、env コマンドがユーザーの環境変数 PATH を検索し、最初に見つかった bash インタプリタを使用してスクリプトを実行するようになります。これにより、bash のインストールパスがシステム間で異なる場合でも、スクリプトを修正することなく実行できるようになり、ビルドプロセスの堅牢性と利便性が向上します。特に、Go言語のようなクロスプラットフォーム開発を重視するプロジェクトにおいては、様々なOSや環境でのビルドを円滑に進める上で重要な改善となります。

前提知識の解説

シバン (Shebang)

シバン(Shebang)とは、Unix系オペレーティングシステムにおけるスクリプトファイルの先頭に記述される #! で始まる行のことです。この行は、そのスクリプトを実行するためにどのインタプリタを使用すべきかをシステムに指示します。

例:

  • #!/bin/bash: このスクリプトは /bin/bash にある bash インタプリタで実行されるべきであることを示します。
  • #!/usr/bin/python: このスクリプトは /usr/bin/python にある python インタプリタで実行されるべきであることを示します。

env コマンド

env コマンドは、環境変数を設定または表示するためのUnix系コマンドです。env の最も一般的な使用法の一つは、特定のプログラムを起動する際に、そのプログラムが使用する環境変数を一時的に変更することです。

シバンと組み合わせて #!/usr/bin/env <interpreter> の形式で使用される場合、env コマンドは環境変数 PATH を検索し、指定された <interpreter>(この場合は bash)を最初に見つけたパスで実行します。これにより、インタプリタの絶対パスがシステム間で異なる場合でも、スクリプトが正しく実行されるようになります。

PATH 環境変数

PATH 環境変数は、Unix系システムにおいて、実行可能ファイルを探すディレクトリのリストをコロン (:) で区切って指定するものです。ユーザーがコマンド名を入力すると、シェルはこの PATH に含まれるディレクトリを順番に検索し、最初に見つかった実行可能ファイルを実行します。

例えば、PATH=/usr/local/bin:/usr/bin:/bin の場合、シェルはまず /usr/local/bin を探し、次に /usr/bin、最後に /bin を探します。

技術的詳細

このコミットで行われた技術的な変更は、Go言語のビルドスクリプト群におけるシバンの統一的な変更です。具体的には、以下のファイル群で #!/bin/bash#!/usr/bin/env bash に変更されました。

  • 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

この変更は、各スクリプトの最初の行、すなわちシバン行のみに適用されています。これにより、スクリプトの実行時に bash インタプリタの絶対パスをハードコードするのではなく、PATH 環境変数に基づいて動的に解決するようになります。

このアプローチは、特に異なるオペレーティングシステムやディストリビューションでGo言語のビルドを行う際に有効です。例えば、一部のLinuxディストリビューションでは bash/bin/bash に、別のディストリビューションでは /usr/bin/bash に配置されていることがあります。#!/usr/bin/env bash を使用することで、スクリプトはこれらのパスの違いを吸収し、システムにインストールされている bash を自動的に見つけて実行できます。

また、この変更は、Go言語のビルドシステムがよりポータブルで、多様な開発環境に対応できることを示しています。ビルドスクリプトはGo言語自体をビルドするために使用されるため、これらのスクリプトが様々な環境で確実に動作することは、Go言語の普及と開発体験にとって非常に重要です。

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

このコミットにおけるコアとなるコードの変更は、各ビルドスクリプトファイルの先頭行(シバン)のみです。

例として、src/buildscript.sh の変更箇所を示します。

--- a/src/buildscript.sh
+++ b/src/buildscript.sh
@@ -12,7 +12,7 @@ do
 	targ=buildscript_${GOOS}_$GOARCH.sh
 	rm -f $targ
 
-(echo '#!/bin/bash
+(echo '#!/usr/bin/env bash
 # AUTO-GENERATED by buildscript.sh; DO NOT EDIT.
 # This script builds the go command (written in Go),
 # and then the go command can build the rest of the tree.

同様の変更が、他のすべての src/buildscript_*.sh ファイルにも適用されています。

コアとなるコードの解説

変更された行は、シェルスクリプトの実行方法を定義するシバンです。

  • 変更前: #!/bin/bash

    • これは、スクリプトが /bin/bash にある bash インタプリタによって直接実行されることを意味します。もし bash がこのパスに存在しない場合、スクリプトは実行エラーとなります。
  • 変更後: #!/usr/bin/env bash

    • これは、スクリプトがまず /usr/bin/env プログラムによって実行され、env プログラムが PATH 環境変数を使用して bash インタプリタを探し、それを見つけたらその bash インタプリタにスクリプトの実行を委ねることを意味します。
    • この方法の利点は、bash がシステム上のどこにインストールされていても(例: /usr/local/bin/bash/opt/homebrew/bin/bash など)、PATH に含まれていればスクリプトが正しく実行される点にあります。これにより、スクリプトの移植性が大幅に向上します。

この変更は、Go言語のビルドシステムがより堅牢で、多様なUnix系環境(Linux、macOS、FreeBSD、NetBSD、OpenBSD、Plan 9、Windows (Cygwin/WSLなど))で一貫して動作することを保証するための、標準的なベストプラクティスに沿ったものです。

関連リンク

参考にした情報源リンク

  • 上記の関連リンクに加えて、一般的なUnix/Linuxのシェルスクリプトのベストプラクティスに関する情報源。
  • man env コマンドのドキュメント。
  • man bash コマンドのドキュメント。
  • Go言語のビルドシステムに関する公式ドキュメントやコミュニティの議論。