Noções básicas sobre comandos internos do shell


12

No manual do bash , está escrito que

Builtin commands are contained >>> within <<< the shell itself

Além disso, esta resposta afirma que

A built-in command is simply a command that the shell carries out itself,
instead of interpreting it as a request to load and run some
>>> other program <<<

Quando eu executar compgen -bem bash 4.4, recebo uma lista de todos shell builtin comandos. Vejo, por exemplo, que [e killestão listados como shell builtins. Mas suas localizações reais são:

/usr/bin/[
/bin/kill

Eu pensei que builtinisso significa que o comando é compilado no /bin/bashexecutável. Então, o que realmente está me confundindo: por favor, corrija-me, mas como um comando separado pode ser um builtin, quando na verdade não faz parte do shell?


1
Alguns comandos existiam originalmente como utilitários separados. Sua presença agora é para conformidade com o padrão POSIX, portabilidade e compatibilidade com versões anteriores. Os shells implementam alguns como incorporados ao desempenho. Pode haver outro motivo, mas é isso sem muitos detalhes.
Sergiy Kolodyazhnyy

1
Outra razão pela qual pude pensar é porque alguns comandos internos são necessários especificamente para o shell, como execmanipular descritores de arquivos e eval avaliar os comandos. Eles não são necessários como comandos independentes #
Sergiy Kolodyazhnyy

Respostas:


16

Os comandos incorporados ao shell geralmente são incorporados devido ao aumento de desempenho que isso proporciona. Ligar para o externo printf , por exemplo, é mais lento do que usar o incorporado printf.

Como alguns utilitários não precisam ser integrados, a menos que sejam especiais, cdtambém são fornecidos como utilitários externos . Isso ocorre para que os scripts não sejam interrompidos se forem interpretados por um shell que não fornece um equivalente interno.

Alguns recursos internos do shell também fornecem extensões para o comando equivalente externo. Bash's printf, por exemplo, é capaz de fazer

$ printf -v message 'Hello %s' "world"
$ echo "$message"
Hello world

(imprima em uma variável) que o externo /usr/bin/printfsimplesmente não seria capaz de fazer, pois não tem acesso às variáveis ​​do shell na sessão atual do shell (e não pode alterá-las).

Os utilitários incorporados também não têm a restrição de que sua linha de comando expandida tenha que ser menor que um determinado comprimento. Fazendo

printf '%s\n' *

portanto, é seguro se printffor um comando interno do shell. A restrição no comprimento da linha de comando vem da execve()função da biblioteca C usada para executar um comando externo. Se a linha de comando e o ambiente atual forem maiores que ARG_MAXbytes (veja getconf ARG_MAXno shell), a chamada para execve()falhará. Se o utilitário estiver embutido no shell, execve()não precisará ser chamado.

Utilitários incorporados têm precedência sobre os utilitários encontrados em $PATH. Para desativar um comando embutido bash, use, por exemplo

enable -n printf

Há uma pequena lista de utilitários que precisam ser incorporados ao shell (extraídos da lista de embutidos especiais do padrão POSIX )

break
colon (:)
continue
dot (.)
eval
exec
exit
export
readonly
return
set
shift
times
trap
unset

Eles precisam ser integrados, pois manipulam diretamente o ambiente e o fluxo do programa da sessão atual do shell. Um utilitário externo não seria capaz de fazer isso.

Curiosamente, cdnão faz parte desta lista, mas o POSIX diz o seguinte sobre isso:

Como cdafeta o ambiente de execução atual do shell, ele sempre é fornecido como um built-in regular do shell. Se for chamado em um subshell ou ambiente de execução de utilitário separado, como um dos seguintes:

(cd /tmp)
nohup cd
find . -exec cd {} \;

isso não afeta o diretório de trabalho do ambiente do chamador.

Portanto, estou assumindo que os "especiais" embutidos não podem ter contrapartes externas, enquanto cdna teoria poderiam ter (mas não faria muito).


O IIRC chdir/ cderam binários externos nos primeiros Unices / pré-Unix antes de serem forkintroduzidos.
Xophmeister

O @Xophmeister Solaris 11.4 (beta) ainda possui /usr/bin/cd, mas na verdade não altera o diretório de trabalho atual. Seu manual diz: /usr/bin/cdnão tem efeito no processo de chamada, mas pode ser usado para determinar se um diretório pode ou não ser definido como o diretório atual.
Kusalananda

2
Outro motivo bastante específico para builtins: o builtin killtambém é bom porque não precisa bifurcar outro processo, bom se você atingir o limite de número de processos.
Derobert

7

Você está (muito compreensivelmente) confundido pelo fato de que alguns builtins existir tanto como builtins e como comandos externos. Portanto, enquanto você estiver certo de que, por exemplo, existe um /bin/[comando, isso não significa que sua "localização real" esteja /bin.

Qualquer maneira fácil de testar isso é executar typecom o -aswitch que mostrará todas as instâncias disponíveis de um comando. No meu sistema Arch, isso mostra:

$ type -a [
[ is a shell builtin
[ is /sbin/[
[ is /usr/sbin/[
[ is /usr/bin/[

Observe que /sbin, /usr/sbine /bintodos os links simbólicos estão apontando para /usr/binque haja apenas um externo [:

$ readlink -f /usr/sbin /sbin /bin/
/usr/bin
/usr/bin
/usr/bin

Como você pode ver, [é um comando interno e externo, e o mesmo se aplica a vários outros recursos internos do shell. No entanto, isso não muda o fato de que eles também são embutidos no shell, compilados no próprio shell.


porque distro. fornecer comando externo separado para um comando interno já existente? por que eles duplicam?
LoveWithMaths

1
@linuxuser Alguns desses utilitários são requeridos pelo POSIX, e você não pode saber se o shell que um usuário está usando também fornecerá um built-in. Não pense neles como comando interno do sistema operacional, eles são apenas comandos internos do shell, e o shell pode mudar.
terdon

Tenho uma dúvida agora, se comandos internos são fornecidos pelo shell; então quem fornece comandos externos? como eu observei muitos comandos disponíveis tanto como internos quanto externos, mas eu os instalei explicitamente; então quem fornece comando externo? Distro fornece-los corretos?
LoveWithMaths

O @linuxuser depende do comando e do sistema operacional. Por exemplo, no meu Arch Linux, /bin/printfé instalado pelo coreutilspacote e /bin/killpor util-linux.
terdon

Sinto muito, mas ainda não estou claro. Qual das opções acima é fornecida pela distro? e o outro que não é fornecido pela distro e quem a fornece.
LoveWithMaths
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.