É possível recuperar o ambiente original em um script de shell POSIX?

3

É possível recuperar o ambiente original com o qual um script de shell foi chamado? Eu não estou tentando escrever um programa que depende da capacidade de acessar o ambiente original, eu estou querendo saber se é garantido para ser inacessível .

Eu tenho um script de shell simples que cria uma nova variável de ambiente e altera o valor de PATH.

#!/bin/sh

PATH=/usr/bin
NEW_VAR=new_var_value; export NEW_VAR

env

Existe uma maneira de recuperar o valor original de PATH ou uma maneira de dizer que NEW_VAR não estava originalmente presente quando o script de shell foi executado?

Eu sei que argv , envp e o caminho para o executável estão todos definidos no início da chamada do sistema execv*(2) , mas não tenho certeza de "onde" ou "como" eles estão armazenados. Meu palpite é que a capacidade de manipular o vetor de argumentos usando shift e o ambiente usando export , unexport e atribuições na verdade não altera o que os argv e envp estão fundamentalmente definidos. Há apenas lógica dentro do shell para garantir que as novas chamadas para execv*(2) usem o envp correto ao chamar outro comando (por exemplo, some-command | LC_ALL=C sort ).

    
por Gregory Nisbet 19.02.2017 / 20:28

3 respostas

3

Enquanto um comando está em execução, a maioria dos sistemas permite que você exiba seu ambiente com o comando ps . Isso não pode ser feito portavelmente, e nem todos os sistemas permitem uma análise confiável, mas se tudo o que você quer é extrair partes “interessantes” do ambiente inicial de uma maneira que funcione em uma variante específica do Unix, isso é fácil. Por exemplo, no Linux e * BSD:

ps eww $$

Como alternativa, no Solaris e no Linux:

cat /proc/$$/environ

Ou no Solaris e AIX:

pargs -e $$

Se você precisar ocultar o conteúdo anterior do ambiente, certifique-se de que todos os processos do shell (incluindo os subshells em segundo plano) tenham saído. Para transmitir dados de uma maneira que não vaze dessa maneira, use um canal em vez de uma variável de ambiente.

exec sh -c 'unset pw; pw=$PASSWORD; unset PASSWORD; printf %s "$pw" | exec theprogram'

Observe que na maioria das variantes Unix (todas modernas), o ambiente de um processo é visível apenas para o mesmo usuário. Somente os argumentos são geralmente visíveis para qualquer usuário executando ps . Então, tudo bem passar dados confidenciais no ambiente; livrar-se dele é apenas uma questão de endurecimento, não de segurança básica.

    
por 19.02.2017 / 23:28
3

O próprio POSIX não fornece nenhuma maneira de fazer isso da caixa. Existem algumas maneiras que eu posso pensar para chegar perto disso:

  1. Observe o ambiente presente no pai (por exemplo, com /proc/pid/environ no Linux) e preencha o ambiente do zero com base nisso. Isso pode ou não funcionar desde
    • O pai pode não necessariamente ter o mesmo ambiente que o filho começou com
    • O pai pode não existir mais
    • O filho pode não ter acesso ao ambiente do pai (por exemplo, no caso de eliminar privilégios)
  2. Salve o ambiente no início do seu script (por exemplo, usando export -p ou /proc/self/environ no início) e restaure-o mais tarde. Isso funciona bem, mas você precisa escrever a lógica para restaurá-la.
  3. Quando você define um novo ambiente varable, faça-o através de uma função que primeiro armazena o valor antigo da variável e depois você pode restaurá-lo através da mesma função (ou manualmente, armazenando em $OLD_PATH ) . Isso funciona, mas é complicado e é fácil esquecer de fazê-lo. Por exemplo:
$OLD_PATH=$PATH
# do something
$PATH=$OLD_PATH
    
por 19.02.2017 / 20:48
1

Se você quiser saber o estado do ambiente antes de qualquer modifs, então por que você não o salva antes para fazer qualquer coisa. Por exemplo,

#!/bin/sh
PATH_orig=$PATH; # save the original PATH
case ${NEW_VAR++} in
   ? ) echo 'Achtung: NEW_VAR is already in the original environment' ;;
   * ) echo 'NEW_VAR not found in the original environment' ;;
esac

OLD_ENV=$(export -p) # will save your original env in a source-able manner

### And now make your changes...
PATH=/usr/bin
NEW_VAR="foo"; export NEW_VAR
    
por 19.02.2017 / 20:50

Tags