Como obter as variáveis de localidade de qualquer processo?

1

Quando eu executo o comando locale no terminal, as variáveis de localidade do shell serão impressas.

Existe uma maneira de obter as variáveis de localidade de qualquer outro processo (além do shell)?

    
por James 12.06.2018 / 06:38

2 respostas

2

Com o GNU xargs no Linux:

xargs -r0a "/proc/$pid/environ" sh -c 'exec env -i -- "$@" locale' sh

Executaria locale em uma cópia do ambiente em que o processo de pid $pid passou para o último comando executado.

Note que locale sendo externo, ele só se preocupa com variáveis de ambiente, não com variáveis de shell se elas não foram exportadas.

O próprio shell pode ter suas configurações de localização afetadas, mesmo se as variáveis LC_* , LANG , LANGUAGE não forem exportadas.

Algumas notas de cautela:

  • Os programas que usam localização geralmente usam setlocale(LC_ALL, "") para inicializar todas suas configurações de localização com base no ambiente, mas não precisam.
  • Eles podem chamar setlocale() com parâmetros diferentes (improváveis).
  • Eles podem chamá-lo antes de depois de modificar seu ambiente (com APIs como putenv() / setenv() ).
  • Esses putenv() / setenv() tradicionalmente não modificam a área exposta por /proc/$pid/environ , mas o IIRC está mudando nas versões recentes do Linux e da GNU libc.
  • Independentemente daqueles putenv() / setenv() , o processo pode acabar modificando sua área da pilha exposta por /proc/$pid/environ (improvável).

Outra opção seria anexar o gdb ao processo e fazer:

call system("locale")

Isso é bastante intrusivo.

Essa pessoa usaria o ambiente preparado pelo próprio processo (assumindo que ele usa environ e / ou putenv() / setenv() , o que nem todas as aplicações, especialmente shells, por exemplo, fazem).

Com o gdb, você também pode consultar as configurações de localização diretamente chamando setlocale() para cada categoria de local com um segundo argumento NULL.

Para saber o valor de uma determinada categoria:

$ printf '#include <locale.h>\nLC_COLLATE\n' | gcc -E -x c - | tail -n 1
3

Para imprimir o nome da localidade em gdb :

(gdb) p (char*)setlocale(3, 0)
$3 = 0xde8f40 "en_GB.UTF-8"

Ou:

(gdb) x/s setlocale(3, 0)
0xde8f40:       "en_GB.UTF-8"
    
por 12.06.2018 / 07:54
0

Mesmo no shell, chamar locale nem sempre lhe dará resultados confiáveis.

O Bourne Shell, e. Importa variáveis de ambiente para as variáveis do shell local e encaminha os valores importados para seus filhos, mas ao mesmo tempo permite modificar as variáveis locais relacionadas sem modificar o valor exportado. A configuração do código de idioma do Bourne Shell é baseada nos valores internos das variáveis do shell e não no ambiente importado ou exportado.

Como isso se aplica às variáveis LC_ *, o Bourne Shell pode ser executado em um código do idioma diferente dos relatórios do comando locale . BTW: você pode mudar isso chamando set -o posix no Bourne Shell ... para dizer ao Bourne Shell para sincronizar valores exportados de variáveis importadas com o valor interno.

Ainda mais: desde o POSIX.1-2008, existe uma maneira de permitir que um programa use várias localidades ao mesmo tempo. Isto é, e. importante para compiladores que gostam de analisar, e. constantes de ponto flutuante no C locale baseado nos EUA, onde o separador de fração flutuante incomum '.' é usado, ao mesmo tempo em que fornece avisos e outras saídas com base em um código do idioma diferente.

O mesmo método também é usado com freqüência para permitir que programas encadeados usem locais diferentes para encadeamentos diferentes.

Como você pode ver, observar o ambiente de outros programas só pode fornecer uma visão geral aproximada do que a localidade pode ser, mas nunca retorna resultados verdadeiros concedidos.

    
por 12.06.2018 / 13:59

Tags