Por que echo um shell é construído em comando?

34
$ which echo
echo: shell built-in command.
$ which ls
/bin/ls
$ which cat
/bin/cat

Por que não é echo um utilitário independente como ls, ps, catetc? Por que é específico do shell? Alguma boa razão?

lazer
fonte
5
Lembre-se de que isso é específico do shell. O ZSH o constrói, o BASH não.
tsvallender
21
@tsv: echocertamente é um Bash embutido. De fato, ele está embutido em todas as principais conchas modernas.
Pausado até novo aviso.

Respostas:

71

Existem duas classes de builtins:

  1. Alguns comandos precisam ser incorporados ao próprio programa shell porque não podem funcionar se forem externos.

    cdé um desses, pois, se fosse externo, só poderia alterar seu próprio diretório; não poderia afetar o diretório de trabalho atual do shell. (Veja também: Por que cdnão é um programa? )

  2. A outra classe de comandos é incorporada ao shell apenas para eficiência.

    A página do homem tem uma seção sobre builtins que menciona , e como exemplos de comandos nesta classe.dash printfechotest

Os sistemas Unix sempre incluíram executáveis ​​separados para comandos nessa segunda classe. Esses executáveis ​​separados ainda estão disponíveis em todos os sistemas Unixy que eu usei, embora também estejam embutidos em todos os shell que você provavelmente usará. (O POSIX realmente exige que esses executáveis ​​estejam presentes.)

Acredito que echofoi incorporado ao shell no AT&T Unix System V Release 3.1. Baseei isso nas comparações de duas edições diferentes de manuais para os sistemas Unix da série AT & Ts 3B1 . Alguém digitalizou gentilmente as edições de 1986 desses manuais e as colocou online ; estes correspondem à versão original do SVR3. Você pode ver que isso echonão está na lista na página 523 do Manual do Usuário do UNIX System V, Volume II , onde você esperaria se o comando fosse incorporado ao shell. Na minha cópia em papel local dos manuais SVR3.1 de 1987, echo está listada nesta seção do manual.

Tenho certeza de que essa não é uma inovação de Berkeley CSRG que a AT&T trouxe de volta para casa. O 4.3BSD saiu no mesmo ano que o SVR3, 1986, mas se você olhar a página de manual sh.1 do 4.3BSD , verá que echonão está na lista de comandos internos da seção "Comandos Especiais". Se o CSRG fez isso, isso nos deixa querendo uma fonte documentada para provar isso.

Nesse ponto, você pode se perguntar se echofoi incorporado ao shell antes do SVR3.1 e que esse fato simplesmente não foi documentado até então. O mais novo código-fonte pré-SVR3 AT&T Unix disponível para mim está no pacote PDP-11 System III , em que você encontrará o código-fonte do shell Bourne. Você não vai encontrar echona tabela de comando interno, que está em /usr/src/cmd/sh/msg.c. Com base nos registros de data e hora desse arquivo, isso prova que echocertamente não estava no shell em 1980.


Curiosidades

O mesmo diretório também contém um arquivo chamado builtin.cque não contém nada específico para esta pergunta, mas achamos este comentário interessante:

/*      
    builtin commands are those that Bourne did not intend
    to be part of his shell.
    Redirection of i/o, or rather the lack of it, is still a
    problem..
*/      
Warren Young
fonte
Na página 385 do SysV UM, Vol. II que você mencionou, existe o printcomando interno para o ksh que é dito se comportar como echo. Este comando também está presente em algo como o AT&T Unix SVR4 2.1 i386 da ISC. print "\012"produz o mesmo resultado que ecoaria. Pergunto-me por que o ksh tinha impressão e não eco embutido? De qualquer forma realmente interessante.
Quantas jóias de alguns anos atrás estão escondidas esperando para serem desenterradas por uma edição em 2016? 1
iruvar
+1. Obrigado. Você poderia fornecer as fontes (referências) com a finalidade de criar um comando interno, para minha leitura / aprendizagem (sistemática)?
Tim
Quero encontrar alguma referência, manual ou padrão para ler ou aprender sistematicamente. Tentei procurar no manual de referência do bash e nas especificações do POSIX. Mas não consigo encontrar. Não tenho certeza se sinto falta deles.
Tim
@ Tim: Como esta e outras respostas aqui explicam, alguns comandos devem ser incorporados ao shell ou eles não podem fazer seu trabalho. Todos os outros são puramente opcionais . Isso é essencialmente o que meu trecho de código fonte do shell Bourne diz acima, na verdade. Como a criação de tais comandos no shell é opcional, uma justificativa autorizada só pode dar a opinião de um implementador.
21816 Warren Young
19

Há uma terceira razão para que alguns comandos sejam incorporados: eles podem ser usados ​​quando a execução de comandos externos é impossível.

Às vezes, um sistema fica tão danificado que o lscomando não funciona. Em alguns casos, um echo *ainda funcionará.

Outro exemplo (mais importante!) É kill: Se um sistema ficar sem PIDs gratuitos, não será possível executá- /bin/killlo (porque ele precisa de um PID :-), mas o interno funcionará kill.

Btw., whichÉ um comando externo (pelo menos não é interno no bash), portanto, não pode listar comandos internos. Por exemplo:

$ which echo
/bin/echo
$ type -a echo
echo is a shell builtin
echo is /bin/echo
bhm
fonte
Não esqueça que quase todos os executáveis ​​externos dependem de arquivos de biblioteca. Às vezes, catástrofes acontecem e essas bibliotecas não podem ser carregadas (conselhos: NUNCA edite, a ldconfigmenos que você saiba exatamente o que está fazendo). Além disso, e se você afastar sua partição / bin, ou pior, sua partição / sbin, mas ainda tiver um shell carregado?
LawrenceC
Se você ficar sem PIDs, pode ser difícil descobrir qual PID você deseja matar. Você não pode executar um pscomando, portanto, você teria que encontrar os PIDs manualmente /proc.
kasperd
Embora no (pelo menos) o CentOS whichseja um alias do bash que é executado alias | /usr/bin/which --read-alias ..., o externo which pode identificar aliases (mas ainda não embutidos). Não posso decidir se considero isso brilhante ou pervertido.
Dave_thompson_085 26/05
No ponto em que o comando ls não funciona mais, acho que você deve montar a unidade como escrava em vez de inicializar / mestre e corrigir a estrutura de arquivos dessa maneira. Não tenho certeza de como você pode corrigir essa extensão da corrupção do sistema com eco, a menos que você esteja ecoando em um arquivo e isso levaria muito tempo para ser corrigido. Concedido que você poderia escrever um script bash para corrigir a estrutura do sistema.
jonnyjandles
13

De acordo com o Manual de Referência do Bash , trata-se de conveniência.

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 podem ser implementados fora do shell porque eles manipulam diretamente o próprio shell. Os históricos, getopts, kill ou pwd, entre outros, poderiam ser implementados em utilitários separados, mas são mais convenientes para usar como comandos internos. Todos os componentes internos do shell são descritos nas seções subseqüentes.

O Advanced Bash Scripting Guide tem uma explicação mais detalhada:

"A builtin é um comando contido dentro do conjunto de ferramentas Bash, literalmente construído em Isto é, quer por motivos de desempenho -. Builtins executar mais rápido do que os comandos externos, que normalmente exigem a bifurcação off 1 um processo separado - ou porque um builtin particular precisa direta acesso aos internos do shell ".

Observe também que echoexiste como um utilitário independente em alguns sistemas. Aqui está o que eu tenho no meu sistema Darwin (MacOSX 10.5.8 - Leopard)

$ uname -a
Darwin host.foo.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ which echo
/bin/echo

echotambém está disponível como interno, mas aparentemente meus scripts usam / bin / echo no meu Mac e usam o Bash embutido na maioria dos meus sistemas Linux e FreeBSD. Mas isso não parece importar, porque os scripts ainda funcionam bem em todos os lugares.

Stefan Lasiewski
fonte
3
Falando em built-ins de shell, você deve usar "type" em vez de "what".
Teddy
Obrigado @Teddy. Eu comecei a fazer isso, quando me lembro. A vida é muito melhor graças a type.
Stefan Lasiewski
6

Para complementar a resposta de bhm, digamos Vamos /binacidentalmente foi removido do seu PATH. Você gostaria echo $PATHde descobrir isso, certo?

Daniel Hershcovich
fonte
2

Embora a maioria dos shells inclua um built-in echohoje em dia, o GNU CoreUtils também inclui uma implementação autônoma dele:

$ which echo
/bin/echo
$ dpkg -S /bin/echo
coreutils: /bin/echo

Parece que você não possui o GNU Coreutils instalado (a maioria dos sistemas operacionais para desktop e servidor baseados em linux o instala por padrão, mas o linux incorporado ou outro UNIX pode usar coleções alternativas de utilitários de shell).

BTW: se você olhar para Busybox , você verá que ls, pse cattambém são built-in comandos lá (ou pelo menos pode ser, é usado para sistemas embeded e tudo não for necessário pode ser deixado de fora).

JanC
fonte
3
Os testes do pôster original não suportam a hipótese que /bin/echonão existe. Eles apenas mostram que o builtin tem precedência sobre qualquer echoprograma no PATH.
Warren Young
1

Aqui está a verdadeira razão pela qual echodeve ser um shell embutido:

Suponha que você tenha uma senha $PASSWORD. Como você escreve em um arquivo ./password? Naturalmente, a maioria dos programadores escreveria:

echo "$PASSWORD" >./password

No entanto, se echonão fosse um shell embutido, a senha vazaria para todos os usuários através de psinformações.

Obviamente, se você quiser ser inteligente, poderá encontrar uma maneira de armazenar uma senha sem echo, talvez explorando algum outro recurso do shell:

cat >./password <<EOF
${PASSWORD}
EOF

No entanto, ter echocomo interno é um cinto de segurança importante, pois a maneira mais óbvia de salvar uma senha em um arquivo também deve funcionar.

DepressedDaniel
fonte
3
Embora seja um efeito colateral útil, acho altamente duvidoso que esse tenha sido o motivo.
plugwash
@DepressedDaniel: O que você faz? Onde está a referência que você usou para apoiar sua resposta?
Joker