Eu quero executar um subshell bash, (1) executar alguns comandos, (2) e permanecer nesse subshell para fazer o que eu quiser. Eu posso fazer cada um destes individualmente:
Execute o comando usando o
-c
sinalizador:$> bash -c "ls; pwd; <other commands...>"
no entanto, ele retorna imediatamente ao shell "super" após a execução dos comandos. Também posso apenas executar um subshell interativo:
Iniciar novo
bash
processo:$> bash
e não sairá do subshell até que eu o diga explicitamente ... mas não consigo executar nenhum comando inicial. A solução mais próxima que encontrei é:
$> bash -c "ls; pwd; <other commands>; exec bash"
que funciona, mas não da maneira que eu queria, pois executa os comandos fornecidos em um subshell e, em seguida, abre um separado para interação.
Eu quero fazer isso em uma única linha. Depois de sair do subshell, devo retornar ao shell "super" comum sem incidentes. Deve haver uma maneira ~~
NB: O que não estou perguntando ...
- não perguntando onde obter a página de manual do bash
- sem perguntar como ler comandos de inicialização de um arquivo ... Eu sei como fazer isso, não é a solução que estou procurando
- não estou interessado em usar a tela tmux ou gnu
- não está interessado em dar contexto a isso. Ou seja, a questão é para ser geral, e não para qualquer finalidade específica
- se possível, quero evitar o uso de soluções alternativas que atinjam o que quero, mas de maneira "suja". Eu só quero fazer isso em uma única linha. Em particular, não quero fazer algo como
xterm -e 'ls'
exec bash
solução é inadequada para você?exec bash
solução envolve dois subshells separados. Eu quero um subshell contínuo.exec
é que ele substitui o primeiro subshell pelo segundo, então você fica apenas 1 shell abaixo do pai. Se seus comandos de inicialização configurarem variáveis de ambiente, elas existirão no shell executado.exec
é que você perde nada que não seja passada para subshells através do ambiente, tais como variáveis não exportado, funções, aliases ...Respostas:
Isso pode ser feito facilmente com pipes nomeados temporários :
O crédito por esta resposta vai para o comentário de Lie Ryan . Achei isso realmente útil, e é menos perceptível nos comentários, então achei que deveria ser sua própria resposta.
fonte
$HOME/.bashrc
não é executado. Teria que ser incluído no pipe nomeado temporário.bash --init-file <(echo ". \"$HOME/.bashrc\"; ls; pwd")
.
é um sinônimo para osource
comando: ss64.com/bash/source.html .sudo bash --init-file <(echo "ls; pwd")
ousudo -iu username bash --init-file <(echo "ls; pwd")
?Você pode fazer isso de maneira indireta com um arquivo temporário, embora isso leve duas linhas:
fonte
rm $BASH_SOURCE
nele.mktemp
resolve o problema do arquivo temporário, como o @cjc apontou. O Bash poderia suportar a leitura dos comandos init do stdin, mas até onde eu sei, não. Especificar-
como arquivo init e canalizá- los pela metade funciona, mas o Bash sai (provavelmente porque detectou o pipeline). A solução elegante, IMHO, é usar exec.Tente isso:
$SHELL
Ele abre o shell no modo interativo, aguardando um encerramento com eleexit
.fonte
A "solução Expect" à qual me referi está programando um shell bash com a linguagem de programação Expect :
Você executaria isso como:
./subshell.exp "ls; pwd"
fonte
Por que não usar subshells nativos?
A inclusão de comandos entre parênteses torna o bash spawn um subprocesso para executar esses comandos, para que você possa, por exemplo, alterar o ambiente sem afetar o shell pai. Isso é basicamente mais legível equivalente ao
bash -c "ls; pwd; exec $BASH"
.Se isso ainda parecer detalhado, há duas opções. Uma é ter esse trecho como função:
Outra é
exec $BASH
diminuir:Eu, pessoalmente, gosto de
R
abordar mais, pois não há necessidade de brincar com cordas que escapam.fonte
Se
sudo -E bash
não funcionar, use o seguinte, que atendeu às minhas expectativas até agora:Defino HOME = $ HOME porque quero que minha nova sessão tenha HOME definida como HOME do usuário, em vez de HOME da raiz, o que acontece por padrão em alguns sistemas.
fonte
menos elegante do que
--init-file
, mas talvez mais instrumentável:fonte