Eu tentei which cd
e não deu um caminho, mas retornou o código de saída 1 (verificado com echo $?
). O coreutil em cd
si está funcionando, então o executável deve estar lá, certo? Também executei um find
para cd
, mas não foi mostrado nenhum arquivo executável. Como é implementado então?
Atualizar:
Não sei se devo perguntar isso em outro post, mas como acho que é bom aqui, estou expandindo (?) O post ... Então a resposta foi realmente bastante simples, não há executável para isso - porque é um builtin - Mas eu descobri que alguns builtins (bash shell no Fedora) têm os arquivos executáveis! Então embutido -> nenhum executável não está certo, suponho? Talvez uma resposta que explique o que são realmente os builtins (comandos internos?), O que realmente é o problema aqui, em vez de se concentrar mais em cd
... Alguns bons links publicados anteriormente indicam que os builtins não são programas ... então, o que são? Como eles funcionam? Eles são apenas funções ou threads do shell?
fonte
type
comandocd
precisa ser incorporado: Por que o CD não é um programa? e este sobre por quetype
é melhor quewhich
: Por que não usar "what"? O que usar então?Respostas:
O comando
cd
não pode ser um executávelEm um shell,
cd
é usado para "entrar em outro diretório", ou mais formalmente, para alterar o diretório de trabalho atual (CWD). É impossível implementar isso como um comando externo:O diretório pertence a um processo
O diretório de trabalho atual é o diretório usado para interpretar caminhos relativos para obter um caminho completo que pode ser usado para acessar arquivos. Caminhos relativos são usados em muitos lugares, e a interpretação em um processo não deve influenciar outro processo.
Por esse motivo, todo processo tem seu próprio diretório de trabalho atual.
cd
é sobre alterar o diretório de trabalho atual do processo de shell, por exemplobash
.Se fosse um comando externo, um executável no caminho, a execução desse executável criaria um processo com seu próprio diretório de trabalho, sem influenciar o do shell atual. Mesmo que o comando externo altere seu diretório, essa alteração desaparece quando o processo externo é encerrado.
Comandos internos do shell
Portanto, não faz sentido executar um comando externo para a tarefa de
cd
. O comandocd
precisa aplicar uma alteração ao processo de shell atualmente em execução.Para fazer isso, é um "comando interno" do shell.
Comandos internos são comandos que se comportam de maneira semelhante aos comandos externos, mas são implementados no shell (portanto,
cd
não faz parte dos coreutils). Isso permite que o comando altere o estado do próprio shell, neste caso, para chamarchdir()
see (seeman 2 chdir
);Sobre
which
Agora, a resposta para a pergunta do título é fácil:
O comando executável
which
não pode nos dizer que cd é um comando embutido porque um comando executável não sabe nada sobre os embutidos.Alternativo
type -a
Como alternativa
which
, você pode usartype -a
; Pode ver comandos executáveis e embutidos; Além disso, ele vê aliases e funções - também implementados no shell:fonte
cd
um shell está embutido.cd
é um shell mandatado pelo POSIX embutido:Embora isso não diga explicitamente que deve ser um built-in, a especificação continua a dizer, na descrição de
cd
:Do
bash
manual :Suponho que você possa pensar em uma arquitetura em
cd
que não precise ser incorporada. No entanto, você precisa ver o que um built-in implica. Se você escrever um código especial no shell para executar algo em algum comando, estará chegando perto de ter um builtin. Quanto mais você faz, melhor é simplesmente ter um builtin.Por exemplo, você poderia fazer com que o shell tivesse IPC para se comunicar com subprocessos, e haveria um
cd
programa que verificaria a existência do diretório e se você tem permissão para acessá-lo e depois se comunica com o shell para solicitar que ele mude seu diretório. diretório. No entanto, você deverá verificar se o processo de comunicação com você é filho (ou criar meios especiais de comunicação apenas com filhos, como um descritor de arquivo especial, memória compartilhada etc.) e se o processo é de fato executando ocd
programa confiável ou outra coisa. Essa é uma lata inteira de vermes.Ou você pode ter um
cd
programa que faz achdir
chamada do sistema e inicia um novo shell com todas as variáveis de ambiente atuais aplicadas ao novo shell e, em seguida, mata seu shell pai (de alguma forma) quando concluído. 1 1Pior, você pode até ter um sistema em que um processo possa alterar os ambientes de outros processos (acho que tecnicamente você pode fazer isso com depuradores). No entanto, esse sistema seria muito, muito vulnerável.
Você se encontrará adicionando cada vez mais código para proteger esses métodos, e é consideravelmente mais simples simplesmente torná-lo um componente interno.
O fato de algo ser um executável não impede que ele seja incorporado. Caso em questão:
echo
etest
echo
etest
são utilitários mandados pelo POSIX (/bin/echo
e/bin/test
). No entanto, quase todos os shell populares têm um embutidoecho
etest
. Da mesma forma,kill
também está embutido que está disponível como um programa. Outros incluem:sleep
(não é tão comum)time
false
true
printf
No entanto, existem alguns casos em que um comando não pode ser outra coisa senão um builtin. Um deles é
cd
. Normalmente, se o caminho completo não for especificado e o nome do comando corresponder ao de um builtin, uma função adequada para esse comando será chamada. Dependendo do shell, o comportamento do interno e o do executável podem diferir (isso é particularmente um problema paraecho
, que possui comportamentos bastante diferentes . Se você deseja ter certeza do comportamento, é preferível chamar o executável usando o comando caminho completo e defina variáveis comoPOSIXLY_CORRECT
(mesmo assim não há garantia real).Tecnicamente, nada impede que você forneça um SO que também seja um shell e que tenha todos os comandos incorporados. Perto deste extremo está a BusyBox monolítica . O BusyBox é um único binário que (dependendo do nome com o qual é chamado) pode se comportar como qualquer um dos mais de 240 programas , incluindo um Almquist Shell (
ash
). Se vocêPATH
cancelar a configuração enquanto estiver executando o BusyBoxash
, os programas disponíveis no BusyBox ainda estarão acessíveis para você sem especificar aPATH
. Eles se aproximam de serem embutidos no shell, exceto que o próprio shell é um tipo de embutido no BusyBox.Estudo de caso: O Debian Almquist Shell (
dash
)Se você olhar para a
dash
fonte, o encadeamento de execução é mais ou menos assim (é claro, com funções adicionais envolvidas quando são usados pipes e outras coisas):main
→cmdloop
→evaltree
→evalcommand
evalcommand
depois usafindcommand
para determinar qual é o comando. Se for um builtin, então :cmdentry.u.cmd
é umstruct
(struct builtincmd
), um de cujos membros é um ponteiro de função, com uma assinatura típica demain
:(int, char **)
. Aevalbltin
função chama (dependendo se oeval
comando interno é ou não)evalcmd
ou esse ponteiro de função. As funções reais são definidas em vários arquivos de origem.echo
, por exemplo, é :Todos os links para o código-fonte nesta seção são baseados em números de linhas, portanto podem ser alterados sem aviso prévio.
1 Os sistemas POSIX possuem um
cd
executável .Nota:
Existem muitas postagens excelentes no Unix e Linux que lidam com o comportamento do shell. Em particular:
cd
comando externo?fonte
cd
texto de ajuda comhelp cd
(mesma coisa para todos os comandos shell builtin)help
é um builtin bash (para zsh, érun-help cd
)cd
deve ser tão embutida no shell ... mas com base em como as propriedades do processo e sua transferência funcionam no UNIXcd
como uma embutida no shell é a única implementação direta. Veja a resposta de Volker Siegel .Você não pode encontrar um executável para
cd
porque não há nenhum.cd
é um comando interno do seu shell (por exemplobash
).fonte
de
man which
:Como podemos ver na descrição de
which
, é apenas uma verificaçãoPATH
. Portanto, se você implementou algunsbash function
, isso não mostrará nada. É melhor usar otype
comando junto comwhich
.Por exemplo, no
ls
comando Ubuntu, com alias parals --color=auto
.E se você implementar a função de teste
hello
:which
não mostra nada. Mastype
:No seu caso:
Isso significa que
cd
é um shell embutido , está dentrobash
. Todos os bash builtins descritos emman bash
, na seção SHELL BUILTIN COMMANDSfonte
manwhich
.which
, usetype
.