RHEL7 または RHEL8 でシステムロケールを変更する方法
Environment
- Red Hat Enterprise Linux (RHEL) 7
- Red Hat Enterprise Linux (RHEL) 8
Issue
- ローカルログイン時のシステム全体のロケール (またはユーザー固有のロケール) を変更するには、どうすればよいですか?
- ssh ログイン時のロケールを変更するには、どうすればよいですか?
- ssh クライアントのロケールが ssh セッションに影響を与えないようにするには、どうすればよいですか?
- OS レベルで "file.encoding" や "sun.jnu.encoding" といった環境変数が設定されているのが見当たりません。これらの変数は OS レベルで設定できますか?RHEL 7.3 と Java 1.8.0_25 に関して、既知の問題はありますか?
Resolution
このセクションでは、ローカルログインと ssh ログインのシステムロケールを変更する手順について詳しく説明します。
- ローカルログイン時のシステムロケールとユーザーロケールの設定方法
- ssh ログイン時のユーザーロケールの設定方法
- 前の手順で行った変更が成功したことを確認する方法
ログイン時に設定されるロケールを設定するには、さまざまな設定ファイルに関するある程度の知識が必要です。どのような変更が必要になるかは、ビジネス要件と、最終的に達成したい結果によって異なります。Red Hat は、まず達成したい最終結果を明確に定義することを推奨しています。定義後は、このソリューション記事を読んで理解するまで、設定変更は一切行わないでください。
ローカルアクセス用に、システム全体またはユーザー固有のロケールを設定する方法
-
技術的背景
対話型シェルが開かれると、/etc/profile.d/ ディレクトリー内のスクリプトが実行されます。スクリプト /etc/profile.d/lang.sh は、以下に示すように LANG やその他のロケール変数を設定できます。# cat /etc/profile.d/lang.sh # /etc/profile.d/lang.sh - set i18n stuff sourced=0 if [ -n "$LANG" ]; then saved_lang="$LANG" [ -f "$HOME/.i18n" ] && . "$HOME/.i18n" && sourced=1 LANG="$saved_lang" unset saved_lang else for langfile in /etc/locale.conf "$HOME/.i18n" ; do [ -f $langfile ] && . $langfile && sourced=1 done fiLANG が設定されている場合、その変数のコピーが保存され、ユーザーのホームディレクトリーにある.i18n ファイルが読み込まれます。ただし、LANG の値は、保存されていた元の値に書き戻される点に注意してください。つまり、LANG がすでに設定されている場合、ホームディレクトリーの.i18n ファイルからその値を変更することはできません。ただし、LC_ALL の値は LANG 環境変数よりも優先されるため、代わりに LC_ALL を設定することもできます (http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html を参照)。他の LC_* 環境変数も LANG よりも優先されますが、LC_ALL は他のすべての LC_* 環境変数よりも優先されます。
LANG の値が未設定または NULL 値の場合、/etc/locale.conf とユーザーのホームディレクトリーにある .i18n が (この順序で) 存在すれば読み込まれます。これは、ユーザーの.i18n ファイルが存在する場合、システム全体の設定ファイル /etc/locale.conf で設定された値をオーバーライドできることを意味します。
- システム全体 でロケールを設定するには、
/etc/locale.confファイルを変更する必要があります。 - 特定のユーザー のロケールを設定するには、
$HOME/.i18nファイルを変更する必要があります。
注記: これらの設定は、次回のログイン時に有効になり、/etc/profile.d/lang.sh が実行される前に LANG がすでに設定されている場合は、標準の RHEL ログインスクリプトでは変更できません。これを理解することは、次のセクションで説明するシステムへの非ローカル (ssh) アクセスにとって重要です。
- システム全体 でロケールを設定するには、
ssh セッションのロケールを設定する方法
-
技術的背景
デフォルトでは、RHEL 7 および RHEL 8 システムは、ssh クライアントからのロケール環境変数を受け入れます。(ssh クライアントから渡された場合) 以下のロケール環境変数は、ログインスクリプトが実行される前に環境変数として設定されます。# Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE上記の出力は、/etc/ssh/sshd_config からのものです。LANG が渡された環境変数の 1 つである場合、ログイン処理中に変更されることはありません。理由については、上記の「ローカルアクセス用に、システム全体またはユーザー固有のロケールを設定する方法」を参照してください。
たとえば、RHEL 7 サーバーにコンソールなどから直接ログインした場合、LANG 変数は以下のように設定されます (これは一例であり、実際のシステムによって値は異なる場合があります)。$ env |grep -e LANG -e LC LANG=en_US.UTF-8続いて、LANG の値 (必ずエクスポートする必要があります) を別のロケールに変更し、ssh クライアントを使用して同じシステムに再接続します。
$ export LANG=ja_JP.UTF-8 $ ssh localhost user@localhost's password: ... $ echo $LANG ja_JP.UTF-8LANG の値はクライアントの ssh セッションから保持され、ユーザーの.i18n ファイルや /etc/locale.conf (この例では en_US.UTF-8) に基づいて設定されるわけではありません。これは、想定内の動作です。
-
上記で説明したデフォルトの動作が見られない場合、ssh クライアントからのロケールの使用を許可したい場合は、以下を実行する必要があります。
-
サーバーの /etc/ssh/sshd_config ファイルの AcceptEnv に LANG が含まれていることを確認します。
注記: sshd_config の設定を変更した場合は、変更を有効にするために sshd サービスを再起動する必要があります。デフォルト設定は以下のとおりです。
# Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE -
ssh を実行する前に、クライアント側で LANG 環境変数をエクスポートします。
export LANG=ja_JP.UTF-8 -
クライアントサーバーから ssh を使用してサーバーに接続します。
注記: これは、ログイン時に実行される各種スクリプトにおいて、ロケール環境変数を変更するような修正を一切行っていないことを前提としています。
-
-
サーバー側で ssh セッションに対して特定の初期ロケールを強制したい場合は、以下のいずれかの方法で設定を変更する必要があります。
- sshd が ssh クライアントから LANG 変数を設定することを防ぐため、サーバー上の sshd_config の AcceptEnv オプションから LANG やその他のロケール変数を削除します (ここでは LANG を使用していますが、すべてのロケール環境変数に適用されます)。
- /etc/profile.d/ 内に新しいスクリプトを作成し、ユーザーに別のロケール環境変数の使用を強制するように設定します。/etc/profile が /etc/profile.d 内のスクリプトを読み込む仕組み上、作成するスクリプトの名前は lang.sh よりもアルファベット順で後になる必要があります。たとえば、unset_lang.sh という名前にすれば、lang.sh の「後」に実行されます。
注記 1: /etc/profile.d/lang.sh を変更することを選択した場合、そのファイルは設定ファイルではありません。/etc/profile.d/lang.sh を提供する RPM パッケージがインストールされると、変更内容は上書きされます。/etc/profile.d/lang.sh を変更することは避けるべきです。
注記 2: /etc/profile は、/etc/profile.d にあるスクリプトを読み込みます。/etc/profile.d にあるスクリプト内では、exit を使用しないでください。これを行うと、そのスクリプトを読み込んでいるスクリプト (/etc/profile) 自体が終了してしまいます。
重要: 万が一に備えて、/etc/profile.d にスクリプトを追加することを選択した場合は、デバッグを容易にするために、以下のいずれかの方法で追加してください。- 設定変更によってシステムにログインできなくなるなどの問題が発生した場合に備え、(できればコンソール経由で) ルートセッションをアクティブな状態のまま保持しておいてください。これにより、新しいスクリプトを削除できるようになります。
- 変更内容を実稼働システムに適用する前に、テスト環境でテストします。
ロケールの変更を確認する方法
- 現在のセッションからログアウトしてください。ロケールはログイン時に設定されるため、変更は次回のログイン時に反映されます。
-
locale コマンドを使用して、行われた変更を確認します。
localeまたは、以下を実行します。
env | grep -e LANG -e LC_ -
ロケールが想定していた値になっていない場合は、上記の手順が正しく実行されているか確認します。この解説は、ユーザーの .bash_profile、.bash_login、.profile.bashrc などのファイルでロケール環境変数を変更するようなカスタマイズが行われていないことを前提としています。
その他の情報
- サーバーを再起動する必要はありません。「ログアウトして再度ログインする」と、ロケールの変更を確認できます。
- 以前の RHEL バージョンに関する情報については、How to change the system locale in RHEL? を参照してください。
- ターミナルエミュレーター (putty など) を使用してサーバーに接続する場合、ターミナルエミュレーターは、ssh セッションを開く際にサーバーに渡す環境変数を定義できます。そうすることで、ログインセッションのロケールをオーバーライドすることが可能になります。putty などのプログラム (またはその他のターミナルエミュレーター) を介してシステムに直接アクセスしていて、環境変数がターミナルエミュレーターによって提供されている場合は、環境変数の変更または削除方法について、ターミナルエミュレーターのドキュメントを参照してください。
注記
RHEL 9 では、RHEL 7 および 8 に見られたデフォルト設定の多くが変更されており、AcceptEnv オプションもその 1 つです。RHEL 9 でこの機能を有効にするには、/etc/ssh/sshd_config ファイルを更新する必要があります。
Root Cause
- 複数の設定ファイルとシステムへのアクセス方法が、ユーザーのロケールに影響を与えます。
- RHEL7 では、グローバルロケール設定ファイルが以前の RHEL バージョン (
/etc/sysconfig/i18n) から/etc/locale.confに変更されました。 - ssh セッションは、デフォルトではクライアント (ssh コマンドが実行された場所) からロケール環境変数を受け入れますが、これはサーバーが設定したい内容をオーバーライドする可能性があります。
Diagnostic Steps
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Comments