Problema : descubra quantas conchas eu tenho.
Detalhes : Eu abro muito o shell do vim. Construa, execute e saia. Às vezes eu esqueço e abro outro vim dentro e depois outro shell. :(
Quero saber quantas conchas de profundidade tenho, talvez até tê-la na tela do meu shell o tempo todo. (Eu posso gerenciar essa parte).
Minha solução : Analise a árvore de processos e procure por vim e bash / zsh e descubra a profundidade do processo atual.
Algo assim já existe? Não consegui encontrar nada.
$SHLVL
variável (mantida por várias conchas) é o que você está procurando?fg
voltar, o que não tem esse problema.vim
trabalhos paralelos interrompidos pode ser mais confuso do que ter uma pilha de processos aninhados. A propósito, prefiro ter várias janelas , para poder ir e voltar rapidamente com facilidade, mas não chamaria isso de problema XY apenas porque prefiro um fluxo de trabalho diferente.Respostas:
Quando li sua pergunta, meu primeiro pensamento foi
$SHLVL
. Então vi que você queria contarvim
níveis além dos níveis de shell. Uma maneira simples de fazer isso é definir uma função shell:Isso aumentará automaticamente e silenciosamente
SHLVL
toda vez que você digitar umvim
comando. Você precisará fazer isso para cada variante devi
/vim
que você usar; por exemplo,O conjunto externo de parênteses cria um subshell, portanto, a alteração manual no valor de
SHLVL
não contamina o ambiente atual do shell (pai). Obviamente, acommand
palavra-chave existe para impedir que as funções se chamem (o que resultaria em um loop infinito de recursão). E é claro que você deve colocar essas definições no seu.bashrc
ou em outro arquivo de inicialização do shell.Há uma ligeira ineficiência no exposto acima. Em algumas conchas (bash sendo uma), se você disser
Onde é um programa executável externo (ou seja, não um comando interno), o shell mantém um processo extra por aí, apenas para aguardar o término. Isso é (sem dúvida) desnecessário; as vantagens e desvantagens são discutíveis. Se você não se importa em amarrar um pouco de memória e um slot de processo (e ver mais um processo de shell do que o necessário quando faz um ), faça o acima e pule para a próxima seção. O mesmo se você estiver usando um shell que não mantém o processo extra por aí. Mas, se você quiser evitar o processo extra, a primeira coisa a tentar é
cmdn
cmdn
ps
O
exec
comando existe para impedir que o processo de shell extra permaneça.Mas, há uma pegadinha. O manuseio do shell
SHLVL
é um tanto intuitivo: quando o shell inicia, ele verifica seSHLVL
está definido. Se não estiver definido (ou definido como algo diferente de um número), o shell o definirá como 1. Se estiver definido (como um número), o shell adicionará 1 a ele.Mas, por essa lógica, se você diz
exec sh
, vocêSHLVL
deve subir. Mas isso é indesejável, porque o seu nível real de shell não aumentou. O shell lida com isso subtraindo um deSHLVL
quando você faz umexec
:assim
é uma lavagem; ele é incrementado
SHLVL
apenas para diminuí-lo novamente. Você pode apenas dizervim
, sem o benefício de uma função.Para consertar isso, você faria
Então vi que você queria contar
vim
níveis independentemente dos níveis do shell. Bem, exatamente o mesmo truque funciona (bem, com uma pequena modificação):(e assim por diante para
vi
,view
, etc.) Aexport
é necessária porqueVILVL
não é definido como uma variável de ambiente por padrão. Mas não precisa fazer parte da função; você pode apenas dizerexport VILVL
como um comando separado (no seu.bashrc
). E, como discutido acima, se o processo extra de shell não for um problema para você, você pode fazer emcommand vim
vez deexec vim
e deixar emSHLVL
paz:Se você estiver usando um shell que não suporta
SHLVL
(por exemplo, traço), poderá implementá-lo você mesmo, desde que o shell implemente um arquivo de inicialização. Basta fazer algo comono seu
.profile
arquivo ou aplicável. (Você provavelmente não deve usar o nomeSHLVL
, pois isso causará caos se você começar a usar um shell compatívelSHLVL
.)Outras respostas abordaram a questão de incorporar valores da variável de ambiente no prompt do shell, então não vou repetir isso, especialmente você diz que já sabe como fazê-lo.
fonte
ps
oupstree
, quando você pode fazer isso com os shell builtins.dash
possui expansão aritmética.SHELL_LEVEL=$((SHELL_LEVEL + 1))
deve ser suficiente, mesmo que $ SHELL_LEVEL estivesse anteriormente desmarcado ou vazio. É somente se você tivesse que ser portátil para o shell Bourne que você precisa de recorrer aexpr
, mas então você também precisaria para substituir$(...)
com`..`
.SHELL_LEVEL=`expr "${SHELL_LEVEL:-0}" + 1`
bash
script a ler ~ / .bashrc por tornando stdin um soquete, por exemplo), isso pode se tornar um problema. Isso é um monte de "se" s, mas algo para se manter na parte de trás da mente (dados unsanitized em contexto aritmética é perigoso)Você pode contar quantas vezes precisar para subir na árvore de processos até encontrar um líder de sessão. Como
zsh
no Linux:Ou POSIXly (mas menos eficiente):
Isso daria 0 para o shell iniciado pelo emulador de terminal ou getty e mais um para cada descendente.
Você só precisa fazer isso uma vez na inicialização. Por exemplo, com:
no seu
~/.zshrc
ou equivalente para tê-lo em seu prompt.tcsh
e vários outros conchas (zsh
,ksh93
,fish
ebash
pelo menos) manter uma$SHLVL
variável que incrementar na inicialização (e decréscimo antes de executar outro comando comexec
(a menos queexec
seja em um subshell se eles não estão de buggy (mas muitos são))). Isso apenas rastreia a quantidade de aninhamento de shell , não o processo de aninhamento. Também não é garantido que o nível 0 seja o líder da sessão.fonte
Use
echo $SHLVL
. Use o princípio KISS . Dependendo da complexidade do seu programa, isso pode ser suficiente.fonte
bash
, mas não paradash
.Uma solução potencial é olhar para a saída de
pstree
. Quando executado dentro de uma concha gerada por dentrovi
, a parte da árvore listadapstree
deve mostrar a sua profundidade. Por exemplo:fonte
Primeira variante - apenas profundidade da casca.
Solução simples para
bash
: adicionar às.bashrc
próximas duas linhas (ou alterar seuPS1
valor atual ):Resultado:
O número no início da string de prompt será denotado no nível do shell.
Segunda variante, com níveis aninhados de vim e shell.
adicione estas linhas ao
.bashrc
Resultado:
v: 1 - nível de profundidade do vim
s: 3 - nível de profundidade do shell
fonte
Na pergunta que você mencionou a análise de
pstree
. Aqui está uma maneira relativamente simples:As
pstree
opções:-A
- Saída ASCII para filtragem mais fácil (no nosso caso, todos os comandos são precedidos por`-
)-a
- show também argumentos de comando, como efeito colateral, todos os comandos são mostrados em uma linha separada e podemos filtrar facilmente a saída usandogrep
-l
- não trunque linhas longas-s
- mostra os pais do processo selecionado(infelizmente não é suportado nas versões antigas do
pstree
)$$
- o processo selecionado - o PID do shell atualfonte
Isso não responde estritamente à pergunta, mas em muitos casos pode ser desnecessário:
Quando você iniciar seu shell, execute
set -o ignoreeof
. Não coloque no seu~/.bashrc
.Crie o hábito de digitar Ctrl-D quando achar que está no shell de nível superior e deseja ter certeza.
Se você não estiver no shell de nível superior, Ctrl-D sinalizará "fim da entrada" para o shell atual e você retornará um nível.
Se você estiver no shell de nível superior, receberá uma mensagem:
Eu uso isso o tempo todo em sessões SSH encadeadas, para facilitar o retorno a um nível específico da cadeia SSH. Também funciona para conchas aninhadas.
fonte