I have a fresh ubuntu 12.04 installation. When i connect to my remote server i got errors like this:

~$ ssh example.com sudo aptitude upgrade
...
Traceback (most recent call last):
  File "/usr/bin/apt-listchanges", line 33, in <module>
    from ALChacks import *
  File "/usr/share/apt-listchanges/ALChacks.py", line 32, in <module>
    sys.stderr.write(_("Can't set locale; make sure $LC_* and $LANG are correct!\n"))
NameError: name '_' is not defined
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
    LANGUAGE = (unset),
    LC_ALL = (unset),
    LC_TIME = "de_DE.UTF-8",
    LC_MONETARY = "de_DE.UTF-8",
    LC_ADDRESS = "de_DE.UTF-8",
    LC_TELEPHONE = "de_DE.UTF-8",
    LC_NAME = "de_DE.UTF-8",
    LC_MEASUREMENT = "de_DE.UTF-8",
    LC_IDENTIFICATION = "de_DE.UTF-8",
    LC_NUMERIC = "de_DE.UTF-8",
    LC_PAPER = "de_DE.UTF-8",
    LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_ALL to default locale: No such file or directory
No packages will be installed, upgraded, or removed.
0 packages upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B of archives. After unpacking 0 B will be used.
...

I don't have this problem when i connect from an older ubuntu installation. This is output from my ubuntu 12.04 installation, LANG and LANGUAGE are set

$ locale
LANG=de_DE.UTF-8
LANGUAGE=de_DE:en_GB:en
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC=de_DE.UTF-8
LC_TIME=de_DE.UTF-8
LC_COLLATE="de_DE.UTF-8"
LC_MONETARY=de_DE.UTF-8
LC_MESSAGES="de_DE.UTF-8"
LC_PAPER=de_DE.UTF-8
LC_NAME=de_DE.UTF-8
LC_ADDRESS=de_DE.UTF-8
LC_TELEPHONE=de_DE.UTF-8
LC_MEASUREMENT=de_DE.UTF-8
LC_IDENTIFICATION=de_DE.UTF-8
LC_ALL=

Does anybody know what has changed in ubuntu to get this error message on remote servers?

up vote 160 down vote accepted

That's because your locale in your local machine is set to German, which SSH forwards to and tries to use on the server, but your server does not have it installed.

You've got several options:

  • Generate the locale. Generate the German locale on the server with sudo locale-gen de.

  • Stop forwarding locale from the client. Do not forward the locale environment variable from your local machine to the server. You can comment out the SendEnv LANG LC_* line in the local /etc/ssh/ssh_config file.

  • Stop accepting locale on the server. Do not accept the locale environment variable from your local machine to the server. You can comment out the AcceptEnv LANG LC_* line in the remote /etc/ssh/sshd_config file.

  • Set the server locale to English. Explicitly set the locale to English on the server. As an example, you can add the following lines to your remote ~/.bashrc or ~/.profile files:

    export LANGUAGE="en"
    export LANG="C"
    export LC_MESSAGES="C"
    

If you don't have root access to the server, the Stop forwarding locale from the client option might be the best (and only) way to go.

  • 2
    Hah! I totally missed the fact that he listed the client's locale settings! Great job... – ish May 31 '12 at 7:29
  • 10
    I decided to "Stop forwarding locale from the client". Works fine. For future reference: you can't override SendEnv settings from /etc/ssh/ssh_config in your local ~/.ssh/config. See bugzilla.mindrot.org/show_bug.cgi?id=1285 – Janning Jun 3 '12 at 23:50
  • 3
    Combined with bugs.php.net/bug.php?id=18556, SSH's sending of locales can cause real problems (and caused for me actually), see bugzilla.mindrot.org/show_bug.cgi?id=1285#c9 ... – Halil Özgür Nov 14 '13 at 17:00
  • 1
    In my case, setting locale in ~/.profile solved my issue. Thanks. – Francisco Apr 6 '17 at 18:27
  • If the server does not have German locale, why is it acceptable for it to overwrite the user-requested value of LANG with something else?.. – Mikhail T. Jul 11 '17 at 20:38

This can happen sometimes on fresh minimal/alternate installs or in other situations. The fix is pretty simple. Try these, in the following order, testing after each to see if the situation is fixed:

1. Reconfigure locales

  • sudo dpkg-reconfigure locales
    • if that doesn't work,

2. Reinstall locale language-pack

  • sudo apt-get --reinstall install language-pack-de
    • if that doesn't work,

3. Manually force locale settings (persistent)

  • sudo update-locale LC_ALL=de_DE.UTF-8 LANG=de_DE.UTF-8
  • I have a JVM problem and I'm trying to set the system locale in 12.04 also. Only problem is I can't seem to set the LC_ALL no matter what I try, locales still shows it as empty. – Dark Star1 Dec 11 '12 at 1:09

Comment the line SendEnv LANG LC_* in /etc/ssh/ssh_config, so it should looks like:

#SendEnv LANG LC_*

The Problem

By default, the ssh client command forwards locale-related environment variables to the SSH server. That's specified in /etc/ssh/ssh_config on the client side:

Host *
    SendEnv LANG LC_*

And by default, the SSH server happens to accept them (in /etc/ssh/sshd_config on the server):

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

So, if there are locale-related environment variables in your shell, they will be populated to the SSH session on the server side.

Unfortunately, the SendEnv option is cumulative. According to man 5 ssh_config:

 SendEnv
         ... Multiple environment variables may be separated
         by whitespace or spread across multiple SendEnv directives.  The
         default is not to send any environment variables.

which means it can't be overridden.

The Solution

Sometimes it's impossible or unwise to change a system-wide configuration, especially on the server side. However, you may bypass it. And that's the side effect of the -F option in ssh command. According to man ssh:

 -F configfile
         Specifies an alternative per-user configuration file.  If a con-
         figuration file is given on the command line, the system-wide
         configuration file (/etc/ssh/ssh_config) will be ignored.  The
         default for the per-user configuration file is ~/.ssh/config.

By default the per-user configuration file ~/.ssh/config is used if it presents. But you can explicitly specify it on the command line to bypass /etc/ssh/ssh_config:

$ touch ~/.ssh/config
$ ssh -F ~/.ssh/config your_user@your_host

It would be more convenient if you make an alias in ~/.bashrc:

alias ssh="ssh -F ~/.ssh/config"

This way, the default SendEnv directives in system-wide configuration are not effective, making no environment variables be sent to the SSH server by default.

  • 2
    Bear in mind that the system configuration file in /etc/ssh/config may contain additional lines that you wish to retain in your user configuration. You'll have to copy them over to your user config file in ~/.ssh/config to keep those settings. – Steven Maude Jan 23 '17 at 16:35

I had a similar issue. My solution was to comment the SendEnv lines in /etc/ssh/ssh_config (since these cannot be overriden), and to add the following entry in ~/.ssh/config:

Host *,!<somehost>
    SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
    SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
    SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
    SendEnv XMODIFIERS    

with <somehost> being the hostname to which I didn't want to send any environment variable.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.