Redirecionamento e descritores de arquivo. (File descriptor)
A tecnologia mais underrated que você já viu.
Você a esse ponto deve saber que você pode escrever em um arquivo, ou fazer pipe de entrada/saída de um programa para o outro. Ótimo, mas essa é só a ponta do iceberg. Isso só acontece porque o terminal, quando você usa o ">" ou "|", ele está fazendo um redirecionamento de descritores de arquivo. O pipe:
$ comando1 | comando2
Ele está redirecionando o stdout do comando1 para stdin do comando2. O stdout é a saída padrão dos comandos, o texto que iria para o terminal, se não fosse o pipe, enquanto o stdin é a entrada padrão, era o que você escreveria no terminal, se não fosse o pipe. Então, você pode dizer que o comando1 está "emulando você" escrevendo, ou melhor, programas não necessariamente sabem quando que é um humano digitando a entrada, ou um programa. E quando você usa o ">", você está redirecionando o stdout para um arquivo, em modo de escrita, o ">>" seria em modo append (escrever, mas sem apagar o que estava antes), e o "<" é em modo de leitura. Aliás, a sintaxe certa do redirecionamento é:
$ comando1 [numero]<<arquivo ou &<numero>> [numero]>[>]<arquivo ou &<numero>>
(Tudo que está entre polchetes ([]
), isso significa que é opcional, enquanto
tudo que está entre "<>" é obrigatório).
Quando o ">" ou ">>" não vem depois de um numero, ele assume que esse número seja 1 (o stdout), enquanto o "<" assume o 0 (o stdin). Mas o que são exatamente esses números? Esses números são os descritores de arquivo. Quando um programa abre algo pra leitura ou escrita, ele identifica esse arquivo por um identificador numeral, que não necessariamente é um arquivo. O shell abre 3 arquivos pro programa por padrão:
- 0, o stdin, em modo de leitura, pra entrada de texto.
- 1, o stdout, em modo de escrita, pra saída de texto
- 2, o stderr, em modo de escrita, pra saída de texto, mas voltado para logs e registros de erros.
Uma coisa muito comum é usuários usarem '2>&1' pra poder ler algum log de
erro com o less(1)
ou salvar tudo num arquivo só. Quando você faz isso,
você está redirecionando o que sai do stderr para o stdout do mesmo
processo (Você também pode fazer '1>&0' pra fazer um loopback), mas uma
coisa que poucos usuários sabem é que você não está limitado a só esses
3 descritores. Em uma compilação de kernel linux padrão, o descritor pode
ser aberto entre os números 0-1023, mas o programa precisa ser programado
para aceitar esses descritores vindos do shell (geralmente, esses outros
são usados para abrir arquivos com o open(2)
), mas isso pode ser útil
pra quando você tiver escrevendo um programa. O AWK aceita você escrever
de outros descritores além dos descritores padrão, e tem até um programa
chamado pipexec para ajudar a criar
pipes mais complexos.
Named pipes.
Os pipes que você estava brincando antes se chamam anonymous pipes, mas
existem outros pipes pra processamentos mais complexos. Eles se chamam
named pipes, pipes nomeados. Eles são apenas arquivos que você cria com um
programa/comando chamado mkfifo
. Eles funcionam exatamente igual aos pipes,
só que você vai usar redirecionamento ao invés de simples pipes, e eles
são half-duplex, isso significa que você pode abrí-lo pra leitura ou escrita,
mas não os dois ao mesmo tempo. São uteis quando você precisa lidar com
programas que usam arquivos como argumentos. Por exemplo:
$ mkfifo hello.fifo world.fifo
$ ls
hello.fifo world.fifo
$ echo -n "Hello, " > hello.fifo & #colocando em background pra não travar o terminal
$ echo "World!" > world.fifo &
$ cat hello.fifo world.fifo
Hello, World!
$ _