others-how to solve '??????' i.e. characters were garbled in linux system ?

1. Purpose

In this post, I would demo how to solve the garbled characters in linux system , i.e. All unicode characters are displayed as ‘??????’.

2. The System

  • Linux System

3. The Problem

When we login a linux system via ssh, sometimes, we got this error or warning message:

Last login: Fri Mar 12 16:45:39 2021 from 10.1.1.251
-bash: Warning:setlocale: LC_CTYPE: Unable to change locale options (UTF-8): No such file or directory

4. The environment

[root@bswen-7 ~]# echo $LANG
zh_CN.UTF-8

[root@bswen-7 ~]# locale
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: ?????????
LANG=zh_CN.UTF-8
LC_CTYPE=UTF-8
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=

[root@bswen-7 ~]# cat /etc/locale.conf
LANG="zh_CN.UTF-8"

You can see that all environment variables about locales are correctly configured as ‘zh_CN.UTF-8’, why is it not working?

5. Solution

There are two solutions:

5.1 Solution #1

add :

LC_ALL=zh_CN.UTF-8
LANG=zh_CN.UTF-8

to the file /etc/environment,then logout of current ssh session, login again.

Last login: Fri Mar 12 17:20:23 2021
[root@Centos76 ~]# ll
总用量 44832
drwxr-xr-x. 6 root root       65 8月  29 2018 vmtools
-r--r--r--. 1 root root 13820154 9月  25 2019 vmtools-2.5.0.142.tar.bz2
drwxr-xr-x. 2 root root        6 9月  25 2019 公共
drwxr-xr-x. 2 root root        6 9月  25 2019 模板
drwxr-xr-x. 2 root root        6 9月  25 2019 视频
drwxr-xr-x. 2 root root        6 9月  25 2019 图片
drwxr-xr-x. 2 root root        6 9月  25 2019 文档
drwxr-xr-x. 2 root root        6 9月  25 2019 下载
drwxr-xr-x. 2 root root        6 9月  25 2019 音乐
drwxr-xr-x. 2 root root        6 9月  25 2019 桌面
[root@Centos76 ~]#

It works, the chinese characters are displayed correctly.

But why do I need do this change ?

5.1.1 The /etc/environment file

/etc/environment is specifically meant for system-wide environment variable settings. It is not a script file, but rather consists of assignment expressions, one per line. Specifically, this file stores the system-wide locale and path settings.

And according to Neula’s answer:

/etc/environment is not part of POSIX, it belongs to PAM (Pluggable Authentication Module), and only programs compiled with PAM support are able to use it (primarily login systems, which subsequently start the shell or user environment). This means it isn’t even read by your shell.

So , this file is used when you want to set variables for all users and it would be loaded when user login.

5.2 Solution #2

In addition to change the /etc/environment manually, you can also do this job automatically by using ansible playbook.

This is the ansible playbook’s content (locale-change.yml):

- name: Configure locale
  hosts: all
  tasks:
    - name: Write locale environment
      shell: |
        echo 'LC_ALL=zh_CN.UTF_8
        LANG=zh_CN.UTF_8' > /etc/environment

And ansible.cfg:

[defaults]
remote_user = root
inventory = hosts

And the hosts file:

10.1.1.43

Then we can execute the ansible playbook by this command:

➜  myhome: ✗ ansible-playbook locale-change.yml

PLAY [Configure locales] ***************************************************************************

TASK [Gathering Facts] ********************************************************************************
ok: [10.1.1.43]

TASK [write locale environment] *******************************************************************************************
changed: [10.1.1.43]

PLAY RECAP ********************************************************************************************
10.1.1.43               : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

The job is done!

6. Summary

In this post, we demonstrated how to solve the garbled characters in linux system by changing the /etc/environment. You can do this job manually or automatically by using ansible playbook.