É possível executar alguns comandos em um subshell sem sair imediatamente depois?

5

Eu uso o fish shell e gostaria de poder "fornecer" alguns scripts de shell escritos com sintaxe compatível com sh, cujo peixe não pode ler . Por exemplo, muitos softwares esperam que você crie alguns scripts de shell para exportar variáveis de ambiente úteis:

# customvars.sh
FOOBAR=qwerty
export FOOBAR

Se eu não me preocupo com a preservação de variáveis locais e definições de funções, uma solução é usar exec para substituir o processo atual com / bin / sh e depois voltar para o fish

# We start out on fish
exec /bin/sh
# Running a POSIX shell now
. customvars.sh
exec /usr/bin/fish
# Back on fish
echo $FOOBAR

Existe uma maneira de resumir este padrão a um one-liner que eu possa salvar em uma função em algum lugar? Se eu tentar fazer

exec /bin/sh -c '. vars.sh; /usr/bin/fish'

minha janela do emulador de terminal é fechada imediatamente em vez de me levar de volta a um prompt interativo de peixes.

    
por hugomg 19.05.2015 / 16:55

3 respostas

1

Para o problema específico de ter scripts em linguagem shell compatível com POSIX que definem variáveis de ambiente e desejam usá-los em fish, uma solução existente é Bass . É um script que funciona de forma semelhante à resposta de terdon, mas pode lidar com mais casos específicos.

    
por 28.08.2016 / 21:02
4

O problema está em como você está chamando o . special builtin:

exec /bin/sh -c '. vars.sh; /usr/bin/fish'

Em sh , se o argumento não contiver / , . procurará o arquivo em $PATH . Então, acima, seria procurar por vars.sh em $PATH em vez do diretório atual como você pretendia.

Além disso, . sendo um especial embutido, sua falha faz com que o shell saia (quando não interativo), então o próximo comando (aqui fish ) não é executado, e é por isso que a janela do emulador de terminal desaparece sem um prompt fish .

Isso pode ser evitado chamando . as command . , que remove o atributo especial dos especiais .

Note que o comportamento de bash (a implementação sh do projeto GNU) é diferente a esse respeito quando não está no modo POSIX (quando não é chamado como sh , nem com --posix , e quando o ambiente não contém POSIXLY_CORRECT= nem SHELLOPTS=posix ):

bash ' . não faz com que o shell saia após a falha e procura por um argumento sem barra no diretório atual se não puder encontrá-lo em $PATH .

Em qualquer caso, no modo POSIX ou não, se você quiser o vars.sh no diretório atual, precisará da sintaxe ./vars.sh . Então é

exec sh -c 'command . ./vars.sh; exec fish'
    
por 19.05.2015 / 22:54
1

Pessoalmente, gostaria de uma abordagem diferente. Presumivelmente, você precisa do arquivo no formato bourne por outros motivos. Por que não apenas obtê-lo em peixes alterando o formato na hora? Algo como:

source (sed -nr 's/(.+)=(.+)/set  /p' file | psub)

O acima é o equivalente de peixe

source <(sed -nr 's/(.+)=(.+)/set  /p' file)

Por exemplo:

> cat file
foo="baz"
export foo
> source (sed -nr 's/(.+)=(.+)/set  /p' | psub)
> echo $foo
baz

NOTA: Isso pressupõe que o script de origem apenas define variáveis, conforme descrito na pergunta, e uma definição de variável por linha. Para operações mais complexas, essa abordagem não funcionará.

    
por 19.05.2015 / 17:43

Tags