クロスプラットフォームスクリプトの行末
シェルスクリプトが常にLFを使用し、バッチスクリプトが常にCRLFを使用するように.gitattributesを設定し、OS間での実行エラーを防ぐ方法。
詳細な説明
スクリプトファイルの行末
スクリプトファイルは不正な行末に対して最も敏感なファイルの1つです。CRLF行末のbashスクリプトはUnixで実行できず、LF行末のバッチファイルはWindowsで誤動作する可能性があります。これはtext=autoだけでは不十分な領域であり、明示的なeolディレクティブが必要です。
推奨設定
# Unixスクリプト(LF必須)
*.sh text eol=lf
*.bash text eol=lf
*.zsh text eol=lf
*.fish text eol=lf
*.csh text eol=lf
*.ksh text eol=lf
# Makefile(LF必須)
Makefile text eol=lf
makefile text eol=lf
*.mk text eol=lf
GNUmakefile text eol=lf
# Docker(LF必須)
Dockerfile text eol=lf
Dockerfile.* text eol=lf
*.dockerfile text eol=lf
docker-compose.yml text eol=lf
# CI設定(LF必須)
.travis.yml text eol=lf
.gitlab-ci.yml text eol=lf
Jenkinsfile text eol=lf
# Windowsスクリプト(CRLF必須)
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
*.psm1 text eol=crlf
*.psd1 text eol=crlf
# Gitフック(LF必須)
.husky/* text eol=lf
シバン問題
Unixシステムがcrlf行末のスクリプトを実行しようとすると、シバン行(#!/bin/bash)が#!/bin/bash\rとして解釈されます。カーネルは/bin/bash\r(キャリッジリターン付き)というインタープリターを探しますが、存在しません:
/bin/bash^M: bad interpreter: No such file or directory
このエラーは不可解で、特にCI/CDパイプラインでは開発者が直接ターミナルにアクセスできないため、デバッグが困難です。
DockerとCRLF
Linux上のDockerビルドは、DockerfileまたはエントリポイントスクリプトのシェルコマンドにCRLF行末がある場合に失敗します。一般的な症状:
standard_init_linux.go: exec user process caused "no such file or directory"
Gitフック
Gitフック(.husky/*、.git/hooks/*)はGit自体が実行するシェルスクリプトです。LF行末と実行可能パーミッションが必要です。.gitattributesが行末を処理し、chmod +xがパーミッションを処理します。
行末のテスト
行末が正しいことを確認します:
# ファイルのCRLFを確認
file script.sh
# 出力: "script.sh: Bourne-Again shell script, ASCII text executable"
# vs: "script.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators"
ユースケース
Unixシェルスクリプトとwindowsバッチ/PowerShellスクリプトの両方を含むリポジトリには、明示的なeolディレクティブが必要です。これは、CI/CDパイプライン、Dockerワークフロー、またはクロスプラットフォーム開発チームを持つプロジェクトにとって重要です。