【bash】Windows/Linuxの改行コードの違いで困った話
背景
- 23卒エンジニア
- 請負開発のSaaSのデータベースバックアップ部分の構築を任される
- シェルスクリプトを自動実行する形式
- コードレビューで「環境変数は切り出して書いて!」とFB
- やってみる
環境
-
Windows環境で開発 -> Amazon Linuxを積んだEC2サーバで実行
- ローカル環境で作成したコードをTera Term経由でログインし、ファイルを転送して実行
-
somewhere
ディレクトリ配下に環境変数設定ファイル(target.txt
)と実行するbashファイル(something.bash
)
エラー
/home/ec2-user/something.bash
not accessible: No such file or directory.omewhere/target.txt
: Name or service not knownname 12.345.678.900
Connection closed
- bashファイルの行頭に書いていた環境変数設定を切り出しただけでこのエラーが出た
原因
-
改行に関するデフォルトの設定がWindowsとLinuxで違うから
- 一見違いがないように見えても文字コードが別物なので、ファイルパスが認識されなかった
確認方法
- VSCodeの右下に表示がある
test.bash
test.txt
-
CRLFは改行に
\r\n
を使う設定 -
LFは改行に
\n
を使う設定 -
zsh, csh系のファイルはデフォルトでLF改行になっていたため、発覚が遅れた
-
.c
,.cpp
,.py
あたりもデフォルトはCRLF改行でした
-
-
echo ${VAR}
の結果は正しく取れている(ように見えた)のでわけがわかるまで大混乱だった
解決策
このファイルの改行コード設定を変える
- 右下の青いリボンの「CRLF(またはLF)」をクリックで変更できる
ここから選択
VSCodeのデフォルトの改行コードをLFに変える
- ファイル -> ユーザー設定 -> 設定
- もしくは
Ctrl + ;
,Ctrl + ,
- もしくは
- 「設定の検索」に
eol
と入力
- 規定の改行文字を
\n
に変更
コードをGit管理している場合の注意
-
git add
すると以下のようなwarningメッセージが出る
$ git add .
warning: in the working copy of 'somewhere/foo.bash', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'somewhere/bar.bash', LF will be replaced by CRLF the next time Git touches it
- 意味は書いてあるそのままで、「改行コードにLFが使われているけど、Gitが次にファイルを触るときにCRLFに統一するよ」とのこと
- ぜひやめてほしい!
- 実際、リモートブランチにpushしたコードをpullすると、改行コードがCRLFに置き換わっているファイルがあった
Gitの行末設定を確認・変更する
git config core.autocrlf
true
- このコマンドでGitの設定を確認できる
core.autocrlf
Setting this variable to "true" is the same as setting the text attribute to "auto" on all files and core.eol to "crlf". Set to true if you want to have CRLF line endings in your working directory and the repository has LF line endings. This variable can be set to input, in which case no output conversion is performed.
-
https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreautocrlf より
-
core.autocrlf
の設定値は3種類あり、以下の違いがある
-
core.autocrlf | チェックアウト時 | コミット時 |
---|---|---|
true | CRLFに統一 | LFに統一 |
input | 変換無し | LFに統一 |
false | 変換無し | 変換無し |
- 設定は
input
にしてしまってよさそう
$ git config core.autocrlf input
感想
コンピュータの改行コード。タイプライターの動作に由来する。タイプライターは1行を最後(紙の右端)まで印字したら、キャリッジ(印字するためのヘッド)を戻し(紙の左端に動かす、キャリッジリターン)、1行分を紙送りして(ライン・フィード)、次の行を印字する態勢となる。この動作はCR(カーソルを先頭に戻し)、LF(次の行に移りなさい)というコンピュータの改行命令CRLFになった。
-
記事書くために調べ物をしていたらこんな記載がありました
- 印刷機(タイプライター)の動作原理が改行コードの発端とのこと
- ノスタルジックでいいとは思いますが、改行コードの規格は早く統一されてほしいです
参考
- Visual Studio Codeで改行をCRLFで保存してしまう。LFに変える方法。 | ただ屋ぁのブログ
- CRLF (しーあーるえるえふ) とは? | 計測関連用語集 | TechEyesOnline
- linux - "Name or service not knownname" using SSH from script - Stack Overflow
- Git - git-config Documentation
- 行終端を処理するようGitを設定する - GitHub Docs
- 気をつけて!Git for Windowsにおける改行コード - Qiita
- warning: LF will be replaced by CRLF inが出たときの対処法
Discussion