Por que o cd não é um programa?

129

Eu sempre me perguntei por que cdnão é um programa, mas nunca consegui encontrar a resposta.

Alguém sabe por que esse é o caso?

AkshaiShah
fonte
1
Lembro-me de ler (não consigo encontrar onde) que o cdcomando unix original era um programa separado. A concha lidou com isso especialmente porque não fork, apenas exec. E quando cdterminasse, seria exec sh. Não sei se é uma história verdadeira.
Camh 17/05/12
Qual seria o objetivo? Se for adicionar um tratamento especial, é melhor chamar o chdirsyscall. fontes: v1 v5 v7 (primeira versão com shell Bourne)
Mikel
2
@camh, é uma história verdadeira. Também li isso em um artigo escrito por Dennis M. Ritchie, “A evolução do sistema de compartilhamento de tempo Unix”, AT&T Bell Laboratories Technical Journal 63 (6), Parte 2, outubro de 1984.
jlliagre
@ Mikel: Concordo que parece inútil, mas eu estava apenas contando uma história sobre o cdque eu tinha lido. Eu estava claramente errado sobre o aspecto, agora que @jlliagre preencheu os detalhes.
Camh 17/05/12

Respostas:

172

O cdcomando modifica o "diretório de trabalho atual", certo?

"diretório de trabalho atual" é uma propriedade exclusiva de cada processo.

Portanto, se cdfosse um programa, funcionaria assim:

  1. cd foo
  2. o cdprocesso começa
  3. o cdprocesso altera o diretório para o processo do CD
  4. o cdprocesso sai
  5. seu shell ainda tem o mesmo estado, incluindo o diretório de trabalho atual, que tinha antes de você começar.
Daniel Pittman
fonte
8
Suas cinco etapas estão corretas, mas "se cdum programa funcionasse dessa maneira" deveria ser "quando cdé usado na implementação de um programa externo, funciona assim".
Jlliagre 19/05/12
1
Não sendo um programador de sistemas, nem realmente tendo um conhecimento profundo dos meandros da interação com o shell, eu esperaria que o shell expusesse seu diretório de trabalho atual e o cd fosse um programa que acessa e altera essa propriedade. Entendendo, depois de analisar esta resposta, que isso provavelmente está abaixo do ideal de como ele realmente funciona por vários motivos.
31414 Jason
108

cdalém de ser um shell embutido, também é um programa em sistemas operacionais compatíveis com POSIX. Eles devem fornecer executáveis ​​independentes para utilitários regulares, como cd. Este é por exemplo o caso com Solaris , AIX , HP-UX e OS X .

Obviamente, um built cd-in ainda é obrigatório, pois sua implementação externa não altera o diretório atual do shell. No entanto, o último ainda pode ser útil. Aqui está um exemplo mostrando como o POSIX prevê como esse cdcomando pode ser usado:

find . -type d -exec cd {} \;

Em um sistema POSIX, este oneliner relatará uma mensagem de erro para todos os diretórios nos quais você não tem permissão para cdentrar. Na maioria das distribuições Gnu / Linux, ela falha com essa mensagem de erro:

find: `cd': No such file or directory

E aqui está a resposta para sua pergunta, " Por que o CD não é um programa? ", De um dos co-autores originais do Unix. Em uma implementação muito antiga do Unix, cd(escrito chdirnaquela época), havia um programa externo. Ele parou de funcionar inesperadamente após a forkprimeira implementação.

Citando Dennis Ritchie :

No meio de nossa alegria, foi descoberto que o comando chdir (alterar diretório atual) havia parado de funcionar. Havia muita leitura de código e introspecção ansiosa sobre como a adição de bifurcação poderia ter quebrado a chamada de chdir. Finalmente, a verdade surgiu: no sistema antigo, chdir era um comando comum; ajustou o diretório atual do processo (único) conectado ao terminal. Sob o novo sistema, o comando chdir alterou corretamente o diretório atual do processo criado para executá-lo, mas esse processo terminou imediatamente e não teve nenhum efeito no shell pai! Era necessário fazer do chdir um comando especial, executado internamente dentro do shell. Acontece que várias funções semelhantes a comandos têm a mesma propriedade, por exemplo, logon.

Fonte: Dennis M. Ritchie, “ A evolução do sistema de compartilhamento de tempo Unix ”, AT&T Bell Laboratories Technical Journal 63 (6), Parte 2, outubro de 1984, pp.1577–93

A página 1 do manual do chdir do Unix versão 1 (março de 1971) afirma:

Como um novo processo é criado para executar cada comando, o chdir seria ineficaz se fosse gravado como um comando normal. É, portanto, reconhecido e executado pela Shell.

jlliagre
fonte
10
... então, aparentemente, o POSIX exige que haja um cdexecutável independente , mas que ele não faça nada (exceto, possivelmente, emita mensagens de erro se chamado com os argumentos errados). Esquisito.
Ilmari Karonen
4
Bem, se é verdade, isso não seria a coisa mais estúpida do POSIX.
264 Kaz
5
A página de cd do POSIX também diz "Como o cd afeta o ambiente atual de execução do shell, ele sempre é fornecido como um built-in regular do shell".
Mikel
6
@ Kaz, eles não são coisas completamente diferentes. Eles fazem a mesma coisa, mas apenas o incorporado afeta o shell atual.
Jlliagre 17/05/12
13
@Kaz: Por favor, não me chame de boba enquanto estou apenas relatando um fato. Você pode concordar ou discordar do POSIX, mas não atire no messenger.
Jlliagre 17/05
47

Na introdução do Bash (o que é um shell? ):

Os shells também fornecem um pequeno conjunto de comandos internos (internos) implementando funcionalidades impossíveis ou inconvenientes de serem obtidas por meio de utilitários separados. Por exemplo, cd, break, continue, e exec) não pode ser realizada fora da casca, porque eles manipular diretamente o próprio shell. A history, getopts, kill, ou pwdbuiltins, entre outros, podem ser implementados em utilitários separados, mas eles são mais convenientes de usar comandos como embutidas. Todos os componentes internos do shell são descritos nas seções subseqüentes.

cjc
fonte
29

Para o April Fool deste ano, escrevi uma versão independente decd .

Ninguém entendeu a piada. Suspiro.

Qualquer pessoa que não tenha certeza de que cddeve ser incorporada ao shell deve fazer o download, compilar e experimentar.

Leia sua página de manual também. :)

Warren Young
fonte
Código realmente útil! :-)
dschulz
6
É bom ver alguém trabalhando para tornar o Gnu / Linux mais compatível com POSIX. Sua implementação não é apenas uma boa piada, mas realmente algo faltando em distribuições Linux ...
jlliagre
8
Acho que vou tentar novamente no próximo ano, citando a questão do POSIX. ;)
Warren Young
6 anos depois: Bem, você fez?
Peter A. Schneider
@ PeterA.Schneider: Eu pensei que estava claro que estava brincando, então, para ficar claro, não, eu não vou realmente gastar muito esforço tentando colocar isso em sistemas operacionais e projetos semelhantes a sistemas operacionais, como o Cygwin, que atualmente falta /bin/cd. Se você quiser pegar meu código e fazer disso sua própria busca pessoal, poderá fazê-lo.
Warren Young
4

O cdcomando no shell não pode ser um processo separado porque no Unix não há mecanismo para alterar o diretório de trabalho atual de um processo diferente (nem mesmo o processo pai).

Se cdfosse um processo diferente, seria necessário alterar o diretório de trabalho atual de seu pai (shell), o que não é possível no Unix. Em vez disso cdé um especial construído no comando. O shell chama funções como chdir()e fchdir() alterar seu próprio diretório de trabalho atual.

Nota: o kernel armazena o número de inode do diretório de trabalho atual para cada processo. O processo filho o herda cwddo pai.

saurav1405
fonte
0

cd é um comando interno do shell. Tão fácil quanto é. O cd do homem diz tudo. o comando cd altera o diretório de trabalho para todos os intérpretes e (em um ambiente encadeado) todos os encadeamentos.


fonte
Porque o shell é o ambiente que cuida dos seus diretórios de trabalho atuais ($ PDW ...) ou cdable_vars. Esse recurso interno é basicamente o modo como todos os comandos visíveis ao usuário devem alterar o diretório de trabalho atual. Você pode testá-lo dessa maneira: compile o bash sem o cd.c e tente escrever seu próprio script de cd, que tenta cuidar de todo o ambiente cdable_vars. Esta questão também é mais um desenvolvedor relacionado. Aposto que eles poderiam responder a essa pergunta com mais detalhes.
2
Há uma muito boa razão técnica que cdé built-in. Eu sugiro que você leia as respostas mais bem classificadas e considere como sua resposta pode ser melhorada.
Thorbjørn Ravn Andersen
A resposta mais alta foi a pior que já li! Mas hein? Quem sou eu!
3
Mas responde à pergunta por quê .
Thorbjørn Ravn Andersen
-1

Acho que uma coisa que falta na resposta das pessoas é que o diretório atual é uma variável de ambiente que cada programa pode mudar. Se você usar o comando 'export' para ver sua lista de variáveis ​​de ambiente atual, terá:

declare -x PWD="/home/erfan"

nos seus resultados. Assim, pelo comando 'cd', apenas queremos modificar essa variável interna. Acho que se tentarmos, podemos alterar a variável PWD de qualquer pty no shell, é claro. Gostar:

cder    #change current PTY $PWD variable

Mas acho que não há necessidade em casos normais. Em outra palavra, usamos ajuda do bash (ou qualquer shell) para modificar sua variável interna definida.

Erfankam
fonte
3
Embora seja verdade que os shells Bourne expõem o diretório de trabalho atual (CWD) como $ PWD, esse não é o local de armazenamento primário; a localização real está na estrutura por processo do kernel. Portanto, é incorreto dizer que o CWD "é uma variável de ambiente". Se funcionasse da maneira que você sugere, este-liner dois C iria imprimir o ..caminho, não o caminho que começou a partir de: #include <stdlib.h> int main(void) { chdir(".."); puts(getenv("PWD")); }(conchas C expor o CWD como% cwd em vez disso, por sinal.)
Warren Young
vamos adicionar outras linhas ao seu aplicativo. #include <stdlib.h> int main (vazio) {chdir (".."); puts (getenv ("PWD")); setenv (P "PWD", "/", 1); puts (getenv ("PWD")); } O que teremos como resultados?
Erfankam
3
Isso substituirá apenas o valor de uma variável, sem efeito colateral no CWD. Este é um teste melhor para mostrar que: #include <unistd.h> int main(void) { char ac[99]; setenv("PWD", "/", 1); puts(getcwd(ac, sizeof(ac))); }Ele mostrará o diretório do qual você iniciou o programa, não /.
Warren Young
Eu acho que todo processo também tem um diretório de trabalho e uma variável de caminho. Assim, você por chdir apenas altera esse atributo do processo. O Shell também possui esse atributo e, por cd, modificamos esse atributo.
Erfankam
4
Não, estou lhe dizendo que $PWDsó tem significado para a concha Bourne. É apenas uma maneira de o shell comunicar algo que sabe sobre shell scripts, para que eles não precisem ligar pwdpara encontrá-lo. Qualquer programa independente, dependendo do valor de $PWD, não será confiável.
Warren Young