Como iniciar um script com ambiente limpo?

12

Eu tentei o seguinte, mas parece que não funciona:

$ cat script.sh
#!/bin/env -i /bin/sh

/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try '/bin/env --help' for more information.
    
por balki 04.11.2013 / 17:39

5 respostas

4

O motivo pelo qual isso não funciona é porque ele vê -i /bin/sh como um único argumento para env . Normalmente, isso seria 2 argumentos, -i e /bin/sh . Esta é apenas uma limitação do shebang. Não há maneira de contornar isso.

No entanto, você ainda pode realizar essa tarefa de uma maneira diferente.

Se você quiser que essa tarefa seja executada pelo próprio script e não precise fazer algo como env -i script.sh , poderá fazer com que o script seja executado novamente.

#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"

Isso fará com que o script seja novamente executado se a variável de ambiente CLEANED não estiver definida. Então, no re-exec, ele define a variável para garantir que ela não entre em loop.

    
por 04.11.2013 / 19:14
3

Execute seu script com env -i :

env -i script.sh

E o roteiro como de costume:

#!/bin/sh
# ... your code here

Se você pretende executar com um ambiente limpo, sem explicitamente dizer isso quando for executado. Eduardo Ivanec dá algumas ideias em esta resposta , você pode chamar recursivamente seu script com exec quando o ambiente não estiver limpo ( por exemplo, $ HOME está definido):

[ "$HOME" != "" ] && exec -c $0
    
por 04.11.2013 / 18:16
1

Com o bash, você pode fazer assim:

#!/usr/bin/bash

set -e
set -u

[ -v HOME ] && exec -c "$0" "$@"

# continue with the rest of the script
# e.g. print the cleaned environment:
export

Os comandos set -e e set -u não são estritamente necessários, mas incluo-os para demonstrar que essa abordagem não depende do acesso a variáveis não definidas (como, por exemplo, [ "$HOME" != "" ] ) e é compatível com set -e configuração.

O teste da variável HOME deve ser seguro porque o bash executa scripts no modo não interativo, ou seja, arquivos de configuração como ~/.bashrc (onde variáveis de ambiente podem ser definidas) não são originados durante a inicialização.

Exemplo de saída:

declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"
    
por 19.03.2016 / 10:27
0

$ cat script.sh

#!/bin/env -i /bin/sh

Infelizmente, isso não funcionará dessa forma - o Linux considera -i /bin/sh como um argumento a ser passado para env (veja Shebang ).

    
por 04.11.2013 / 18:33
0

A limitação shebang do argumento 2 do Linux (interpeter + argumento único) é observada na maioria das respostas, mas dizer que isso não pode ser feito está incorreto - você só precisa mudar para um interpretador que possa fazer algo útil com um único argumento:

#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here

O que isto faz é invocar perl com um script de uma linha ( -e ) que limpa %ENV (mais barato que env -i ) e invoca exec /bin/sh , citando corretamente os argumentos. Outras perl logic podem ser adicionadas, se necessário (embora não muito no Linux, já que você está limitado a BINPRM_BUF_SIZE caracteres, o que é provável 128)

Infelizmente, isso é específico do Linux, não funcionará em um sistema que permita múltiplos argumentos: - /

perl processa esta string como um único argumento, então ela não é citada acima como você normalmente faria com perl -e ... da linha de comando (se você fosse adicionar aspas, elas são preservadas, perl vê apenas uma string literal, com avisos sobre ela que se queixam de uma constante inútil).

Observe também que há uma pequena alteração no comportamento quando usada dessa forma, @ARGV normalmente contém apenas os argumentos e $0 contém o script, mas com este shebang $ARGV[0] é o nome do script (e $0 é -e ) o que torna isso um pouco mais fácil.

Você também pode resolver isso com um intérprete que "reprocessa" sua linha de comando (sem um argumento -c extra) o antigo AT & T ksh93 :

#!/bin/ksh /usr/bin/env -i /bin/sh

embora talvez ksh não seja tão comum hoje em dia; -)

( bash tem um recurso semelhante com --wordexp , mas é "não documentado" nas versões em que funciona, e não habilitado em tempo de compilação nas versões em que está documentado: - / Também não pode ser usado para isso, pois precisa de dois argumentos ...)

Além disso, efetivamente, uma variação nas respostas do @Patrick e @ maxschlepzig:

#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here

Em vez de usar uma nova variável, ela usa a variável especial " _ ", se não estiver definida como "bash", substitua o script por exec usando -a para gerar ARGV[0] (e, portanto, $_ ) apenas "bash" e usando -c para limpar o ambiente.

Como alternativa, se for aceitável limpar o ambiente no início do script (apenas bash):

#!/bin/sh
unset $(compgen -e)
# your script here

Utiliza compgen (ajudante de conclusão) para listar os nomes de todas as variáveis de ambiente exportadas e unset s de uma só vez.

Veja também Múltiplos argumentos em shebang para mais detalhes sobre o problema geral da shebang comportamento.

    
por 05.07.2018 / 14:51