シェルスクリプト改行コードでのエラー原因と対策

シェルスクリプト改行コードでのエラー原因と対策

Windows で作成した シェルスクリプトが Linux でエラーが発生する

エラーの内容

以下のようなシェルスクリプトを Windows で作成します。

a.sh

#!/bin/bash

echo hello world

"hello world" を出力するだけのコードです。

これを Linux 環境に移して実行します。例えば WSL(Ubuntu) に移して実行してみると以下のようなエラーが発生します。

$ ./a.sh
./a.sh: line 2: $'\r': command not found
hello world

一応 "hello world" 葉出力されていますが、**"./a.sh: line 2: $'\r': command not found"** というエラーエラーが発生しています。2行目は空行なのにエラーになってしまっています。

同じ内容を CentOS や Amazon Linux などで実行すると以下のようなエラーになることがあります。

$ ./a.sh
-bash: ./a.sh: /bin/bash^M: 誤ったインタプリタです: そのようなファイルやディレクトリはありません

"/bin/bash^M: 誤ったインタプリタです: そのようなファイルやディレクトリはありません""/bin/bash^M: bad interpreter: No such file or directory" のようなエラーになることがあります。

エラーの原因

これらのエラーはいずれも作成したスクリプトの改行コードが CRLF であることが原因です。Windows 環境で作成した場合、改行コードが CRLF になることが多く、このようなエラーが発生します。

あるいは気を付けて改行コードを LF にしてもGitを使っていると、Git側で改行コードが混在しているとコミット時に勝手に CRLF に変換されてしまっているかもしれません。。。

実行しようとしたファイルを cat コマンドを使って改行コードを確認できるように表示してみます。

$ cat -e ./a.sh

-e でTABを除く全ての非表示文字を表示することができます。表示した結果は次のようになります。

#!/bin/bash^M$
^M$
echo hello world^M$

^M$ と表示されている個所があるのがわかります。この ^M が CR, $ が LF に対応しています。つまりこのコードは改行コードが CRLF になっており、これがエラーの原因になっています。

ちなみにOSによってはCRLFでも実行できる場合があるみたいです。

解決策、対策

エラーの解決策は改行コードを LF に直すことです。sedコマンドを使って改行コード \r を取り除けばOKです。

$ sed -i 's/\r//' *.sh

上のコマンドはカレントディレクトリ内の .sh の拡張子を持つファイルすべての \r を削除しています。

実行後、スクリプトを実行してエラーが出なければOKです。

Git コミット時に改行コードを CRLF にされる

Gitを使ってソースコードを管理していると、改行コードをコミットやらプッシュ時に変換してくれる機能があります。どうもデフォルトで有効になっているようで、これが原因でWindows環境からLinux環境にファイルを移動してエラーが発生していました。

なのでこのGitの改行コード自動変換機能を無効化しました。

面倒なのでグローバルに一括で無効化しました。

$ git config --global core.autocrlf false

リポジトリごとに無効化することもできます。

$ git config --local core.autocrlf false

その他細かく挙動を設定できるみたいですがひとまずこれで良しとしておきます。

以上。

参考URL

Linuxカテゴリの最新記事