As it was discussed in this question most programs don't have 'English' locale but use default ('C') locale with English messages instead. So if I want to use some languages with preferred English then I have to add 'C' locale right after the English locale in the list. In my case the 'LANGUAGES' must be:
LANGUAGES=en:C:ru
Which means "Use English then Default and then Russian". So every program which doesn't have English locale (because of using English locale as its default locale) will fall back to its default locale.
Someone may think that there is no effect in specifying Russian locale after 'default' because the default locale is always present and the Russian locale will never be chosen. It's true. But some programs (like browsers and text-editors) use the 'LANGUAGES' variable to get a list of user-spoken languages (like languages to request HTML-pages on, or languages for spell-checking) and in such cases Russian language won't be superfluous in the language list.
Then answer is that sudo
has a bug. First, the workaround: I put this in my /etc/sudoers.d/zabbix file
:
zabbix ALL=(root) NOPASSWD: /bin/env SHELL=/bin/sh /usr/local/bin/zabbix_raid_discovery
and now subcommands called from zabbix_raid_discovery
work.
A patch to fix this will be in sudo 1.8.15. From the maintainer, Todd Miller:
This is just a case of "it's always been like that". There's not
really a good reason for it. The diff below should make the behavior
match the documentation.
- todd
diff -r adb927ad5e86 plugins/sudoers/env.c
--- a/plugins/sudoers/env.c Tue Oct 06 09:33:27 2015 -0600
+++ b/plugins/sudoers/env.c Tue Oct 06 10:04:03 2015 -0600
@@ -939,8 +939,6 @@
CHECK_SETENV2("USERNAME", runas_pw->pw_name,
ISSET(didvar, DID_USERNAME), true);
} else {
- if (!ISSET(didvar, DID_SHELL))
- CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
/* We will set LOGNAME later in the def_set_logname case. */
if (!def_set_logname) {
if (!ISSET(didvar, DID_LOGNAME))
@@ -984,6 +982,8 @@
if (!env_should_delete(*ep)) {
if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
ps1 = *ep + 5;
+ else if (strncmp(*ep, "SHELL=", 6) == 0)
+ SET(didvar, DID_SHELL);
else if (strncmp(*ep, "PATH=", 5) == 0)
SET(didvar, DID_PATH);
else if (strncmp(*ep, "TERM=", 5) == 0)
@@ -1039,7 +1039,9 @@
if (reset_home)
CHECK_SETENV2("HOME", runas_pw->pw_dir, true, true);
- /* Provide default values for $TERM and $PATH if they are not set. */
+ /* Provide default values for $SHELL, $TERM and $PATH if not set. */
+ if (!ISSET(didvar, DID_SHELL))
+ CHECK_SETENV2("SHELL", runas_pw->pw_shell, false, false);
if (!ISSET(didvar, DID_TERM))
CHECK_PUTENV("TERM=unknown", false, false);
if (!ISSET(didvar, DID_PATH))
Best Answer
You can set any locale category independently.
LANG
applies only to the categories that are not explicitly set.LANG
andLC_xxx
are ordinary environment variables. They are not settings for thelocale
utility: thelocale
program isn't involved in any locale processing, it's just a small utility to report current and available locale settings.When you write
LC_TIME=ru_RU.utf8
, this doesn't set an environment variable, only a shell variable. Shell variables are internal to the shell, they are not seen by other programs. Environment variables, on the other hand, are inherited by the programs that the shell starts. You need to export the variable to the environment as well:or directly