LANG or LC_ALL environment variables on both machines to a consistent UTF-8 locale, such as en_US.UTF-8. This ensures that terminal emulators and file viewers interpret byte sequences correctly, eliminating display errors without modifying SSH configuration directives.
Understanding the Root Cause
When you connect to a remote server via SSH, your local machine sends keystrokes and receives output based on its own locale settings. If the remote server is configured with a different encoding (for example, ISO-8859-1 instead of UTF-8), characters that do not map directly will appear as question marks, boxes, or random symbols. This is not a bug in the SSH protocol itself but a mismatch in how the operating systems handle text representation. The problem often manifests when viewing log files, editing configuration files, or running scripts that contain non-ASCII characters. It can also occur when copying files between systems with different default encodings. While SSH handles the binary transmission of data reliably, the interpretation of that data depends entirely on the shell environment active on the remote host.Verifying Current Locale Settings
Before applying fixes, you must identify where the mismatch exists. Log into your remote server and run thelocale command. This displays the current language and encoding settings for categories like LC_CTYPE, LC_NUMERIC, and LC_ALL. Look specifically at the LANG variable, which sets the default locale for all categories unless overridden.
On your local machine, run the same command. Compare the outputs. If the remote server shows LANG=en_US.ISO-8859-1 while your local terminal expects UTF-8, you have identified the source of the corruption. Note that some servers may have multiple locales installed but use a legacy one by default for compatibility reasons.
Setting the Correct Locale Permanently
The most robust fix is to ensure both ends of the connection use UTF-8. On the remote Linux server, you can check if the desired locale is available by runninglocale -a | grep utf8. If en_US.UTF-8 is listed, you can set it permanently by adding export statements to your shell profile.
Edit the ~/.bashrc or ~/.profile file on the remote server and add the following lines:
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
After saving the file, source it using source ~/.bashrc or log out and back in. This forces every new session to use the correct encoding. If the locale is not installed on the server, you must install it first using your distribution’s package manager, such as sudo apt-get install locales on Debian-based systems, then generate it with sudo locale-gen en_US.UTF-8.
For Windows clients connecting via PuTTY, the setting is found under Connection > Data. Set the "Terminal-type string" to xterm and ensure the "Remote character set" is set to UTF-8. This aligns the client’s expectations with the server’s output.
Temporary Overrides for Specific Tasks
If you cannot modify system-wide settings due to permission restrictions, you can override the locale for specific commands. Prepend the environment variable to any command that requires correct encoding. For example, to view a file with proper encoding, run:LANG=en_US.UTF-8 less /var/log/syslog
This method is useful for troubleshooting because it isolates the issue. If the file displays correctly with the prefix, the problem is definitely in the persistent shell configuration. You can also use env to inspect the current environment before and after the override to confirm the change took effect.
Another common scenario involves file transfers. When using scp or rsync, encoding mismatches rarely affect the binary integrity of the transfer, but they can corrupt filenames containing special characters. To mitigate this, ensure the destination directory’s filesystem supports UTF-8 and that the mounting options do not force a different code page.
Advanced Troubleshooting Steps
If setting the locale does not resolve the issue, the problem may lie in the terminal emulator itself. Ensure your local terminal software is configured to send UTF-8 input. In GNOME Terminal, check Edit > Preferences > Advanced and verify the encoding is set to UTF-8. In macOS Terminal, go to Preferences > Profiles > Advanced and select Unicode (UTF-8). You should also check for alias conflicts. Sometimes, users create aliases for commands likecat or less that include flags forcing a specific encoding. Run type cat to see if an alias is defined. If so, remove it from your .bashrc or use the full path /bin/cat to bypass it during testing.
For more complex network setups, refer to Troubleshooting kex_exchange_identification Error in Linux SSH Connection. While that article focuses on key exchange failures, understanding the underlying SSH negotiation process helps diagnose why certain environment variables might be stripped or ignored during connection establishment.
Additionally, if you are managing multiple servers, consider standardizing your SSH configurations. See SSH: Creating Parameterized Config Entries for Tech Support for best practices on maintaining consistent connection parameters across different environments.
Frequently Asked Questions
Why do my files look correct locally but garbled remotely?
This indicates a mismatch between your local terminal’s expected encoding and the remote server’s actual output encoding. Your local machine renders bytes correctly based on its settings, but the remote shell is sending bytes interpreted differently by the viewer.
Can I fix encoding issues without root access on the remote server?
Yes, you can use temporary environment variable overrides for individual commands, such as LANG=UTF-8 command. However, you cannot change the system-wide default locale without administrative privileges, so this is only a partial workaround.
Does changing the locale affect file permissions or ownership?
No, changing the LANG or LC_ALL variables only affects text interpretation and display. It has no impact on file permissions, ownership, or the binary content of files. Only the way humans read the text changes.
What should I do if the required locale is not installed on the server?
You must install the locale package using your distribution’s package manager (e.g., apt-get install locales) and then generate it using locale-gen. Without generating the locale, the system cannot use it regardless of configuration changes.
Is it safe to set LC_ALL to UTF-8 on production servers?
It is generally safe and recommended, as UTF-8 is the modern standard for Linux systems. However, always test in a staging environment first to ensure that legacy applications relying on older encodings do not break unexpectedly.