Table of Contents

Streams, Pipes e Redirecionadores

Fluxos e ligações

Saber trabalhar com fluxos,pipes e redirecionadores no Linux é uma obrigação de qualquer usuário e principalmente do administrador, pois essas tarefas são coisas rotineiras no dia-a-dia de qualquer um deles.

I/O padrão e descritores

A entrada e saída padrão (I/O) é a capacidade do interpretador de comandos e usada praticamente por todos os utilitários de modo texto do Linux quando da necessidade de fazer algum redirecionamento para atela ou para dentro de um arquivo qualquer.

Os três tipos de descritores mais conhecidos são:

Dutos

O pipe “|”, pronuncia-se “paipe”, também é chamado de duto e ele simplesmente envia a saída de um comando para a entrada do próximo comando para continuidade do processamento.

O uso mais comum dele é quando desejamos procurar por algo no sistema cujo resultado é maior que a tela, então, fazemos o uso de pipe com os comandos de pausa como um ls -R / | more, por exemplo.

Para listar todos os processo por ocorrência da string gean com filtragem na tela (stdout):

$ ps aux | grep gean

Ou redirecionando o resultado para um arquivo

$ ps aux | grep gean | tee gean.log

Redirecionamentos

Redirecionador > (maior)

Redireciona a saída de um programa ou comando para algum dispositivo ou arquivo, em vez do dispositivo de de saída padrão (stdout) que é a tela. Esse redirecionamento cria ou substitui o conteúdo do arquivo.

# ls / 1> stdout
# cat stdout 
bin
boot
dev
etc
home
initrd.img
lib
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
vmlinuz

Redirecionador > (maior-maior)

Alimenta (append) um conteúdo ao já existente, diferente do primeiro ele não apaga o conteúdo do arquivo, caso esse arquivo já exista; o que ele faz é adicionar o resultado no final do arquivo.

# ls / 1>> stdout
# cat stdout 
bin
boot
dev
etc
home
initrd.img
lib
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
vmlinuz
bin
boot
dev
etc
home
initrd.img
lib
lost+found
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
vmlinuz

O comando logsave usado como o parâmetro -a serve como append, ou seja, anexa o conteúdo no arquivo de log:

# logsave ls.log ls -laF /etc/init.d/
# cat ls.log 
Log of ls -laF /etc/init.d/ 
Sat May 28 09:38:14 2016
 
total 252
drwxr-xr-x  2 root root  4096 Mar  1 08:55 ./
drwxr-xr-x 89 root root  4096 Mai 28 08:56 ../
-rwxr-xr-x  1 root root  2243 Nov  9  2014 acpid*
-rwxr-xr-x  1 root root  2014 Dez 28  2014 anacron*
-rwxr-xr-x  1 root root 10077 Out 24  2015 apache2*
-rwxr-xr-x  1 root root  2948 Ago 18  2014 bluetooth*
-rwxr-xr-x  1 root root  1276 Abr  6  2015 bootlogs*
-rwxr-xr-x  1 root root  1248 Abr  6  2015 bootmisc.sh*
-rwxr-xr-x  1 root root  3807 Abr  6  2015 checkfs.sh*
-rwxr-xr-x  1 root root  1072 Abr  6  2015 checkroot-bootclean.sh*
-rwxr-xr-x  1 root root  9290 Abr  6  2015 checkroot.sh*
-rwxr-xr-x  1 root root  1379 Dez  8  2011 console-setup*
-rwxr-xr-x  1 root root  3049 Out 23  2014 cron*
-rwxr-xr-x  1 root root  2813 Jul 21  2015 dbus*
-rw-r--r--  1 root root  1345 Mar  1 08:55 .depend.boot
-rw-r--r--  1 root root   550 Mar  1 08:55 .depend.start
-rw-r--r--  1 root root   501 Mar  1 08:55 .depend.stop
-rwxr-xr-x  1 root root  2078 Fev 19 11:30 didiwiki*
-rwxr-xr-x  1 root root  1336 Abr  6  2015 halt*
-rwxr-xr-x  1 root root  1423 Abr  6  2015 hostname.sh*
-rwxr-xr-x  1 root root  3916 Mar 29  2015 hwclock.sh*
-rwxr-xr-x  1 root root  8189 Out 25  2014 kbd*
-rwxr-xr-x  1 root root  1591 Set 30  2012 keyboard-setup*
-rwxr-xr-x  1 root root  1300 Abr  6  2015 killprocs*
-rwxr-xr-x  1 root root  1990 Set 23  2014 kmod*
-rwxr-xr-x  1 root root   995 Abr  6  2015 motd*
-rwxr-xr-x  1 root root   677 Abr  6  2015 mountall-bootclean.sh*
-rwxr-xr-x  1 root root  2138 Abr  6  2015 mountall.sh*
-rwxr-xr-x  1 root root  1461 Abr  6  2015 mountdevsubfs.sh*
-rwxr-xr-x  1 root root  1564 Abr  6  2015 mountkernfs.sh*
-rwxr-xr-x  1 root root   685 Abr  6  2015 mountnfs-bootclean.sh*
-rwxr-xr-x  1 root root  2456 Abr  6  2015 mountnfs.sh*
-rwxr-xr-x  1 root root  5485 Jan 26 10:49 mysql*
-rwxr-xr-x  1 root root  4760 Dez 14  2014 networking*
-rwxr-xr-x  1 root root  1192 Mar  6  2015 procps*
-rwxr-xr-x  1 root root  6228 Abr  6  2015 rc*
-rwxr-xr-x  1 root root   820 Abr  6  2015 rc.local*
-rwxr-xr-x  1 root root   117 Abr  6  2015 rcS*
-rw-r--r--  1 root root  2427 Abr  6  2015 README
-rwxr-xr-x  1 root root   661 Abr  6  2015 reboot*
-rwxr-xr-x  1 root root  1042 Abr  6  2015 rmnologin*
-rwxr-xr-x  1 root root  4355 Jul 10  2014 rsync*
-rwxr-xr-x  1 root root  2796 Ago 29  2015 rsyslog*
-rwxr-xr-x  1 root root  3207 Abr  6  2015 sendsigs*
-rwxr-xr-x  1 root root   597 Abr  6  2015 single*
-rw-r--r--  1 root root  1087 Abr  6  2015 skeleton
-rwxr-xr-x  1 root root  4077 Mar 22  2015 ssh*
-rwxr-xr-x  1 root root  6581 Ago 29  2015 udev*
-rwxr-xr-x  1 root root   461 Ago 29  2015 udev-finish*
-rwxr-xr-x  1 root root  2737 Abr  6  2015 umountfs*
-rwxr-xr-x  1 root root  2202 Abr  6  2015 umountnfs.sh*
-rwxr-xr-x  1 root root  1129 Abr  6  2015 umountroot*
-rwxr-xr-x  1 root root  3111 Abr  6  2015 urandom*
 
Sat May 28 09:38:14 2016
----------------

Redirecionador < (menor)

Tem a função de “receber”, ou seja, enviar a instrução ao comando para que ele execute uma ação se essa for uma ação válida para o comando

# tr "a-z" "A-Z" < ls.log 
LOG OF LS -LAF /ETC/INIT.D/ 
SAT MAY 28 09:38:14 2016
 
TOTAL 252
DRWXR-XR-X  2 ROOT ROOT  4096 MAR  1 08:55 ./
DRWXR-XR-X 89 ROOT ROOT  4096 MAI 28 08:56 ../
-RWXR-XR-X  1 ROOT ROOT  2243 NOV  9  2014 ACPID*
-RWXR-XR-X  1 ROOT ROOT  2014 DEZ 28  2014 ANACRON*
-RWXR-XR-X  1 ROOT ROOT 10077 OUT 24  2015 APACHE2*
-RWXR-XR-X  1 ROOT ROOT  2948 AGO 18  2014 BLUETOOTH*
-RWXR-XR-X  1 ROOT ROOT  1276 ABR  6  2015 BOOTLOGS*
-RWXR-XR-X  1 ROOT ROOT  1248 ABR  6  2015 BOOTMISC.SH*
-RWXR-XR-X  1 ROOT ROOT  3807 ABR  6  2015 CHECKFS.SH*
-RWXR-XR-X  1 ROOT ROOT  1072 ABR  6  2015 CHECKROOT-BOOTCLEAN.SH*
-RWXR-XR-X  1 ROOT ROOT  9290 ABR  6  2015 CHECKROOT.SH*
-RWXR-XR-X  1 ROOT ROOT  1379 DEZ  8  2011 CONSOLE-SETUP*
-RWXR-XR-X  1 ROOT ROOT  3049 OUT 23  2014 CRON*
-RWXR-XR-X  1 ROOT ROOT  2813 JUL 21  2015 DBUS*
-RW-R--R--  1 ROOT ROOT  1345 MAR  1 08:55 .DEPEND.BOOT
-RW-R--R--  1 ROOT ROOT   550 MAR  1 08:55 .DEPEND.START
-RW-R--R--  1 ROOT ROOT   501 MAR  1 08:55 .DEPEND.STOP
-RWXR-XR-X  1 ROOT ROOT  2078 FEV 19 11:30 DIDIWIKI*
-RWXR-XR-X  1 ROOT ROOT  1336 ABR  6  2015 HALT*
-RWXR-XR-X  1 ROOT ROOT  1423 ABR  6  2015 HOSTNAME.SH*
-RWXR-XR-X  1 ROOT ROOT  3916 MAR 29  2015 HWCLOCK.SH*
-RWXR-XR-X  1 ROOT ROOT  8189 OUT 25  2014 KBD*
-RWXR-XR-X  1 ROOT ROOT  1591 SET 30  2012 KEYBOARD-SETUP*
-RWXR-XR-X  1 ROOT ROOT  1300 ABR  6  2015 KILLPROCS*
-RWXR-XR-X  1 ROOT ROOT  1990 SET 23  2014 KMOD*
-RWXR-XR-X  1 ROOT ROOT   995 ABR  6  2015 MOTD*
-RWXR-XR-X  1 ROOT ROOT   677 ABR  6  2015 MOUNTALL-BOOTCLEAN.SH*
-RWXR-XR-X  1 ROOT ROOT  2138 ABR  6  2015 MOUNTALL.SH*
-RWXR-XR-X  1 ROOT ROOT  1461 ABR  6  2015 MOUNTDEVSUBFS.SH*
-RWXR-XR-X  1 ROOT ROOT  1564 ABR  6  2015 MOUNTKERNFS.SH*
-RWXR-XR-X  1 ROOT ROOT   685 ABR  6  2015 MOUNTNFS-BOOTCLEAN.SH*
-RWXR-XR-X  1 ROOT ROOT  2456 ABR  6  2015 MOUNTNFS.SH*
-RWXR-XR-X  1 ROOT ROOT  5485 JAN 26 10:49 MYSQL*
-RWXR-XR-X  1 ROOT ROOT  4760 DEZ 14  2014 NETWORKING*
-RWXR-XR-X  1 ROOT ROOT  1192 MAR  6  2015 PROCPS*
-RWXR-XR-X  1 ROOT ROOT  6228 ABR  6  2015 RC*
-RWXR-XR-X  1 ROOT ROOT   820 ABR  6  2015 RC.LOCAL*
-RWXR-XR-X  1 ROOT ROOT   117 ABR  6  2015 RCS*
-RW-R--R--  1 ROOT ROOT  2427 ABR  6  2015 README
-RWXR-XR-X  1 ROOT ROOT   661 ABR  6  2015 REBOOT*
-RWXR-XR-X  1 ROOT ROOT  1042 ABR  6  2015 RMNOLOGIN*
-RWXR-XR-X  1 ROOT ROOT  4355 JUL 10  2014 RSYNC*
-RWXR-XR-X  1 ROOT ROOT  2796 AGO 29  2015 RSYSLOG*
-RWXR-XR-X  1 ROOT ROOT  3207 ABR  6  2015 SENDSIGS*
-RWXR-XR-X  1 ROOT ROOT   597 ABR  6  2015 SINGLE*
-RW-R--R--  1 ROOT ROOT  1087 ABR  6  2015 SKELETON
-RWXR-XR-X  1 ROOT ROOT  4077 MAR 22  2015 SSH*
-RWXR-XR-X  1 ROOT ROOT  6581 AGO 29  2015 UDEV*
-RWXR-XR-X  1 ROOT ROOT   461 AGO 29  2015 UDEV-FINISH*
-RWXR-XR-X  1 ROOT ROOT  2737 ABR  6  2015 UMOUNTFS*
-RWXR-XR-X  1 ROOT ROOT  2202 ABR  6  2015 UMOUNTNFS.SH*
-RWXR-XR-X  1 ROOT ROOT  1129 ABR  6  2015 UMOUNTROOT*
-RWXR-XR-X  1 ROOT ROOT  3111 ABR  6  2015 URANDOM*
 
SAT MAY 28 09:38:14 2016
----------------

Outros exemplos:

# more < /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
[...]
# < /etc/passwd less

Redirecionador << (menor-menor)

# sort -k2 <<END
> 1 uva
> 2 pera
> 3 banana
> 4 abacaxi
> END
4 abacaxi
3 banana
2 pera
1 uva

Usando esse redirecionado ele abre um editor com o delimitador que indica o final da edição, ou seja, quando o interpretador identificar o delimitador END que foi utilizado no exemplo, ele encerra a edição e exibe na saída padrão.

Exemplo usando os dois redirecionadores duplo.

# cat << END >> vhost.conf
> <VirtualHost 203.0.113.4>
> DocumentRoot /var/www/html/vhost
> ErrorLog logs/vhost.error
> CustomLog logs/vhost.access combined
> </VirtualHost>
> END
# cat vhost.conf 
<VirtualHost 203.0.113.4>
DocumentRoot /var/www/html/vhost
ErrorLog logs/vhost.error
CustomLog logs/vhost.access combined
</VirtualHost>

Nesse exemplo ao invés do outro anterior, o conteúdo digitado foi redirecionado há um arquivo.

Redirecionador 2> (dois-maior)

Tem o mesmo comportamento que o redirecionador > (maior), mas com a ideia de usar mensagens de erros, ou seja, elas não serão ecoadas na tela e sim enviadas para um arquivo.

# cat /etc/passwd /etc/senhas 2> error.log
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:103:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:106:systemd Bus Proxy,,,:/run/systemd:/bin/false
messagebus:x:104:109::/var/run/dbus:/bin/false
avahi-autoipd:x:105:111:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
gean:x:1000:1000:Gean Martins,,,:/home/gean:/bin/bash
didiwiki:x:107:113:DidiWiki,,,:/var/lib/didiwiki:/bin/false
mysql:x:108:115:MySQL Server,,,:/nonexistent:/bin/false
# cat error.log 
cat: /etc/senhas: Arquivo ou diretório não encontrado

Redirecionador 2>> (dois-maior-maior)

Usado para alimentar o arquivo de erro:

# cat /etc/passwd /etc/senhas 2>> error.log
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:103:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:106:systemd Bus Proxy,,,:/run/systemd:/bin/false
messagebus:x:104:109::/var/run/dbus:/bin/false
avahi-autoipd:x:105:111:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
sshd:x:106:65534::/var/run/sshd:/usr/sbin/nologin
gean:x:1000:1000:Gean Martins,,,:/home/gean:/bin/bash
didiwiki:x:107:113:DidiWiki,,,:/var/lib/didiwiki:/bin/false
mysql:x:108:115:MySQL Server,,,:/nonexistent:/bin/false
# cat error.log 
cat: /etc/senhas: Arquivo ou diretório não encontrado
cat: /etc/senhas: Arquivo ou diretório não encontrado

Redirecionadores com /dev/null

O uso do /dev/null, também conhecido como buraco negro (bit bucket) ou dispositivo nulo, é muito comum no Linux. Ele é um arquivo especial que descarta toda informação escrita/enviada para ele e não retorna qualquer informação para um processo que o leia.

Exemplo enviando as mensagens de erro para esse arquivo:

# find / -user gean 2> /dev/null

Mensagens de saída para o buraco negro

# find / -user gean 1> /dev/null 
find: `/proc/1214/task/1214/fd/5': Arquivo ou diretório não encontrado
find: `/proc/1214/task/1214/fdinfo/5': Arquivo ou diretório não encontrado
find: `/proc/1214/fd/5': Arquivo ou diretório não encontrado
find: `/proc/1214/fdinfo/5': Arquivo ou diretório não encontrado

Mensagens de erro para o buraco negro

# find / -user gean 2> /dev/null 
/proc/1047
/proc/1047/task
/proc/1047/task/1047
/proc/1047/task/1047/attr
/proc/1047/net
/proc/1047/attr
[...]

Enviando os dois ao mesmo tempo

# find / -user gean 1> /dev/null 2> /dev/null

Exemplo de script para transforma todos os arquivo do diretório de maiúsculas para minúsculas

# cat << END >> renomeiafile.sh
> #!/bin/bash
> for file in *
> do
> mv $file `echo $file | tr [:upper:] [:lower:]` 2> /dev/null
> done
> END

Para enviar as mensagens para um único arquivo:

# ls /tmp/ /tempo > todo 2>&1

Redirecionadores com /dev/zero, /dev/random

O uso desse redirecionamento comumente usado com o comando dd também é comum no Linux, o /dev/zero é um arquivo especial que fornece caracteres nulos, o da tabela ASCII, o NULL (código de controle 0x00) e não o número 0 (zero) que tem o código 0x30 na tabela. O fluxo de caracteres gerado por esse dispositivo pode, por exemplo, ser utilizado para sobrescrever informações ou para gerar um arquivo limpo de certo tamanho.

Para sobrescrever totalmente uma partição:

# dd if=/dev/zero of=/dev/sda1

Quando necessário é possível criar um arquivo vazio especificando o tamanho do bloco e quantas vezes isso acontece. A multiplicação do bloco com o número de vezes resulta no tamanho do arquivo:

# dd if=/dev/zero of=/tmp/teste.img bs=2048 count=20000
20000+0 registros de entrada
20000+0 registros de saída
40960000 bytes (41 MB) copiados, 0,237271 s, 173 MB/s
# du -sch /tmp/teste.img 
40M	/tmp/teste.img
40M	total
# cat /dev/null > /tml/vazio1
# cat /dev/zero > /tmp/vazio2

O primeiro comando é uma forma de criar um arquivo vazio com 0 (zoro) bytes, mas no segundo, como ele é indefinido, o arquivo crescerá com zeros dentro dele até acabar com o espaço físico do disco ou partição.

O /dev/random também é um arquivoespecial que serve como um gerador de números pseudo-aleatórios. Também podemos usar o /dev/urandom para gerar sementes aleatórias de alta qualidade.

Exemplo para limpar um disco:

# dd if=/dev/urandom of=/dev/sda1

Exemplo para criar chaves SSL e WEP:

# dd if=/dev/random bs=1 count=32 2> /dev/null | xxd -ps
f8064f3eca754db272a65b5e559992fd5e7fdb3a97838f449238208b130c
06b0
# dd if=/dev/random bs=1 count=32 2> /dev/null | hexdump 
0000000 222d 1ed1 3049 f6e6 d650 a2ba d3d7 f176
0000010 ac39 1f7c 5b21 45eb 0178 3cc8 d2e4 73e1
0000020

A contagem aqui é importante, pois é ela quem define o tamanho da chave a ser criada. Veja que para gerar uma chave de 40 bits: count=5, 64 bits: count=8, 104 bits: count=13, 128 bits: count=16, 152 bits: count=19, 232 bitis: count=29, e 256 bits: count=32.

# dd if=/dev/random bs=1 count=5 2> /dev/null | xxd -ps
900b9651ee
# dd if=/dev/random bs=1 count=8 2> /dev/null | xxd -ps
be597e9eb14f63e9
# dd if=/dev/random bs=1 count=13 2> /dev/null | xxd -ps
dcbb73f7c38c518bac9a466b90
# dd if=/dev/random bs=1 count=16 2> /dev/null | xxd -ps
42302c313074e4c7fd2bf1e5afe724ff
# dd if=/dev/random bs=1 count=19 2> /dev/null | xxd -ps
ab24fa7546297c111e937b259158b94fc55a8b
$ dd if=/dev/random bs=1 count=29 2> /dev/null | xxd -ps
fc3abe0f9279a5c6e4d5bb0b85c8e2e1a1bda538305069b6ecb42855c8
$ dd if=/dev/random bs=1 count=32 2> /dev/null | xxd -ps
07d51fe1d285ffedfbee30a7787075c8e4ab169844c89f8eac401eb23e0e
d415

Referências:

  1. Linux Fundamentos, Prática e Certificação LPI - BONAN, Adilson. Alta Books, Rio de Janeiro/RJ, 2010