Você está na página 1de 237

Machine Translated by Google

3ª EDIÇÃO

COMO AS

LINUX
FUNCIONA
O QUE TODO SUPERUSUÁRIO DEVE SABER

BRIAN WARD
Machine Translated by Google
Machine Translated by Google

AVALIAÇÕES PARA
COMO FUNCIONA O LINUX

“Se você está interessado em Linux, How Linux Works: What Every Superuser Should Know é
um título de leitura obrigatória.”
—Linux Insider

“Muito a oferecer em quase todos os aspectos da arquitetura Linux.”


—Usuário Linux diário

“Você terá uma compreensão essencial do que está acontecendo sob o capô sem ficar atolado
em minúcias – tornando esta uma adição muito refrescante (e totalmente recomendada) à
literatura Linux.”
—Phil Bull, coautor de Ubuntu
Made Easy e membro da equipe de
documentação do Ubuntu

“Mergulhe direto nas profundezas transparentes dos sistemas operacionais baseados em


Linux e nos mostra como todas as peças se encaixam.”
—DistroWatch

“Ganha o seu lugar na prateleira como uma referência essencial.”


—A revista MagPi
Machine Translated by Google
Machine Translated by Google

COMO LINUX
FUNCIONA
3ª edição

O que é superusuário
Deveria saber

por Brian Ward

São Francisco
Machine Translated by Google

COMO FUNCIONA O LINUX, 3ª EDIÇÃO. Copyright © 2021 por Brian Ward.

Todos os direitos reservados. Nenhuma parte desta obra pode ser reproduzida ou transmitida de qualquer forma ou por qualquer meio,
eletrônico ou mecânico, incluindo fotocópia, gravação ou por qualquer sistema de armazenamento ou recuperação de informações,
sem a permissão prévia por escrito do proprietário dos direitos autorais e do editor.

ISBN-13: 978-1-7185-0040-2 (impressão)


ISBN-13: 978-1-7185-0041-9 (e-book)

Editora: William Pollock Editora


Executiva: Barbara Yien Editora de
Produção: Rachel Monaghan
Editores de Desenvolvimento: Larry Wake e Jill Franklin
Capa e Design de Interiores: Octopod Studios Revisores
Técnicos: Jordi Gutiérrez Hermoso e Petros Koutoupis
Editor de texto: Rachel Monaghan
Compositor: Cody Gates, Happenstance Type-O-Rama Revisor:
James M. Fraleigh

Para obter informações sobre distribuidores de livros ou traduções, entre em contato diretamente com a No Starch Press,
Inc.: No Starch Press, Inc.
245 8th Street, San Francisco, CA 94103 telefone:
1-415-863-9900; info@nostarch.com www.nostarch.com

A Biblioteca do Congresso catalogou a primeira edição da seguinte forma:

Ward, Brian.
Como o Linux funciona: o que todo superusuário deve saber / Brian Ward.
pág. cm.
Inclui índice.
ISBN 1-59327-035-6
1. Linux. 2. Sistemas operacionais (Computadores). I. Título.
QA76.76.O63 W3654 2004
005.4'32--dc22
2004002692

No Starch Press e o logotipo No Starch Press são marcas registradas da No Starch Press, Inc. Outros nomes de produtos e empresas
aqui mencionados podem ser marcas comerciais de seus respectivos proprietários. Em vez de usar um símbolo de marca registrada em
todas as ocorrências de um nome de marca registrada, estamos usando os nomes apenas de forma editorial e em benefício do
proprietário da marca, sem intenção de infringir a marca.

As informações contidas neste livro são distribuídas “como estão”, sem garantia. Embora todas as precauções tenham sido tomadas
na preparação deste trabalho, nem o autor nem a No Starch Press, Inc. informações nele contidas.
Machine Translated by Google

Sobre o autor
Brian Ward trabalha com Linux desde 1993. Ele também é autor de The
Linux Kernel HOWTO, The Book of VMware (No Starch Press) e The
Linux Problem Solver (No Starch Press).

Sobre os revisores técnicos


Jordi Gutiérrez Hermoso é usuário e desenvolvedor GNU/Linux com
quase duas décadas de experiência, com contribuições pontuais em
diversos círculos das comunidades de software livre, como GNU Octave e
Mercurial. Seu trabalho profissional lhe permitiu colaborar e aprender sobre
diversos tópicos, como assinaturas criptográficas digitais, imagens médicas
e, mais recentemente, contabilidade de gases de efeito estufa e dados de
mapas ecológicos, todos construídos inteiramente com Linux e outros
softwares gratuitos. Quando não está perto de um computador, gosta de
nadar, matemática e tricô.

Petros Koutoupis é atualmente engenheiro de software de desempenho


sênior na HPE (anteriormente Cray Inc.) para sua divisão Lustre High
Performance File System. Ele também é o criador e mantenedor do
RapidDisk Project (www.rapiddisk.org). Petros trabalha no setor de
armazenamento de dados há mais de uma década e ajudou a ser pioneiro
nas muitas tecnologias liberadas na natureza hoje.
Machine Translated by Google
Machine Translated by Google

BREVE CONTEÚDO

Prefácio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi

Capítulo 1: O Grande Quadro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Capítulo 2: Comandos Básicos e Hierarquia de Diretórios . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Capítulo 3: Dispositivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Capítulo 4: Discos e sistemas de arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

Capítulo 5: Como o kernel do Linux é inicializado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Capítulo 6: Como o espaço do usuário é iniciado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

Capítulo 7: Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários . . . . . . . . 167

Capítulo 8: Um olhar mais atento sobre processos e utilização de recursos . . . . . . . . . . . . . . . . . . . 199

Capítulo 9: Entendendo sua rede e sua configuração . . . . . . . . . . . . . . . . . . . . 223

Capítulo 10: Aplicativos e Serviços de Rede . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

Capítulo 11: Introdução aos scripts de shell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291

Capítulo 12: Transferência e compartilhamento de arquivos de rede . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315

Capítulo 13: Ambientes de Usuário......................................... 335

Capítulo 14: Uma breve pesquisa sobre a área de trabalho e impressão do Linux . . . . . . . . . . . . . . . . . . . . . 347

Capítulo 15: Ferramentas de Desenvolvimento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363

Capítulo 16: Introdução à compilação de software a partir do código-fonte C . . . . . . . . . . . . . . . 385

Capítulo 17: Virtualização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Bibliografia................................................. ...... 419

Índice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
Machine Translated by Google
Machine Translated by Google

CONTEÚDO EM DETALHE

PREFÁCIO XXI
Quem deveria ler esse livro? . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . xxi
Pré-requisitos. . . . . . . . . . . . . . . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . xxii
Como ler este livro Uma . . . . . . . . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . xxii
abordagem prática . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . xxii
Como Este Livro Está Organizado. . . . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . xxiii
O que há de novo na terceira edição? . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . xxiii
Uma Nota sobre Terminologia. . . . . . . . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . xxiv

1
A GRANDE IMAGEM 1

1.1 Níveis e Camadas de Abstração em um Sistema Linux . . .. . .. .. .. .. .. . .. .. .. .. . 2


1.2 Hardware: Entendendo a Memória Principal . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. . 4
1.3 O Núcleo . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. . 4
1.3.1 Gestão de Processos . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .5
1.3.2 Gerenciamento de Memória . . . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. .. .6
1.3.3 Drivers e Gerenciamento de Dispositivos . . . . . .. . .. .. .. .. .. . .. .. .. .. .6
1.3.4 Chamadas e Suporte do Sistema . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. .. .7
1.4 Espaço do Usuário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. .. .8
1.5 Usuários. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. .. .9
1.6 Olhando para o futuro . . . . . . . . . . . . . . . . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. . . 10

2
COMANDOS BÁSICOS E HIERARQUIA DE DIRETÓRIOS 11

2.1 O Bourne Shell: /bin/sh . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 12


2.2 Usando o Shell . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 12
2.2.1 A Janela Shell . . 2.2.2 .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 13
gato. . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 13
2.2.3 Entrada Padrão e Saída Padrão . . .. . .. .. .. .. .. . .. .. .. . . 14
2.3 Comandos Básicos . . . . . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . . 15
2.3.1 l. 2.3.2 .cp.
. . .. . . . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . . 15
2,3,3 mv. . 2.3.4. . . . . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . . 15
toque . . 2.3.5 rm .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 16
2.3.6 eco . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 16
.. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 16
.. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 16
2.4 Navegando em Diretórios . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . . 16
2.4.1 cd. . 2.4.2 . . . . . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . . 17
mkdir . . 2.4.3 rmdir. . .. . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . . 17
.. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 17
2.4.4 Shell Globbing (“Coringas”) . .. .. .. .. . .. .. .. .. .. . .. .. .. . . 18
Machine Translated by Google

2.5 Comandos Intermediários . . . . 19. . . . .. .. .


.. .... .. .. . .. .. .. .. .. . .. .. ..
2.5.1 agarrar . . .. .19. . . . . . . . . .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
2.5.2 menos. . . .20 . .. . .. .. .. .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
2.5.3 pwd. . . 20. . . . . . . . . . . .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
.. .. . .. .. ..
2.5.4 diferenças. . 21 .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
2.5.5 arquivo . . 21 .. .. . .. .. .. .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
2.5.6 encontre e localize . . 21. . .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
2.5.7 cabeça e cauda . 21 . . . . .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
.. .. . .. .. ..
2.5.8 classificar . 22 .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
2.6 Mudando sua senha e shell. . 22 .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
.. .. .. .. . .. .. .. .. ..
2.7 Arquivos de Pontos. . 22 .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
2.8 Ambiente e Variáveis do Shell . . 22 .. .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
2.9 O Caminho do Comando . . .. . .23 . .. .. .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
2.10 Caracteres Especiais . . 24 . . . . . . . . . . . .
.. .... .. .. . .. .. .. .. .. . .. .. .. ..
2.11 Edição de linha de comando . . . . 25 . . . . . . . . .. ..
. .. .. .. . .. .. .. .. .. . .. .. ..
2.12 Editores de Texto ... .. 25.. .. . .. .. .. .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
2.13 Obtendo Ajuda Online . . . 26 . .. .. .. .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
2.14 Entrada e Saída do Shell . . . . 28 .. .. .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
2.14.1 Erro Padrão. . . . 29 .. .. .. .
.. .... .. .. . .. .. .. .. .. . .. .. ..
2.14.2 Redirecionamento de Entrada Padrão. ..... 29 .. .. .. . .. .. .. .. .. . .. .. ..
2.15 Entendendo as mensagens de erro . . . . 29 .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
2.15.1 Anatomia de uma Mensagem de Erro Unix. .. .. 30 .. . .. .. .. .. .. . .. .. ..
2.15.2 Erros Comuns......................................... 30
2.16 Listando e Manipulando Processos . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 32
2.16.1 Opções de Comando . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 32
2.16.2 Rescisão do Processo . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 33
2.16.3 Controle de Trabalho. . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 34
2.16.4 Processos em segundo plano . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 34
2.17 Modos de arquivo e permissões . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 35
2.17.1 Modificando Permissões . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 36
2.17.2 Trabalhando com Links Simbólicos . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 38
2.18 Arquivando e compactando arquivos . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 39
2.18.1 gzip . . 2.18.2. . alcatrão.
. .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 39
.. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 39
2.18.3 Arquivos compactados (.tar.gz) . . .. .. .. . .. .. .. .. .. . .. .. .. . . 40
2.18.4 zcat . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 41
2.18.5 Outros Utilitários de Compressão . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 41
2.19 Fundamentos da hierarquia de diretórios do Linux . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 42
2.19.1 Outros subdiretórios raiz . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 43
2.19.2 O diretório /usr . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 44
2.19.3 Localização do Kernel . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 44
2.20 Executando Comandos como Superusuário . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 44
2.20.1 sudo . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 45
2.20.2 /etc/sudoers . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 45
2.20.3 sudo Logs . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 46
2.21 Olhando para o futuro . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 46

3
DISPOSITIVOS 47
3.1 Arquivos do dispositivo. . . . .48
. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
3.2 O caminho do dispositivo sysfs.............................. 49

x Conteúdo em detalhes
Machine Translated by Google

.. .. . .. .. .. .. .. . .. .. .. .. ..
3.3 dd e Dispositivos . . . 50 . .. .. .. .. .. . .. .. ..
3.4 Resumo do nome do dispositivo . . .. .. 51
.. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
3.4.1 Discos Rígidos: /dev/sd* . . . 52. . . . . . . . . . . . . . .. .. .. .. .. . .. .. ..
3.4.2 Discos Virtuais: /dev/xvd*, /dev/vd* . . . . 53 .. . .. .. .. .. .. . .. .. ..
3.4.3 Dispositivos de Memória Não Volátil: /dev/nvme*................... 53
3.4.4 Mapeador de dispositivo: /dev/dm-*, /dev/mapper/* . . . . 53 . . . . . .. .. .. ..
3.4.5 Unidades de CD e DVD: /dev/sr* . . . . 53 . . . . . . . . . . . . . . . . .. .. .. ..
3.4.6 Discos Rígidos PATA: /dev/hd* . . . . 53. . . . . . . . . . . . . . . . . . .. .. .. ..
3.4.7 Terminais: /dev/tty*, /dev/pts/* e /dev/tty . . . 53 .. .. . .. .. .. ..
3.4.8 Portas seriais: /dev/ttyS*, /dev/ttyUSB*, /dev/ttyACM* . . . . 55 . .. .. ..
3.4.9 Portas paralelas: /dev/lp0 e /dev/lp1 . . . 55 . . . . . . . . . . . . . . .. .. ..
3.4.10 Dispositivos de áudio: /dev/snd/*, /dev/dsp, /dev/audio e mais . . . . 55
3.4.11 Criação de arquivo de dispositivo . . . . .56. . . . . . . . . . . . . . . . . . . . . . . . .. ..
.. .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . ..
3.5 udev. . . 56 .. ..
3.5.1 devtmpfs . . . . 57. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. ..
3.5.2 Operação e Configuração do udevd . . . . 58 .. . .. .. .. .. .. . .. .. ..
3.5.3 udevadm . , , 60 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. ..
3.5.4 Monitoramento do Dispositivo . .. .. . 61
.. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
3.6 Aprofundado: SCSI e o Kernel Linux................................ 62
3.6.1 Armazenamento USB e SCSI . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . . 65
3.6.2 SCSI e ATA 3.6.3 . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . . 65
Dispositivos SCSI genéricos . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 66
3.6.4 Múltiplos Métodos de Acesso para um Único Dispositivo . . . . .. .. .. . .. .. .. . . 67

4
DISCOS E SISTEMAS DE ARQUIVOS 69
4.1 Particionando Dispositivos de Disco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.1.1 Visualizando uma Tabela de Partições . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.1.2 Modificando Tabelas de Partição . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 75
4.1.3 Criando uma Tabela de Partição . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 76
4.1.4 Navegando na Geometria do Disco e da Partição . . . .. .. .. .. .. . .. .. .. . . 78
4.1.5 Leitura de discos de estado sólido . . .. .. .. . .. .. .. .. .. . .. .. .. . . 80
4.2 Sistemas de arquivos. . . . . . . . . . . . . . . . . . . . . . . . . . .. .. . .. .. .. .. .. . .. .. .. . . 80
4.2.1 Tipos de sistema de arquivos . . . . . . . . . . . . . . . .. .. . .. .. .. .. .. . .. .. .. . . 81
4.2.2 Criando um sistema de arquivos . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 82
4.2.3 Montando um sistema de arquivos . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 83
4.2.4 UUID do sistema de arquivos. . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 85
4.2.5 Buffer de disco, cache e sistemas de arquivos . . .. .. .. .. .. . .. .. .. . . 86
4.2.6 Opções de montagem do sistema de arquivos . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. . . 86
4.2.7 Remontando um sistema de arquivos . . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. . . 87
4.2.8 A tabela do sistema de arquivos /etc/fstab . . . . . . .. . .. .. .. .. .. . .. .. .. . . 88
4.2.9 Alternativas para /etc/fstab . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 89
4.2.10 Capacidade do sistema de arquivos . . . . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. . . 89
4.2.11 Verificando e Reparando Sistemas de Arquivos . . .. . .. .. .. .. .. . .. .. .. . . 91
.. .. ..
4.2.12 Sistemas de Arquivos de Propósitos Especiais . . .. . .. .. .. .. .. . .. .. .. . . 93
4.3 Trocar Espaço . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 94
4.3.1 Usando uma partição de disco como espaço de troca . .. . .. .. .. .. .. . .. .. .. . . 94
4.3.2 Usando um arquivo como espaço de troca . . . . . . . . .. . .. .. .. .. .. . .. .. .. . . 95
4.3.3 Determinando a quantidade de swap necessária . . .. .. .. .. .. . .. .. .. . . 95
4.4 O Gerenciador de Volume Lógico . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . . 96
4.4.2 Trabalhando com LVM . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . . 97
4.4.3 A Implementação do LVM . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 107

XI
Conteúdo em detalhes
Machine Translated by Google

4.5 Olhando para o futuro: Discos e espaço do usuário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111


4.6 Dentro de um sistema de arquivos tradicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
4.6.1 Detalhes do Inode e Contagem de Link . . . . . . . . . . . . . . . . . . . . . . . . . . 113
4.6.2 Alocação de Blocos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
4.6.3 Trabalhando com Sistemas de Arquivos no Espaço do Usuário . . . . . . . . . . . . . . . . . . . . . 115

5
COMO AS BOTAS DO LINUX KERNEL 117

5.1 Mensagens de Inicialização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118


5.2 Inicialização do Kernel e Opções de Inicialização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
5.3 Parâmetros do Kernel . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 120
5.4 Carregadores de Inicialização . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 121
5.4.1 Tarefas do carregador de inicialização . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 122
5.4.2 Visão geral do carregador de inicialização . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 123
5.5 Introdução ao GRUB . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 123
5.5.1 Explorando dispositivos e partições com a linha de comando do GRUB . .. . 125
5.5.2 Configuração do GRUB. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 127
5.5.3 Instalação do GRUB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. . 130
5.6 Problemas de inicialização segura UEFI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. . 131
5.7 Carregamento em cadeia de outros sistemas operacionais . . . . . . . . . . . . . . . . . . . . . . . . .. .. . 132
5.8 Detalhes do carregador de inicialização . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. . 132
5.8.1 Inicialização MBR.............................................. 133
5.8.2 Inicialização UEFI .. . .133 . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
5.8.3 Como o GRUB funciona . . . .134 . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..

6
COMO COMEÇA O ESPAÇO DO USUÁRIO 137
6.1 Introdução ao init 6.2 . .. . .. .. .. .. .. . .. .. .. ..
.. . .. .. .. .. .. . .. .. .. . 138
Identificando seu init 6.3 .. . .. .. .. .. .. . .. .. .. ..
.. . .. .. .. .. .. . .. .. .. . 139
systemd . . .. .. .. .. . .. .. .. .. .. . .. .. .. ..
.. . .. .. .. .. .. . .. .. .. . 139
6.3.1 Unidades e Tipos de Unidade. . . . . . .. .. .. ..
.. . .. .. .. .. .. . .. .. .. . 140
6.3.2 Inicializando e Gráficos de Dependência de .. . .. .. .. .. .. . .. .. .. . 140
Unidade . 6.3.3 Configuração do systemd . . . ...6.3.4
.. .. .. .. . .. .. .. .. .. . .. .. .. . 141
. . . . . . . .e. . . . . . . . . . . . . . . . . .
Operação do sistema . . 6.3.5 Rastreamento . .. .. .. . 144
Sincronização de Processos do systemd . . 6.3.6 Dependências . . . . . . . .. .. .. . 147
do systemd . 6.3.7 Inicialização sob demanda . . . . . . .e .recursos
. .. .. . .. .. .. .. .. . .. .. .. . 148
paralelizados do systemd . . 6.3.8 Componentes Auxiliares do sistema . . . .. .. .. . 151
.. .. .. . .. .. .. .. .. . .. .. .. . 156
6.4 Níveis de execução do System V . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 156
6.5 System V init . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 157
6.5.1 System V init: Sequência de comandos de inicialização. .. . . . . . . . . . .. .. .. . 158
6.5.2 O System V init Link Farm . 6.5.3 . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 159
peças de execução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 160
6.5.4 Controle de inicialização do .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 161
System V . . 6.5.5 Compatibilidade Systemd System .V. . .. . . . . . . . . . . . . . . . .. .. .. . 161
6.6 Encerrando seu sistema . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 162
6.7 O sistema de arquivos RAM inicial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 163
6.8 Inicialização de Emergência e Modo de Usuário Único . . . . . . . . . . . . . . . . . . . . .. .. .. . 164
6.9 Olhando para o futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 165

xii Conteúdo em detalhes


Machine Translated by Google

7
CONFIGURAÇÃO DO SISTEMA:
LOG, HORA DO SISTEMA, TRABALHOS EM LOTE E USUÁRIOS 7.1 167

Log do sistema . .. .. . .. .. .. .. .. . .. .. ..
.. .. . ..
.. .. .. .. . .. .. .. . 168
7.1.1 Verificando sua configuração de log. . . . . . . .
.. .. . ..
.. .. .. .. . .. .. .. . 169
7.1.2 Pesquisando e Monitorando Logs . . .. .. .. . ..
.. .. .. .. . .. .. .. . 169
7.1.3 Rotação do arquivo de log . . . . . . . . . . . . . . .
.. .. . ..
.. .. .. .. . .. .. .. . 172
7.1.4 Manutenção do Diário. . .. . .. .. ..
.. .. . ..
.. .. .. .. . .. .. .. . 173
7.1.5 Uma análise mais detalhada do registro do sistema . . .
.. .. . ..
.. .. .. .. . .. .. .. . 173
7.2 A Estrutura do /etc . . . .. .. .. .. .. . .. .. ..
.. .. . ..
.. .. .. .. . .. .. .. . 176
7.3 Arquivos de gerenciamento de usuários. . . . . . . . . . . . . . . . .
.. .. . ..
.. .. .. .. . .. .. .. . 177
7.3.1 O arquivo /etc/passwd . . .. . .. .. ..
.. .. . ..
.. .. .. .. . .. .. .. . 177
7.3.2 Usuários Especiais . . . . . . . . . . .. .. ..
.. .. . ..
.. .. .. .. . .. .. .. . 178
7.3.3 O arquivo /etc/shadow . . .. . .. .. ..
.. .. . ..
.. .. .. .. . .. .. .. . 179
7.3.4 Manipulando Usuários e Senhas . .. .. . ..
.. .. .. .. . .. .. .. . 179
7.3.5 Trabalhando com Grupos . . . . . . . . . . . . . .. . ..
.. .. .. .. . .. .. .. . 180
7.4 getty e login . .. .. . .. .. .. .. .. . .. .. .. .. .. . ..
.. .. .. .. . .. .. .. . 181
7.5 Ajustando a Hora . .. .. . .. .. .. .. .. . .. .. .. .. .. . ..
.. .. .. .. . .. .. .. . 181
7.5.1 Representação do Horário do Kernel e Fusos Horários . . . . .. .. .. . .. .. .. . 182
7.5.2 Horário da Rede . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 182
7.6 Agendando tarefas recorrentes com cron e unidades de timer . . . . . . .. .. .. .. ... .. . 183
7.6.1 Instalando Arquivos Crontab . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 184
7.6.2 Arquivos Crontab do Sistema . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 185
7.6.3 Unidades de Temporização .. . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 185
7.6.4 cron vs. Unidades de Temporização . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 187
7.7 Agendando Tarefas Únicas com às . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 187
7.7.1 Equivalentes da Unidade do Temporizador . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 188
7.8 Unidades de Temporização Funcionando como Usuários Regulares . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 188
7.9 Tópicos de Acesso do Usuário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 189
7.9.1 IDs de Usuário e Troca de Usuário . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 189
7.9.2 Propriedade do processo, UID efetivo, UID real e UID salvo . . .. .. . 189
7.9.3 Identificação, autenticação e autorização do usuário . . .. . .. .. .. . 191
7.9.4 Usando Bibliotecas para Informações do Usuário . . . . . . . . . . . . . . .. . .. .. .. . 192
7.10 Módulos de autenticação plugáveis . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 192
7.10.1 Configuração do PAM . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 193
7.10.2 Dicas sobre a sintaxe de configuração do PAM . . . . . . . . . . . . . . .. . .. .. .. . 196
7.10.3 PAM e Senhas . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 197
7.11 Olhando para o futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . .. .. .. . 198

8
UM OLHAR MAIS DE PERTO DOS PROCESSOS E UTILIZAÇÃO DE RECURSOS 199

8.1 Processos de Rastreamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200


8.2 Localizando Arquivos Abertos com lsof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
8.2.1 Lendo a saída lsof . . . .. .. .. ..
.. .. . .. .. .. .. . .. .. .. . 201
8.2.2 Usando lsof . . . . . . . . . . . . . . . . . .. ..
.. .. . .. .. .. .. . .. .. .. . 202
8.3 Rastreando Execução do Programa e Chamadas do .. ..
.. .. . .. .. .. .. . .. .. .. . 202
. .. . 8.3.2
Sistema . 8.3.1 linha . . . .ltraço.
. . . . .. . . . . . . .. ..
.. .. . .. .. .. .. . .. .. .. . 202
.. . .. .. .. .. .. . .. .. .. ..
.. .. . .. .. .. .. . .. .. .. . 204
8.4 Fios . . .. .. .. .. . .. .. .. .. .. . .. .. .. ..
.. .. . .. .. .. .. . .. .. .. . 204
8.4.1 Processos Single-Threaded e Multithreaded . .. .. .. .. . .. .. .. . 204
8.4.2 Visualizando Threads . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 205

xiii
Conteúdo em detalhes
Machine Translated by Google

8.5 Introdução ao Monitoramento de Recursos . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 206


8.5.1 Medindo o Tempo de CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 207
8.5.2 Ajustando as Prioridades do Processo . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 207
8.5.3 Medindo o desempenho da CPU com médias de carga . . .. .. . .. .. .. . 208
8.5.4 Monitorando o Status da Memória . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 210
8.5.5 Monitorando o desempenho da CPU e da memória com vmstat . . . .. .. .. . 212
8.5.6 Monitoramento de E/S . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 214
8.5.7 Monitoramento por processo com pidstat . . . . . . . . . . . . . . . . . .. .. .. . 216
8.6 Grupos de Controle (cgroups) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 216
8.6.1 Diferenciando entre as versões do cgroup . . .. .. .. .. .. . .. .. .. . 217
8.6.2 Visualizando cgroups . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 219
8.6.3 Manipulando e Criando cgroups . .. .. . .. .. .. .. .. . .. .. .. . 220
8.6.4 Visualizando a utilização de recursos . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 221
8.7 Tópicos Adicionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . 221

9
ENTENDENDO SUA REDE E SUA CONFIGURAÇÃO 223

9.1 Noções básicas de rede ............................................. 224


9.2 Pacotes . 224. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ... .. .. .. . .. .. .. .
9.3 Camadas de Rede . . 225 .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
9.4 A Camada da Internet . . .. 226. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
9.4.1 Visualizando Endereços IP . . . .228 . . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
9.4.2 Sub-redes. . . 228 . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
9.4.3 Máscaras de sub-rede comuns e notação CIDR. . . 229 .. .. .. .. . .. .. ..
9.5 Rotas e a Tabela de Roteamento do Kernel . . .. .230 . .. .. .. .. . .. .. .. .. .. . .. .. ..
9.6 O Gateway Padrão . . 231 . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. ..
9.7 Endereços e redes IPv6 . . . 231 .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
9.7.1 Visualizando a configuração IPv6 em seu sistema . . . 232 .. .. .. .. . .. .. ..
9.7.2 Configurando redes de pilha dupla . . 233 . . . . . . . . . . . .. .. .. . .. .. ..
9.8 Ferramentas básicas de ICMP e DNS . .. .. 234 .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
9.8.1 ping. . 234. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. ..
9.8.2 DNS e host.............................. 235
9.9 A Camada Física e Ethernet . . 235 .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
9.10 Entendendo as interfaces de rede do kernel . . . 236 . . . . . . . . . . . .. .. .. . .. .. ..
9.11 Introdução à configuração da interface de rede . . . 237 .. . .. .. .. .. .. . .. .. ..
9.11.1 Configurando Interfaces Manualmente . . . 237 .. .. . .. .. .. .. .. . .. .. ..
9.11.2 Adicionando e excluindo rotas manualmente . . . 238 . .. .. .. .. .. . .. .. ..
9.12 Configuração de rede ativada por inicialização . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 239
9.13 Problemas com configuração de rede manual e ativada por inicialização . . . .. .. .. . 239
9.14 Gerenciadores de Configuração de Rede . . . . . . . . . . . . . . . . . . . . . . .. . .. .. .. . 240
9.14.1 Operação do NetworkManager . .. .. .. .. . .. .. .. .. .. . .. .. .. . 241
9.14.2 Interação do NetworkManager . .. .. .. .. . .. .. .. .. .. . .. .. .. . 241
9.14.3 Configuração do NetworkManager . . .. .. . .. .. .. .. .. . .. .. .. . 242
9.15 Resolvendo nomes de .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 243
host . 9.15.1 /etc/ .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 244
hosts. 9.15.2 resolv.conf . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . .. .. .. . 245
9.15.3 Cache e DNS de configuração zero . . 9.15.4 / . .. .. .. .. .. . .. .. .. . 245
etc/nsswitch.conf . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 246
9.16 Localhost . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 247
9.17 A Camada de Transporte: TCP, UDP e Serviços . . .. .. . .. .. .. .. .. . .. .. .. . 247
9.17.1 Portas e Conexões TCP . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 248
9.17.2 UDP. . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 250

xiv Conteúdo em detalhes


Machine Translated by Google

9.18 Revisitando uma Rede Local Simples................................ 252


9.19 Entendendo o DHCP . . 252 . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. ..
9.19.1 Clientes DHCP Linux . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 253
9.19.2 Servidores DHCP Linux . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 253
9.20 Configuração Automática de Rede IPv6 . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 253
9.21 Configurando o Linux como um Roteador . . . . . . . . . . .. .. .. . .. .. .. .. .. . .. .. .. . 254
9.22 Redes Privadas (IPv4) . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 256
9.23 Conversão de Endereço de Rede (Mascaramento de IP) . . . . .. .. .. .. .. . .. .. .. . 256
9.24 Roteadores e Linux . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 258
9.25 Firewalls . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 259
9.25.1 Fundamentos do Firewall Linux . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 259
9.25.2 Configurando regras de firewall . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 261
9.25.3 Estratégias de firewall. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 262
9.26 Ethernet, IP, ARP e NDP . . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 264
9.27 Ethernet sem fio . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 266
9.27.1 iw. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 267
9.27.2 Segurança sem fio. . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 268
9.28 Resumo. . . . . . . . . . . . . . . . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 268

10
APLICATIVOS E SERVIÇOS DE REDE 269
10.1 Noções básicas de serviços . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 270
10.2 Um olhar mais atento . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 271
10.3 Servidores de Rede . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 272
10.3.1 Shell Seguro . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 273
10.3.2 O servidor sshd . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 274
10.3.3 fail2ban . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 276
10.3.4 O Cliente SSH . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 277
10.4 Servidores de conexão de rede pré-sistemad: inetd/xinetd . . ..... ...... . . . . . . . 278
10.5 Ferramentas de .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 279
diagnóstico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . . . . . . . . 280
10.5.1 lsof . 10.5.2 . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 281
tcpdump . 10.5.3 netcat
. . . .. . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . . . . . . . . 283
10.5.4 Varredura de Portas . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . . . . . . . . 284
10.6 Chamadas de Procedimento Remoto . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . . . . . . . . 284
10.7 Segurança da Rede . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . . . . . . . . 285
10.7.1 Vulnerabilidades Típicas . .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 286
10.7.2 Recursos de Segurança . . . .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 287
10.8 Olhando para o futuro . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . . . . . . . . 287
10.9 Soquetes de Rede . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . . . . . . . . 288
10.10 Soquetes de Domínio Unix . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . . . . . . . . 289

11
INTRODUÇÃO AOS SHELL SCRIPTS 11.1 291
Noções básicas de Shell Script . .. . . . . . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 291
11.1.1 Limitações dos Shell Scripts . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 292
11.2 Citação e Literais. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 293
11.2.1 Literais . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 293
11.2.2 Cotações Simples . . . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 294
11.2.3 Cotações Duplas . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 295
11.2.4 Aspas Simples Literais . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 295

xv
Conteúdo em detalhes
Machine Translated by Google

11.3 Variáveis Especiais. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 296


11.3.1 Argumentos Individuais: $1, $2 e assim por diante. . .. .. .. .. . .. .. .. . 296
11.3.2 Número de Argumentos: $# . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 297
11.3.3 Todos os Argumentos: $@ . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 297
11.3.4 Nome do script: $0 . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 297
11.3.5 ID do processo: $$ . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 298
11.3.6 Código de saída: $? . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 298
11.4 Códigos de Saída . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 298
11.5 Condicionais . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 299
11.5.1 Uma solução alternativa para listas de parâmetros vazias . .. .. .. .. .. . .. .. .. . 299
11.5.2 Outros Comandos para Testes . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 300
11.5.3 elif. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 300
11.5.4 Construções Lógicas . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 300
11.5.5 Condições de Teste . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 301
11.5.6 caso . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 304
11.6 Loops . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 305
11.6.1 para Loops . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 305
11.6.2 enquanto Loops . . . . . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 305
11.7 Substituição de Comandos . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 306
11.8 Gerenciamento de Arquivos Temporários . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 307
11.9 Aqui Documentos . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 308
11.10 Utilitários de script de shell importantes . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 308
11.10.1 nome de base . . 11.10.2
.. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 308
. . . . xargs
aw. 11.10.3 sed. 11.10.4 . . . .. .. . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 309
11.10.5 exp. 11.10.6. .exec.
. .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 309
. .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 310
.. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 311
.. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 311
11.11 Subcamadas . . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 311
11.12 Incluindo outros arquivos em scripts. . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 312
11.13 Lendo a entrada do usuário. . . . . . . . . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 312
11.14 Quando (não) usar scripts de shell . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 312

12
TRANSFERÊNCIA E COMPARTILHAMENTO DE ARQUIVOS DE REDE 315
12.1 Cópia Rápida . . 12.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. .. . .. .. .. . 316
rsync. .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 317
12.2.1 Introdução ao rsync . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 317
12.2.2 Fazendo cópias exatas de uma estrutura de diretórios . . .. .. .. . .. .. .. . 318
12.2.3 Usando a barra final . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 319
12.2.4 Excluindo Arquivos e Diretórios . .. .. .. . .. .. .. .. .. . .. .. .. . 320
12.2.5 Verificando transferências, adicionando
salvaguardas e usando o modo detalhado . . . . . .. .. . . . . . .. . .. . . . ...... 321
12.2.6 Compactando Dados . . 321. . . . . . . . . . . . . . . . . . .. .. .. .. . .. .. ..
12.2.7 Limitando a largura de banda .. .. 322
.. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
12.2.8 Transferindo arquivos para seu computador . . . 322 .. . .. .. .. .. .. . .. .. ..
12.2.9 Tópicos adicionais do rsync . .. .. 322 . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
12.3 Introdução ao Compartilhamento de Arquivos.. .. 323
.. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
12.3.1 Uso e Desempenho de Compartilhamento de Arquivos ....................... 323
12.3.2 Segurança de Compartilhamento de Arquivos. .. . 323
. .. .. .. .. .. . .. .. .. .. .. . .. .. ..

xvi Conteúdo em detalhes


Machine Translated by Google

12.4 Compartilhando arquivos com o Samba . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 324


12.4.1 Configuração do Servidor . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 324
12.4.2 Controle de acesso ao servidor . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 325
12.4.3 Senhas . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 326
12.4.4 Inicialização Manual do Servidor . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 327
12.4.5 Diagnósticos e Arquivos de Log . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 328
12.4.6 Configuração de Compartilhamento de Arquivos . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 328
12.4.7 Diretórios Home . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 328
12.4.8 Compartilhamento de Impressora . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 329
12.4.9 O Cliente Samba . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 329
12.5 SSHFS. . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 331
12.6 NFS. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 332
12.7 Armazenamento em Nuvem. . . . . . . . . . . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 333
12.8 O estado do compartilhamento de arquivos de rede . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 333

13
AMBIENTES DO USUÁRIO 335
13.1 Diretrizes para criar arquivos de inicialização .. .. 336 .. .. .. .. . .. .. .. .. .. . .. .. ..
13.2 Quando alterar os arquivos de inicialização .. .. 336 .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.3 Elementos do Arquivo de Inicialização do Shell .. ... 337
.. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.3.1 O Caminho do Comando . . .. 337 . . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.3.2 O Caminho da Página do Manual.............................. 338
13.3.3 O Aviso . . . 338 . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. . .. .. ..
13.3.4 Pseudônimos . .. . .339 . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.3.5 A Máscara de Permissões . .. 339 . . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.4 Ordem de Arquivos de Inicialização e Exemplos . .. 340 . . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.4.1 O shell bash . . . 340 . . . . . . . . . . . . . . . . . . . . . . . . .. .. . .. .. ..
13.4.2 O Shell tcsh . . . 342 . . . . . . . . . . . . . . . . . . . . . . . . .. .. . .. .. ..
13.5 Configurações padrão do usuário.. .. 343 .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.5.1 Padrões do Shell . . . 343 .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.5.2 Editor. . 344. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. .. . .. .. ..
13.5.3 Pager . . 344 .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.6 Armadilhas do arquivo de inicialização .. . .. 344
. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
13.7 Outros Tópicos de Inicialização . .. 345 . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..

14
UMA BREVE PESQUISA DO LINUX DESKTOP E IMPRESSÃO 347
14.1 Componentes da área de trabalho. .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 348
14.1.1 Framebuffers. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 348
14.1.2 O Sistema X Window . . . ..
.. .. .. .. . .. .. .. .. .. . .. .. .. . 348
14.1.3 Wayland. . . . . . . . . . . . ..
.. .. .. .. . .. .. .. .. .. . .. .. .. . 349
14.1.4 Gerenciadores de Janelas . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 349
14.1.5 Kits de ferramentas . . . . . . . . . . . . . . . .
.. .. .. .. . .. .. .. .. .. . .. .. .. . 350
14.1.6 Ambientes de Trabalho . .. . ..
.. .. .. .. . .. .. .. .. .. . .. .. .. . 350
14.1.7 Aplicativos . . . . . . . . . . ..
.. .. .. .. . .. .. .. .. .. . .. .. .. . 350
14.2 Você está executando Wayland ou X? . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 351
14.3 Um olhar mais atento sobre Wayland. . . . . . . . . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 351
14.3.1 O Gerenciador de Janelas de Composição . . . . .. .. .. .. .. . .. .. .. . 351
14.3.2 libinput . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 352
14.3.3 X Compatibilidade em Wayland. .. .. .. .. . .. .. .. .. .. . .. .. .. . 353

xvii
Conteúdo em detalhes
Machine Translated by Google

14.4 Um olhar mais atento ao sistema X Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354


14.4.1 Gerenciadores de Exibição......................... 355
14.4.2 Transparência da Rede . . . 355. . . . . . . . . . . . . . .. .. .. .. . .. .. ..
14.4.3 Formas de Explorar Clientes X . . 355 .. .. .. .. . .. .. .. .. .. . .. .. ..
14.4.4 X Eventos . . 356 . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
14.4.5 X Entrada e configurações de preferência .. .. 357 .. .. . .. .. .. .. .. . .. .. ..
14.5 D-Bus. . 359 .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
14.5.1 Instâncias de Sistema e Sessão . . . 360 .. .. .. . .. .. .. .. .. . .. .. ..
14.5.2 Monitoramento de mensagens D-Bus . .. ..360 .. .. .. . .. .. .. .. .. . .. .. ..
14.6 Impressão. . . .360. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
14.6.1 COPOS . . .361 . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..
14.6.2 Conversão de Formato e Filtros de Impressão . ... .361 . .. .. .. .. .. . .. .. ..
14.7 Outros tópicos da área de trabalho .. .. 362
.. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. ..

15
FERRAMENTAS DE DESENVOLVIMENTO 363

15.1 O compilador C. . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 364


15.1.1 Compilando vários arquivos de origem . . . .. .. . .. .. .. .. .. . .. .. .. . 365
15.1.2 Vinculando com Bibliotecas . . . . . . . . . . .. .. . .. .. .. .. .. . .. .. .. . 366
15.1.3 Trabalhando com Bibliotecas Compartilhadas . . . . .. .. . .. .. .. .. .. . .. .. .. . 367
15.1.4 Trabalhando com arquivos e diretórios de cabeçalho .. . .. .. .. . 371
(incluir) . . 15.2 fazer.
.. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 373
15.2.1 Um Makefile de Amostra . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 374
15.2.2 Regras Integradas . . . . . . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 374
15.2.3 Construção Final do Programa . . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 375
15.2.4 Atualizações de dependência . . . . . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 375
15.2.5 Argumentos e opções de linha de comando . . . . . . .. .. .. . .. .. .. . 376
15.2.6 Macros e Variáveis Padrão . . .. .. . .. .. .. .. .. . .. .. .. . 377
15.2.7 Alvos Convencionais . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 378
15.2.8 Organização do Makefile . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 378
15.3 Lex e Yacc. . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 379
15.4 Linguagens de script . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 380
15.4.1 Python . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 381
15.4.2 Perl. . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 381
15.4.3 Outras linguagens de script . . .. .. .. .. . .. .. .. .. .. . .. .. .. . 381
15.5 Java. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 382
15.6 Olhando para o futuro: compilando pacotes . . . . . . . . . . . . . . . .. .. .. . .. .. .. . 383

16
INTRODUÇÃO À COMPILAÇÃO DE SOFTWARE
DO CÓDIGO DE FONTE C 385

16.1 Sistemas de Construção de Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386


16.2 Descompactando Pacotes de Origem C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
16.3 GNU Autoconf . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 388
16.3.1 Um Exemplo de Autoconf . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 389
16.3.2 Instalação usando uma ferramenta de .. . .. .. .. .. .. . .. .. .. . 390
empacotamento . . 16.3.3 configurar opções. de . . script.
.. .. .. .. . .. .. .. .. .. . .. .. .. . 390
16.3.4 Variáveis de Ambiente . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 391
16.3.5 Destinos do Autoconf . . . . . . . . . . . . . . . . . . .. .. .. .. .. . .. .. .. . 392
16.3.6 Arquivos de log do .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 392
. . . .. . . . . . . . . . . . . . . . . .
Autoconf . . 16.3.7 pkg-config . .. .. .. .. .. . .. .. .. . 393

xviii Conteúdo em detalhes


Machine Translated by Google

16.4 Prática de Instalação . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 394


16.4.1 Onde Instalar . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 395
16.5 Aplicando um Patch . . . . . . . . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 395
16.6 Solucionando problemas de compilações e instalações . . . . . .. . .. .. .. .. .. . .. .. .. . 396
16.6.1 Erros Específicos. . .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 397
16.7 Olhando para o futuro . . . . . . . . . . .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 399

17
VIRTUALIZAÇÃO 401
17.1 Máquinas Virtuais . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 402
17.1.1 Hipervisores . . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 402
17.1.2 Hardware em uma Máquina Virtual . .. .. .. . .. .. .. .. .. . .. .. .. . 403
17.1.3 Usos Comuns de Máquinas Virtuais . .. .. . .. .. .. .. .. . .. .. .. . 404
17.1.4 Desvantagens das Máquinas Virtuais . .. .. .. . .. .. .. .. .. . .. .. .. . 404
17.2 Contêineres. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 405
17.2.1 Docker, Podman e Privilégios . .. .. .. . .. .. .. .. .. . .. .. .. . 406
17.2.2 Um exemplo do Docker. . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 407
17.2.3 LXC . . .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 414
17.2.4 Kubernetes. . .. .. .. .. . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 415
17.2.5 Armadilhas de Contêineres . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 415
17.3 Virtualização baseada em tempo de execução . . . . . . . .. .. .. .. .. . .. .. .. .. .. . .. .. .. . 417

BIBLIOGRAFIA 419

ÍNDICE 423

xix
Conteúdo em detalhes
Machine Translated by Google

AGRADECIMENTOS

As contribuições para este livro não vêm apenas daqueles que estiveram envolvidos na
o processo de desenvolvimento, mas também aqueles sem os quais eu não saberia
nada sobre Linux. Estes incluem James Duncan, Douglas N. Arnold,
Bill Fenner, Ken Hornstein, Scott Dickson, Dan Ehrlich, Felix Lee e
Gregório P. Smith. As edições anteriores incluíram a ajuda de Karol Jurado, Laurel
Chun, Serena Yang, Alison Law, Riley Hoffman, Scott Schwartz, Dan Sully,
Dominique Poulain, Donald Karon e Gina Steele.
Esta terceira edição beneficia do excelente trabalho de Barbara Yien,
Rachel Monaghan, Jill Franklin, Larry Wake, Jordi Gutierrez Hermoso,
e Petros Koutoupis. Como editor da No Starch Press, Bill Pollock
tem sido fundamental neste livro desde a primeira edição. E mais uma vez, Hsinju
Hsieh me atura para outra revisão.
Machine Translated by Google

PREFÁCIO

Seu sistema não deve ser um mistério. Você deve ser capaz de fazer seu software
fazer o que você quer sem encantamentos ou rituais “mágicos”. A chave para alcançar
esse poder está em entender os fundamentos do que o software faz e como ele funciona,
e é disso que trata este livro.
Você nunca deveria ter que lutar com um computador.
O Linux é uma ótima plataforma para aprender porque não tenta esconder nada
de você. Em particular, você pode encontrar a maioria dos detalhes de configuração do
sistema em arquivos de texto simples de fácil leitura. A única parte complicada é
descobrir quais partes são responsáveis pelo quê e como todas elas se encaixam.

Quem deveria ler esse livro?


Seu interesse em aprender como o Linux funciona pode ter vindo de várias fontes. No
âmbito profissional, o pessoal de operações e DevOps precisa saber quase tudo o que
você encontrará neste livro. Arquitetos e desenvolvedores de software Linux também
devem conhecer este material para fazer o melhor uso do sistema operacional.
Pesquisadores e estudantes, muitas vezes executando seus próprios sistemas Linux,
também descobrirão que este livro fornece explicações úteis sobre por que as coisas são
configuradas do jeito que são.
Depois, há os funileiros - pessoas que adoram brincar com
seus computadores por diversão, lucro ou ambos. Quer saber por que certas coisas
funcionam enquanto outras não? Quer saber o que acontece se você mover alguma
coisa? Você provavelmente é um funileiro.
Machine Translated by Google

Pré-requisitos
Embora o Linux seja amado pelos programadores, você não precisa ser um programador
para ler este livro; você precisa apenas de conhecimento básico de usuário de computador.
Ou seja, você deve ser capaz de mexer em uma GUI (especialmente o instalador e a interface
de configurações para uma distribuição Linux) e saber quais são os arquivos e diretórios
(pastas). Você também deve estar preparado para verificar a documentação adicional em seu
sistema e na web. A coisa mais importante que você precisa é estar pronto e disposto a brincar
com seu computador.

Como ler este livro


Construir o conhecimento necessário é um desafio na abordagem de qualquer assunto
técnico. Explicar como os sistemas de software funcionam pode ser muito complicado.
Muitos detalhes podem atrapalhar os leitores e dificultar a compreensão de conceitos
importantes (o cérebro humano simplesmente não consegue processar tantas ideias novas
ao mesmo tempo), mas poucos detalhes podem deixar os leitores no escuro e despreparados
para material posterior.
Eu projetei a maioria dos capítulos para abordar o material mais importante primeiro:
as informações básicas que você precisa para progredir. Em alguns lugares, simplifiquei as
coisas para manter o foco. À medida que um capítulo avança, você verá muito mais detalhes,
especialmente nas últimas seções. Você precisa conhecer esses bits imediatamente? Na
maioria dos casos, não; Observo isso quando aplicável. Se seus olhos começarem a ficar
vidrados quando você se deparar com muitos detalhes extras sobre conceitos que acabou de
aprender, não hesite em pular para o próximo capítulo ou fazer uma pausa. O âmago da
questão ainda estará lá esperando por você.

Uma abordagem prática


Seja como for que você decida prosseguir com este livro, você deve ter uma máquina Linux à
sua frente, de preferência uma que você esteja confiante em abusar com experimentos. Você
pode preferir brincar com uma instalação virtual - usei o VirtualBox para testar grande parte do
material deste livro. Você também deve ter acesso de superusuário (root), mas tente usar uma
conta de usuário comum na maioria das vezes. Você trabalhará principalmente na linha de
comando, em uma janela de terminal ou em uma sessão remota. Se você não trabalhou muito
nesse ambiente, não tem problema; O Capítulo 2 o atualizará.

Os comandos neste livro normalmente são assim:

$l/
[alguma saída]

Digite o texto em negrito; o texto sem negrito que se segue é o que a máquina
cospe de volta. O $ é o prompt para uma conta de usuário normal. Se você vir um # como
um prompt, precisará ser superusuário. (Mais sobre isso no Capítulo 2.)

xxii Prefácio
Machine Translated by Google

Como este livro está organizado


Agrupei os capítulos do livro em três partes básicas. A primeira é introdutória, dando uma
visão geral do sistema e, em seguida, oferecendo experiência prática com algumas
ferramentas que você precisará enquanto estiver executando o Linux. Em seguida, você
explorará cada parte do sistema com mais detalhes, desde o gerenciamento do dispositivo
até a configuração da rede, seguindo a ordem geral em que o sistema é iniciado. Por fim,
você fará um tour por algumas partes de um sistema em execução, aprenderá algumas
habilidades essenciais e obterá algumas informações sobre as ferramentas que programam
meros usam.

Com exceção do Capítulo 2, a maioria dos primeiros capítulos envolve fortemente


o kernel do Linux, mas você trabalhará no espaço do usuário à medida que o livro avança.
(Se você não sabe do que estou falando aqui, não se preocupe; explicarei no Capítulo 1.)

O material deve ser o mais agnóstico possível em termos de distribuição. Dito isso,
pode ser tedioso cobrir todas as variações de software de sistemas, então tentei cobrir as
duas principais famílias de distribuição: Debian (incluindo Ubuntu) e RHEL/Fedora/CentOS.
Também me concentrei em instalações de desktops e servidores. Uma quantidade significativa
de material é transferida para sistemas embarcados, como Android e OpenWRT, mas cabe a
você descobrir as diferenças nessas plataformas.

O que há de novo na terceira edição?


A segunda edição foi publicada durante um período de transição para sistemas Linux.
Vários componentes tradicionais estavam em processo de substituição, o que dificultava
o manuseio de alguns assuntos, pois os leitores podiam encontrar uma grande variedade de
configurações. Agora, no entanto, essas novas peças (systemd em particular) têm adoção
quase universal, então consegui simplificar uma boa parte da discussão.

Mantive a ênfase no papel do kernel em um sistema Linux. este


material provou ser popular, e você provavelmente interage com o kernel mais do que
imagina.
Eu adicionei um novo capítulo apresentando a virtualização. Embora o Linux sempre
tenha sido popular em máquinas virtuais (como serviços em nuvem), esse tipo de virtualização
está fora do escopo deste livro, porque a maneira como o sistema opera em uma máquina
virtual é quase a mesma de um hardware “bare metal”. Portanto, a discussão aqui se
concentra principalmente em decifrar a terminologia que você encontrará. No entanto, os
contêineres ganharam popularidade desde que a segunda edição foi publicada e também se
encaixam aqui, porque basicamente consistem em um monte de recursos do Linux, como os
descritos no restante do livro. Containers fazem uso intenso de cgroups, que também
ganham novo tratamento nesta terceira edição.

Outros assuntos (não necessariamente relacionados a contêineres) expandi alegremente


estão o Logical Volume Manager, o sistema de registro journald e o IPv6 no material de rede.

Prefácio xxiii
Machine Translated by Google

Embora eu tenha adicionado uma quantidade significativa de conteúdo, o livro


ainda tem um tamanho razoável. Quero fornecer as informações que você precisa
para entrar no caminho mais rápido, e isso inclui explicar certos detalhes ao longo
do caminho que podem ser difíceis de entender, mas não quero que você tenha que
se tornar um levantador de peso para pegar isso livro. Depois de dominar os assuntos
importantes aqui, você não deve ter problemas para buscar e entender mais detalhes.
A primeira edição incluiu informações históricas que removi posteriormente para
melhorar o foco. Se você estiver interessado em Linux e como ele se relaciona com a
história do Unix, leia The Daemon, the Gnu, and the Penguin , de Peter H. Salus (Reed
Media Services, 2008). Ele faz um ótimo trabalho ao explicar como o software que
usamos evoluiu ao longo do tempo.

Uma Nota sobre Terminologia


Os nomes de certos elementos do sistema operacional causaram bastante debate
historicamente – até mesmo a própria palavra Linux . Deveria ser “Linux” ou deveria
ser “GNU/Linux” para refletir que o sistema operacional também contém partes do
Projeto GNU? Ao longo deste livro, tentei usar os nomes mais comuns e menos
estranhos possíveis.

xxiv Prefácio
Machine Translated by Google

1
A GRANDE IMAGEM

À primeira vista, um sistema operacional


contemporâneo como o Linux é muito complicado,
com um número vertiginoso de peças rodando e se
comunicando simultaneamente. Por exemplo, um
servidor web pode se comunicar com um servidor de banco de
dados, que por sua vez pode usar uma biblioteca compartilhada
que muitos outros programas usam. Como tudo isso consegue
funcionar e como você pode entender tudo isso?
A maneira mais eficaz de entender como um sistema operacional funciona é
por meio da abstração - uma maneira elegante de dizer que você pode ignorar a
maioria dos detalhes que compõem uma parte que você está tentando entender e
se concentrar em seu propósito básico e Operação. Por exemplo, quando você
anda de carro, normalmente não precisa pensar em detalhes como os parafusos de
montagem que prendem o motor dentro do carro ou as pessoas que constroem e
mantêm a estrada sobre a qual o carro dirige. Tudo o que você realmente precisa
saber é o que o carro faz (transporta você para outro lugar) e algumas noções
básicas sobre como usá-lo (como operar a porta e o cinto de segurança).
Machine Translated by Google

Esse nível de abstração pode funcionar se você for apenas um passageiro no carro.
Mas se você também precisa dirigi-lo, você precisa cavar mais fundo e dividir sua
abstração em algumas partes. Agora você expande seu conhecimento em três áreas: o carro
em si (como seu tamanho e capacidades), como operar os controles (volante, pedal do
acelerador e assim por diante) e os recursos da estrada.
A abstração pode ser de grande ajuda quando você está tentando encontrar e corrigir
problemas. Por exemplo, digamos que você esteja dirigindo um carro e a viagem seja difícil.
Você pode avaliar rapidamente as três abstrações básicas relacionadas ao carro
mencionadas para determinar a origem do problema. Deve ser bastante fácil eliminar as
duas primeiras abstrações (seu carro ou a maneira como você está dirigindo) se nenhuma
delas for o problema, para que você possa reduzir o problema à própria estrada. Você
provavelmente vai descobrir que a estrada é esburacada. Agora, se você quiser, pode cavar
mais fundo em sua abstração da estrada e descobrir por que a estrada se deteriorou ou, se a
estrada é nova, por que os trabalhadores da construção fizeram um péssimo trabalho.
Os desenvolvedores de software usam a abstração como uma ferramenta ao construir
um sistema operacional e seus aplicativos. Existem muitos termos para uma subdivisão
abstrata em software de computador – incluindo subsistema, módulo e pacote –
mas usaremos o termo componente neste capítulo porque é simples. Ao construir um
componente de software, os desenvolvedores normalmente não pensam muito sobre a
estrutura interna de outros componentes, mas consideram outros componentes que podem
usar (para que não precisem escrever nenhum software adicional desnecessário) e como usá-
los .
Este capítulo fornece uma visão geral de alto nível dos componentes que compõem um
sistema Linux. Embora cada um tenha um número enorme de detalhes técnicos em sua
composição interna, vamos ignorar esses detalhes e nos concentrar no que os componentes
fazem em relação a todo o sistema. Veremos os detalhes nos capítulos subsequentes.

1.1 Níveis e Camadas de Abstração em um Sistema Linux


Usar abstração para dividir sistemas de computação em componentes torna as coisas mais
fáceis de entender, mas não funciona sem organização. Organizamos os componentes em
camadas ou níveis, classificações (ou agrupamentos) de componentes de acordo com a
posição dos componentes entre o usuário e o hardware. Navegadores da Web, jogos e afins
ficam na camada superior; na camada inferior temos a memória no hardware do computador
- os 0s e 1s. O sistema operacional ocupa muitas das camadas intermediárias.

Um sistema Linux tem três níveis principais. A Figura 1-1 mostra esses níveis e
alguns dos componentes dentro de cada nível. O hardware está na base.
O hardware inclui a memória, bem como uma ou mais unidades de processamento
central (CPUs) para realizar cálculos e ler e gravar na memória.
Dispositivos como discos e interfaces de rede também fazem parte do hardware.
O próximo nível é o kernel, que é o núcleo do sistema operacional.
O kernel é um software residente na memória que informa à CPU onde procurar sua próxima
tarefa. Atuando como mediador, o kernel gerencia o hardware (especialmente a memória
principal) e é a interface primária entre o hardware e qualquer programa em execução.

2 Capítulo 1
Machine Translated by Google

Processos — os programas em execução que o kernel gerencia — compõem coletivamente o


nível superior do sistema, chamado espaço do usuário. (Um termo mais específico para processo é
processo do usuário, independentemente de um usuário interagir diretamente com o processo. Por
exemplo, todos os servidores da Web são executados como processos do usuário.)

Processos do usuário

Interface gráfica do usuário Servidores Casca

Kernel Linux

Chamadas do sistema Gerenciamento de processos Gerenciamento de memória

Drivers de dispositivo

Hardware

Processador (CPU) Memória principal (RAM) Discos Portas de rede

Figura 1-1: Organização geral do sistema Linux

Há uma diferença crítica entre como o kernel e o usuário profissional


cesses run: o kernel é executado em modo kernel e os processos de usuário são executados
em modo de usuário. O código executado no modo kernel tem acesso irrestrito ao processador e
à memória principal. Este é um privilégio poderoso, mas perigoso, que permite ao kernel facilmente
corromper e travar todo o sistema. A área de memória que somente o kernel pode acessar é
chamada de espaço do kernel.
O modo de usuário, em comparação, restringe o acesso a um subconjunto (geralmente bem
pequeno) de memória e operações seguras da CPU. O espaço do usuário refere-se às partes da
memória principal que os processos do usuário podem acessar. Se um processo comete um erro e
trava, as consequências são limitadas e podem ser corrigidas pelo kernel.
Isso significa que, se o seu navegador da web travar, provavelmente não derrubará a computação
científica que está sendo executada em segundo plano há dias.
Em teoria, um processo de usuário descontrolado não pode causar sérios danos ao
resto do sistema. Na realidade, depende do que você considera “dano grave”, bem como dos
privilégios particulares do processo, porque alguns processos podem fazer mais do que outros.
Por exemplo, um processo de usuário pode destruir completamente os dados em um disco? Com
as permissões corretas, sim – e você pode considerar isso bastante perigoso. No entanto, existem
salvaguardas para evitar isso, e a maioria dos processos simplesmente não pode causar estragos
dessa maneira.

A Grande Imagem 3
Machine Translated by Google

NOTA O kernel Linux pode executar threads do kernel, que se parecem muito com processos, mas têm
acesso ao espaço do kernel. Alguns exemplos são kthreadd e kblockd.

1.2 Hardware: Entendendo a Memória Principal


De todo o hardware em um sistema de computador, a memória principal é talvez a mais
importante. Em sua forma mais bruta, a memória principal é apenas uma grande área de
armazenamento para um monte de 0s e 1s. Cada slot para um 0 ou 1 é chamado de bit. É aqui que
residem o kernel e os processos em execução - eles são apenas grandes coleções de bits. Todas
as entradas e saídas de dispositivos periféricos fluem pela memória principal, também como um
monte de bits. Uma CPU é apenas um operador na memória; ele lê suas instruções e dados da
memória e grava os dados de volta na memória.
Você ouvirá frequentemente o termo estado em referência à memória, processos, kernel e
outras partes de um sistema de computador. Estritamente falando, um estado é um arranjo
particular de bits. Por exemplo, se você tiver quatro bits na memória, 0110, 0001 e 1011
representam três estados diferentes.
Quando você considera que um único processo pode facilmente consistir em milhões de
bits na memória, geralmente é mais fácil usar termos abstratos ao falar sobre estados. Em vez
de descrever um estado usando bits, você descreve o que algo fez ou está fazendo no momento.
Por exemplo, você pode dizer “O processo está aguardando entrada” ou “O processo está
executando o Estágio 2 de sua inicialização”.

NOTA Como é comum referir-se ao estado em termos abstratos em vez dos bits reais, o termo imagem
refere-se a um arranjo físico específico de bits.

1.3 O Núcleo
Por que estamos falando de memória principal e estados? Quase tudo o que o kernel faz gira
em torno da memória principal. Uma das tarefas do kernel é dividir a memória em muitas
subdivisões, e ele deve manter sempre certas informações de estado sobre essas subdivisões.
Cada processo obtém seu próprio compartilhamento de memória e o kernel deve garantir que cada
processo mantenha seu compartilhamento.
O kernel é responsável por gerenciar tarefas em quatro áreas gerais do sistema:

Processos O kernel é responsável por determinar quais processos podem usar a CPU.

Memória O kernel precisa acompanhar toda a memória — o que está atualmente alocado
para um processo específico, o que pode ser compartilhado entre os processos e o que está
livre.
Drivers de dispositivo O kernel atua como uma interface entre o hardware (como um
disco) e os processos. Geralmente é trabalho do kernel operar o hardware.

Chamadas de sistema e suporte Processos normalmente usam chamadas de sistema para


se comunicar com o kernel.

Vamos agora explorar brevemente cada uma dessas áreas.

4 Capítulo 1
Machine Translated by Google

NOTA Se você estiver interessado no funcionamento detalhado de um kernel, dois bons livros são
Operating System Concepts, 10ª edição, por Abraham Silberschatz, Peter B.
Galvin e Greg Gagne (Wiley, 2018) e Modern Operating Systems, 4ª edição, de Andrew S.
Tanenbaum e Herbert Bos (Prentice Hall, 2014).

1.3.1 Gestão de Processos


O gerenciamento de processos descreve o início, a pausa, a retomada, o agendamento e o
término dos processos. Os conceitos por trás de iniciar e encerrar processos são bastante diretos,
mas descrever como um processo usa a CPU em seu curso normal de operação é um pouco
mais complexo.
Em qualquer sistema operacional moderno, muitos processos são executados
“simultaneamente”. Por exemplo, você pode ter um navegador da Web e uma planilha abertos em
um computador desktop ao mesmo tempo. No entanto, as coisas não são como parecem: os
processos por trás desses aplicativos geralmente não são executados exatamente ao mesmo
tempo.
Considere um sistema com uma CPU de um núcleo. Muitos processos podem usar a CPU,
mas apenas um processo pode realmente usar a CPU a qualquer momento. Na prática, cada
processo usa a CPU por uma pequena fração de segundo e depois pausa; então outro processo
usa a CPU por outra pequena fração de segundo; em seguida, outro processo dá uma volta, e
assim por diante. O ato de um processo ceder o controle da CPU para outro processo é chamado
de troca de contexto.
Cada pedaço de tempo - chamado de fatia de tempo - dá a um processo tempo suficiente para
computação significativa (e, de fato, um processo geralmente termina sua tarefa atual durante
uma única fatia). No entanto, como as fatias são tão pequenas, os humanos não podem percebê-
las, e o sistema parece estar executando vários processos ao mesmo tempo (um recurso conhecido
como multitarefa).
O kernel é responsável pela troca de contexto. Para entender como isso
funciona, vamos pensar em uma situação em que um processo está sendo executado no modo de
usuário, mas sua fatia de tempo está ativa. Aqui está o que acontece:

1. A CPU (o hardware real) interrompe o processo atual com base em um temporizador interno,
alterna para o modo kernel e devolve o controle ao kernel.

2. O kernel registra o estado atual da CPU e da memória, o que será essencial para retomar o
processo que acabou de ser interrompido.

3. O kernel executa quaisquer tarefas que possam surgir durante o


fatia de tempo anterior (como coleta de dados de operações de entrada e saída, ou E/S).

4. O kernel agora está pronto para permitir que outro processo seja executado. O kernel analisa a
lista de processos que estão prontos para execução e escolhe um.

5. O kernel prepara a memória para este novo processo e então prepara a CPU.

6. O kernel informa à CPU quanto tempo o intervalo de tempo para o novo processo
Vai durar.

7. O kernel muda a CPU para o modo de usuário e passa o controle da CPU para o processo.

A Grande Imagem 5
Machine Translated by Google

A troca de contexto responde à importante questão de quando o kernel é executado. A resposta é que
ele é executado entre as fatias de tempo do processo durante uma troca de contexto.

No caso de um sistema multi-CPU, como a maioria das máquinas atuais, as coisas


tornar-se um pouco mais complicado porque o kernel não precisa abrir mão do controle de sua CPU
atual para permitir que um processo seja executado em uma CPU diferente, e mais de um processo pode
ser executado por vez. No entanto, para maximizar o uso de todas as CPUs disponíveis, o kernel
normalmente executa essas etapas de qualquer maneira (e pode usar certos truques para obter um pouco
mais de tempo de CPU).

1.3.2 Gerenciamento de Memória

O kernel deve gerenciar a memória durante uma troca de contexto, o que pode ser um trabalho complexo.
As seguintes condições devem ser mantidas:

•O kernel deve ter sua própria área privada na memória que os processos do usuário não podem
acessar.

•Cada processo de usuário precisa de sua própria seção de memória.

• Um processo de usuário pode não acessar a memória privada de outro


processo.

•Os processos do usuário podem compartilhar memória.

•Algumas memórias nos processos do usuário podem ser somente leitura.

• O sistema pode usar mais memória do que está fisicamente presente usando
espaço em disco como auxiliar.

Felizmente para o kernel, existe ajuda. As CPUs modernas incluem uma unidade de gerenciamento de
memória (MMU) que permite um esquema de acesso à memória chamado memória virtual. Ao usar a memória
virtual, um processo não acessa diretamente a memória por sua localização física no hardware. Em vez disso,
o kernel configura cada processo para agir como se tivesse uma máquina inteira para si. Quando o processo
acessa parte de sua memória, a MMU intercepta o acesso e usa um mapa de endereços de memória para
traduzir a localização da memória do ponto de vista do processo para uma localização real da memória física
na máquina. O kernel ainda deve inicializar e manter e alterar continuamente esse mapa de endereços de
memória. Por exemplo, durante uma troca de contexto, o kernel precisa alterar o mapa do processo de saída
para o processo de entrada.

NOTA A implementação de um mapa de endereços de memória é chamada de tabela de páginas.

Você aprenderá mais sobre como visualizar o desempenho da memória no Capítulo 8.

1.3.3 Drivers e Gerenciamento de Dispositivos

O papel do kernel com os dispositivos é relativamente simples. Um dispositivo é normalmente acessível


apenas no modo kernel porque o acesso impróprio (como um processo de usuário pedindo para desligar a
energia) pode travar a máquina. Uma dificuldade notável

6 Capítulo 1
Machine Translated by Google

é que dispositivos diferentes raramente têm a mesma interface de programação, mesmo que os
dispositivos executem a mesma tarefa (por exemplo, duas placas de rede diferentes). Portanto, os
drivers de dispositivo tradicionalmente fazem parte do kernel e se esforçam para apresentar uma
interface uniforme aos processos do usuário para simplificar o trabalho do desenvolvedor de software.

1.3.4 Chamadas e Suporte do Sistema

Existem vários outros tipos de recursos do kernel disponíveis para os processos do usuário.
Por exemplo, chamadas de sistema (ou syscalls) executam tarefas específicas que um processo de
usuário sozinho não pode fazer bem ou de todo. Por exemplo, os atos de abrir, ler e gravar arquivos
envolvem chamadas de sistema.
Duas chamadas de sistema, fork() e exec(), são importantes para entender como os processos
são iniciados:

fork() Quando um processo chama fork(), o kernel cria uma cópia quase idêntica do processo.

exec() Quando um processo chama exec(program), o kernel carrega e inicia o programa,


substituindo o processo atual.

Além de init (veja o Capítulo 6), todos os novos processos de usuário em um sistema Linux são
iniciados como resultado de fork() e, na maioria das vezes, você também executa exec() para iniciar
um novo programa em vez de executar uma cópia de um processo existente. Um exemplo muito
simples é qualquer programa que você executa na linha de comando, como o ls
comando para mostrar o conteúdo de um diretório. Quando você insere ls em uma janela de
terminal, o shell que está sendo executado dentro da janela do terminal chama fork() para criar uma
cópia do shell e, em seguida, a nova cópia do shell chama exec(ls) para executar ls. A Figura 1-2
mostra o fluxo de processos e chamadas de sistema para iniciar um programa como ls.

Concha garfo() Concha

cópia do escudo exec(ls) ls

Figura 1-2: Iniciando um novo processo

NOTA As chamadas do sistema são normalmente indicadas entre parênteses. No exemplo mostrado em
Figura 1-2, o processo que solicita ao kernel para criar outro processo deve executar uma
chamada de sistema fork() . Essa notação deriva da forma como a chamada seria escrita na
linguagem de programação C. Você não precisa saber C para entender este livro; apenas lembre-
se de que uma chamada de sistema é uma interação entre um processo e o kernel.
Além disso, este livro simplifica certos grupos de chamadas de sistema. Por exemplo, exec()
refere-se a uma família inteira de chamadas de sistema que executam uma tarefa semelhante, mas
diferem na programação. Há também uma variante de um processo chamado thread, que abordaremos
no Capítulo 8.

A Grande Imagem 7
Machine Translated by Google

O kernel também suporta processos de usuário com recursos diferentes das chamadas de sistema
tradicionais, sendo os pseudodispositivos os mais comuns .
Os pseudodispositivos parecem dispositivos para os processos do usuário, mas são implementados
puramente em software. Isso significa que eles tecnicamente não precisam estar no kernel, mas geralmente
estão lá por razões práticas. Por exemplo, o dispositivo gerador de números aleatórios do kernel (/ dev/
random) seria difícil de implementar de forma segura com um processo de usuário.

NOTA Tecnicamente, um processo de usuário que acessa um pseudodispositivo deve usar uma chamada de sistema para abrir o dispositivo,

portanto, os processos não podem evitar totalmente as chamadas de sistema.

1.4 Espaço do usuário


Como mencionado anteriormente, a memória principal que o kernel aloca para os processos do usuário é
chamada de espaço do usuário. Como um processo é simplesmente um estado (ou imagem) na memória, o
espaço do usuário também se refere à memória para toda a coleção de processos em execução. (Você também
pode ouvir o termo mais informal userland
usado para espaço do usuário; às vezes, isso também significa que os programas estão sendo executados no
espaço do usuário.)
A maior parte da ação real em um sistema Linux acontece no espaço do usuário.
Embora todos os processos sejam essencialmente iguais do ponto de vista do kernel, eles realizam tarefas
diferentes para os usuários. Existe uma estrutura de nível de serviço (ou camada) rudimentar para os tipos de
componentes do sistema que os processos do usuário representam. A Figura 1-3 mostra como um exemplo de
conjunto de componentes se encaixa e interage em um sistema Linux. Os serviços básicos estão no nível inferior
(mais próximo do kernel), os serviços utilitários estão no meio e os aplicativos que os usuários tocam estão no topo.
A Figura 1-3 é um diagrama bastante simplificado porque apenas seis componentes são mostrados, mas você
pode ver que os componentes na parte superior estão mais próximos do usuário (a interface do usuário e o
navegador da web); os componentes no nível médio incluem um servidor de cache de nome de domínio que o
navegador da Web usa; e há vários componentes menores na parte inferior.

Processos do usuário

Interface de usuário Navegador da Web

Servidor de cache de nome

configuração de rede Barramento de comunicação Registro de diagnóstico

Figura 1-3: Tipos de processo e interações

8 Capítulo 1
Machine Translated by Google

O nível inferior tende a consistir em pequenos componentes que realizam pecado


gle, tarefas descomplicadas. O nível médio tem componentes maiores, como serviços de correio,
impressão e banco de dados. Finalmente, os componentes no nível superior executam tarefas
complicadas que o usuário geralmente controla diretamente. Os componentes também usam outros
componentes. Geralmente, se um componente deseja usar outro, o segundo componente está no
mesmo nível de serviço ou abaixo.
No entanto, a Figura 1-3 é apenas uma aproximação da disposição do espaço do usuário. Na
realidade, não há regras no espaço do usuário. Por exemplo, a maioria dos aplicativos e serviços
gravam mensagens de diagnóstico conhecidas como logs. A maioria dos programas usa o serviço
syslog padrão para escrever mensagens de log, mas alguns preferem fazer todo o registro por conta
própria.
Além disso, é difícil categorizar alguns componentes do espaço do usuário.
Componentes de servidor, como servidores da Web e de banco de dados, podem ser considerados
aplicativos de nível muito alto porque suas tarefas geralmente são complicadas, portanto, você pode
colocá-los no nível superior na Figura 1-3. No entanto, os aplicativos do usuário podem depender
desses servidores para executar tarefas que eles preferem não fazer por conta própria, portanto, você
também pode argumentar para colocá-los no nível intermediário.

1.5 Usuários
O kernel Linux suporta o conceito tradicional de um usuário Unix. Um usuário é uma entidade que
pode executar processos e possuir arquivos. Um usuário é mais frequentemente associado a um
nome de usuário; por exemplo, um sistema pode ter um usuário chamado billyjoe.
No entanto, o kernel não gerencia os nomes de usuário; em vez disso, ele identifica os usuários por
meio de identificadores numéricos simples chamados IDs de usuário. (Você aprenderá mais sobre
como os nomes de usuário correspondem aos IDs de usuário no Capítulo 7.)
Os usuários existem principalmente para dar suporte a permissões e limites. Todo processo
de espaço de usuário tem um proprietário de usuário, e diz-se que os processos são executados
como o proprietário. Um usuário pode encerrar ou modificar o comportamento de seus próprios
processos (dentro de certos limites), mas não pode interferir nos processos de outros usuários.
Além disso, os usuários podem possuir arquivos e optar por compartilhá-los com outros usuários.

Um sistema Linux normalmente tem um número de usuários além daqueles que correspondem
aos seres humanos reais que usam o sistema. Você lerá sobre isso com mais detalhes no Capítulo 3,
mas o usuário mais importante a ser conhecido é o root. O usuário root é uma exceção às regras
anteriores porque o root pode encerrar e alterar os processos de outro usuário e acessar qualquer
arquivo no sistema local. Por esse motivo, o root é conhecido como superusuário. Uma pessoa que
pode operar como root – isto é, que tem acesso root – é um administrador em um sistema Unix
tradicional.

NOTA Operar como root pode ser perigoso. Pode ser difícil identificar e corrigir erros porque o sistema permite
que você faça qualquer coisa, mesmo que seja prejudicial ao sistema.
Por esse motivo, os projetistas de sistemas tentam constantemente tornar o acesso root o mais
desnecessário possível – por exemplo, não exigindo acesso root para alternar entre redes sem fio em
um notebook. Além disso, por mais poderoso que seja o usuário root, ele ainda é executado no modo
de usuário do sistema operacional, não no modo kernel.

A Grande Imagem 9
Machine Translated by Google

Grupos são conjuntos de usuários. O objetivo principal dos grupos é permitir que um
usuário compartilhe o acesso a arquivos com outros membros de um grupo.

1.6 Olhando para a frente


Até agora, você viu o que constitui um sistema Linux em execução . Os processos do usuário
compõem o ambiente com o qual você interage diretamente; o kernel gerencia processos e hardware.
Tanto o kernel quanto os processos residem na memória.
Esta é uma ótima informação básica, mas você não pode aprender os detalhes de um
sistema Linux lendo sobre ele sozinho; você precisa sujar as mãos. O próximo capítulo inicia sua
jornada ensinando alguns conceitos básicos sobre o espaço do usuário. Ao longo do caminho, você
aprenderá sobre a maior parte do sistema Linux que este capítulo não discute: armazenamento de
longo prazo (discos, arquivos e similares). Afinal, você precisa armazenar seus programas e dados
em algum lugar.

10 Capítulo 1
Machine Translated by Google

2
COMANDOS BÁSICOSAND
HIERARQUIA DE DIRETÓRIO

Este capítulo é um guia para os comandos


e utilitários do Unix que você encontrará ao
longo deste livro. Este é um material preliminar,
e você já deve conhecer uma quantidade
substancial dele. Mesmo se você achar que está atualizado,
reserve alguns momentos para folhear o capítulo apenas
para ter certeza, especialmente quando se trata do material
de hierarquia de diretórios na Seção 2.19.
Por que comandos Unix? Este não é um livro sobre como o Linux funciona? É, de
claro, mas o Linux é um sabor de Unix no coração. Você verá a palavra Unix neste
capítulo mais do que Linux porque você pode levar o que aprendeu diretamente para o
BSD e outros sistemas com sabor de Unix. Tentei evitar cobrir muitas extensões de
interface de usuário específicas do Linux, não apenas para fornecer uma base melhor
para o uso de outros sistemas operacionais, mas também porque essas extensões
tendem a ser instáveis. Você poderá se adaptar ao novo Linux
Machine Translated by Google

libera muito mais rapidamente se você conhecer os comandos principais. Além disso,
conhecer esses comandos pode aumentar sua compreensão do kernel, pois muitos
correspondem diretamente às chamadas do sistema.

NOTA Para mais detalhes sobre Unix para iniciantes do que você encontrará aqui, considere ler
The Linux Command Line, 2ª edição (No Starch Press, 2019), UNIX for the Impatient, 2ª
edição (Addison-Wesley Professional, 1995) e Learning the UNIX Operating System, 5ª
edição (O'Reilly, 2001).

2.1 O Bourne Shell: /bin/sh


O shell é uma das partes mais importantes de um sistema Unix. Um shell é um programa
que executa comandos, como os que os usuários inserem em uma janela de terminal. Esses
comandos podem ser outros programas ou recursos internos do shell. O shell também serve
como um pequeno ambiente de programação. Os programadores de Unix geralmente
dividem tarefas comuns em componentes menores e usam o shell para gerenciar tarefas e
juntar as coisas.
Muitas partes importantes do sistema são, na verdade , scripts de shell — arquivos
de texto que contêm uma sequência de comandos de shell. Se você já trabalhou com MS-
DOS anteriormente, pode pensar nos scripts de shell como arquivos .BAT muito poderosos.
Por serem importantes, o Capítulo 11 é inteiramente dedicado a scripts de shell.
À medida que você progride neste livro e ganha prática, você aumentará sua
conhecimento de manipulação de comandos usando o shell. Uma das melhores coisas
sobre o shell é que, se você cometer um erro, poderá ver facilmente o que digitou para
descobrir o que deu errado e tentar novamente.
Existem muitos shells Unix diferentes, mas todos derivam recursos do
Bourne shell (/ bin/ sh), um shell padrão desenvolvido no Bell Labs para as primeiras
versões do Unix. Todo sistema Unix precisa de uma versão do shell Bourne para funcionar
corretamente, como você verá ao longo deste livro.
O Linux usa uma versão aprimorada do shell Bourne chamada bash ou shell
“Bourne-again”. O shell bash é o shell padrão na maioria das distribuições Linux, e /bin/ sh
normalmente é um link para bash em um sistema Linux. Você deve usar o shell bash ao
executar os exemplos deste livro.

NOTA Poderá não ter o bash como a sua shell por omissão se estiver a usar este capítulo como guia
para uma conta Unix em uma organização onde você não é o administrador do sistema. Você
pode alterar seu shell com chsh ou pedir ajuda ao administrador do sistema.

2.2 Usando o Shell


Ao instalar o Linux, você deve criar pelo menos um usuário regular para ser sua conta
pessoal. Para este capítulo, você deve fazer login como o usuário regular
do utilizador.

12 Capítulo 2
Machine Translated by Google

2.2.1 A Janela Shell


Após o login, abra uma janela de shell (geralmente chamada de terminal). A maneira mais
fácil de fazer isso a partir de uma GUI como o Gnome ou o KDE é abrir um aplicativo de
terminal, que inicia um shell dentro de uma nova janela. Depois de abrir um shell, ele deve
exibir um prompt na parte superior que geralmente termina com um cifrão ($). No Ubuntu,
esse prompt deve se parecer com name@host:path$, e no Fedora, é [name@host path]$,
onde name é seu nome de usuário, host é o nome de sua máquina e path é seu diretório
de trabalho atual ( consulte a Seção 2.4.1). Se você estiver familiarizado com o Windows,
a janela do shell será semelhante a um prompt de comando do DOS; no macOS, o aplicativo
Terminal é essencialmente o mesmo que uma janela de shell do Linux.

Este livro contém muitos comandos que você digitará em um prompt do shell.
Todos eles começam com um único $ para denotar o prompt do shell. Por exemplo, digite
este comando (apenas a parte em negrito, não o $) e pressione ENTER:

$ echo Olá.

NOTA Muitos comandos shell neste livro começam com #. Você deve executar esses comandos como
superusuário (root), portanto, eles exigem cuidado extra. A melhor prática ao executá-los
é usar o sudo para fornecer alguma proteção e um log que você possa consultar
posteriormente para possíveis erros. Você verá como fazer isso na Seção 2.20.

Agora digite este comando:

$ cat /etc/passwd

Este comando exibe o conteúdo do arquivo de informações do sistema /etc/ passwd e,


em seguida, retorna o prompt do shell. Não se preocupe com o que esse arquivo faz agora;
você aprenderá tudo sobre isso no Capítulo 7.
Os comandos geralmente começam com um programa a ser executado e podem ser
seguidos por argumentos que informam ao programa em que operar e como fazê-lo.
Aqui, o programa é cat, e há um argumento, /etc/passwd. Muitos argumentos são opções
que modificam o comportamento padrão de um programa e normalmente começam com
um traço (-). Você verá isso em breve na discussão de ls.
No entanto, existem algumas exceções que não seguem essa estrutura de comando
normal, como shells internos e o uso temporário de variáveis de ambiente.

2.2.2 gato
O programa cat é um dos mais fáceis de entender no Unix; ele simplesmente coloca o
conteúdo de um ou mais arquivos ou outra fonte de entrada. A sintaxe geral de um
comando cat é a seguinte:

$ cat arquivo1 arquivo2 ...

Comandos Básicos e Hierarquia de Diretórios 13


Machine Translated by Google

Quando você executa esse comando, cat imprime o conteúdo de arquivo1, arquivo2 e
quaisquer outros arquivos que você especificar como argumentos (indicados por ... no exemplo
anterior)
e, em seguida, sai. O programa é chamado de cat porque realiza concatenação quando imprime o
conteúdo de mais de um arquivo.
Existem muitas maneiras de executar o gato; vamos usá-lo para explorar a E/S do Unix.

2.2.3 Entrada Padrão e Saída Padrão


Os processos Unix usam fluxos de E/S para ler e gravar dados. Os processos leem dados de fluxos
de entrada e gravam dados em fluxos de saída. Os fluxos são muito flexíveis. Por exemplo, a origem
de um fluxo de entrada pode ser um arquivo, um dispositivo, uma janela de terminal ou até mesmo o
fluxo de saída de outro processo.
Para ver um fluxo de entrada em funcionamento, digite cat (sem argumentos) e pressione
ENTER. Desta vez, você não obterá nenhuma saída imediata e não receberá seu prompt do shell
de volta porque o cat ainda está em execução. Agora digite qualquer coisa e pressione ENTER
no final de cada linha. Quando usado assim, o comando cat repete qualquer linha que você digitar.
Quando estiver suficientemente entediado, pressione CTRL-D em uma linha vazia para encerrar cat
e retornar ao prompt do shell.

A razão pela qual cat adota um comportamento interativo aqui tem a ver com streams.
Quando você não especifica um nome de arquivo de entrada, cat lê a partir do fluxo de entrada
padrão fornecido pelo kernel do Linux em vez de um fluxo conectado a um arquivo. Nesse caso, a
entrada padrão é conectada ao terminal onde você executa o cat.

OBSERVAÇÃO Pressionar CTRL-D em uma linha vazia interrompe a entrada de entrada padrão atual do terminal
com uma mensagem EOF (fim de arquivo) (e geralmente encerra um programa). Não confunda isso
com CTRL-C, que normalmente encerra um programa independentemente de sua entrada ou saída.

A saída padrão é semelhante. O kernel dá a cada processo um fluxo de saída padrão onde ele
pode escrever sua saída. O comando cat sempre grava sua saída na saída padrão. Quando você
executou cat no terminal, a saída padrão foi conectada a esse terminal, então é onde você viu a saída.

A entrada e a saída padrão são geralmente abreviadas como stdin e stdout.


Muitos comandos funcionam como cat ; se você não especificar um arquivo de entrada, o comando lê
de stdin. A saída é um pouco diferente. Alguns programas (como cat) enviam saída apenas para
stdout, mas outros têm a opção de enviar saída diretamente para arquivos.

Há um terceiro fluxo de E/S padrão, chamado erro padrão. Você verá isso na Seção 2.14.1.

Um dos melhores recursos dos fluxos padrão é que você pode manipulá-los facilmente
para ler e gravar em outros lugares além do terminal, como você aprenderá na Seção 2.14. Em
particular, você aprenderá como conectar fluxos a arquivos e outros processos.

14 Capítulo 2
Machine Translated by Google

2.3 Comandos Básicos


Agora vamos ver mais alguns comandos do Unix. A maioria dos programas a seguir aceita vários
argumentos, e alguns têm tantas opções e formatos que uma lista completa seria inútil. Esta é uma
lista simplificada dos comandos básicos; você não precisa de todos os detalhes ainda.

2.3.1 l
O comando ls lista o conteúdo de um diretório. O padrão é o diretório atual, mas você pode adicionar
qualquer diretório ou arquivo como argumento, e há muitas opções úteis. Por exemplo, use ls -l para
uma listagem detalhada (longa) e ls -F para exibir informações sobre o tipo de arquivo. Aqui está uma
lista longa de amostra; inclui o proprietário do arquivo (coluna 3), o grupo (coluna 4), o tamanho do
arquivo (coluna 5) e a data/hora da modificação (entre a coluna 5 e o nome do arquivo):

$ ls -l
total 3616
-rw-r--r-- 1 juser users 3804 28 de maio 10:40 abusive.c
-rw-r--r-- 1 juser users 4165 13 de agosto 10:01 bateria.zip
-rw-r--r-- 1 usuários de juser 131219 13 de agosto 10:33 beav_1.40-13.tar.gz
-rw-r--r-- 1 juser users 6255 20 de maio 14:34 country.c
drwxr-xr-x 2 usuários juser 4096 17 de julho 20:00 cs335
-rwxr-xr-x 1 usuários juser 7108 16 de junho 13:05 dhry
-rw-r--r-- 1 usuários de juser 11309 13 de agosto 10:26 dhry.c
-rw-r--r-- 1 usuários de juser 56 drwxr- 09 de julho 15:30 deve
xr-x 6 usuários de juser 4096 drwxr-xr-x 20 de fevereiro 13:51 dw
3 usuários de juser 4096 1 de julho 16:05 hough-stuff

Você aprenderá mais sobre a coluna 1 desta saída na Seção 2.17. Você pode ignorar a
coluna 2 por enquanto; é o número de links físicos para o arquivo e é explicado na Seção 4.6.

2.3.2 cp
Em sua forma mais simples, cp copia arquivos. Por exemplo, para copiar arquivo1 para
arquivo2, digite isto:

$ cp arquivo1 arquivo2

Você também pode copiar um arquivo para outro diretório, mantendo o mesmo arquivo
nome nesse diretório:

$ cp arquivo dir

Para copiar mais de um arquivo para um diretório (pasta) chamado dir, tente alguns
algo como este exemplo, que copia três arquivos:

$ cp arquivo1 arquivo2 arquivo3 dir

Comandos Básicos e Hierarquia de Diretórios 15


Machine Translated by Google

2,3,3 mv
O comando mv (mover) funciona como cp. Em sua forma mais simples, ele renomeia um
arquivo. Por exemplo, para renomear arquivo1 para arquivo2, digite isto:

$ mv arquivo1 arquivo2

Você também pode usar mv para mover arquivos para outros diretórios da mesma forma que cp.

2.3.4 toque
O comando touch pode criar um arquivo. Se o arquivo de destino já existir, toque em
não altera o arquivo, mas atualiza o carimbo de data/hora de modificação do arquivo.
Por exemplo, para criar um arquivo vazio, digite isto:

$ toque no arquivo

Em seguida, execute ls -l nesse arquivo. Você deve ver uma saída como a seguinte, onde a
data e a hora indicam quando você executou o touch:

$ ls -l arquivo
-rw-r--r-- 1 usuários juser 0 21 de maio 18:32 arquivo

Para ver uma atualização do carimbo de data/hora, aguarde pelo menos um minuto e
execute o mesmo comando de toque novamente. O carimbo de data/hora retornado por ls -l será atualizado.

2,3,5 mm
O comando rm exclui (remove) um arquivo. Depois de remover um arquivo, ele geralmente
desaparece do sistema e geralmente não pode ser recuperado a menos que você o restaure a partir
de um backup.

arquivo $ rm

2.3.6 eco
O comando echo imprime seus argumentos na saída padrão:

$ echo Olá novamente.


Olá de novo.

O comando echo é muito útil para encontrar expansões de shell globs (“curingas” como *) e
variáveis (como $HOME), que você encontrará mais adiante neste capítulo.

2.4 Navegando em Diretórios


A hierarquia de diretórios do Unix começa em /, também chamado de diretório raiz. O separador de
diretório é a barra (/), não a barra invertida (\). Existem vários

16 Capítulo 2
Machine Translated by Google

subdiretórios padrão no diretório raiz, como /usr, como você aprenderá na Seção 2.19.

Ao fazer referência a um arquivo ou diretório, você especifica um caminho ou nome de caminho.


Quando um caminho começa com / (como /usr/ lib), é um caminho completo ou absoluto .
Um componente de caminho identificado por dois pontos (..) especifica o pai de um
diretório. Por exemplo, se você estiver trabalhando em /usr/ lib, o caminho .. se referirá a /usr. Da
mesma forma, ../bin se referiria a /usr/ bin.
Um ponto (.) refere-se ao diretório atual; por exemplo, se você estiver em /usr/ lib, o
caminho . ainda é /usr/ lib e ./X11 é /usr/ lib/ X11. Você não terá que usar . muitas vezes porque
a maioria dos comandos padrão para o diretório atual se um caminho não começar com / (então
você pode usar apenas X11 em vez de ./X11 no exemplo anterior).

Um caminho que não começa com / é chamado de caminho relativo. Na maioria das
vezes, você trabalhará com nomes de caminho relativos, porque já estará dentro ou perto do
diretório de que precisa.
Agora que você tem uma noção da mecânica básica de diretórios, aqui estão
alguns comandos de diretório essenciais.

2.4.1 CD
O diretório de trabalho atual é o diretório em que um processo (como o shell) está
atualmente. Além do prompt do shell padrão na maioria das distribuições Linux, você pode ver
seu diretório atual com o comando pwd , descrito na Seção 2.5.3.

Cada processo pode definir independentemente seu próprio diretório de trabalho atual.
O comando cd altera o diretório de trabalho atual do shell:

$ cd você

Se você omitir dir, o shell retornará ao seu diretório pessoal, o diretório onde você iniciou
quando fez o login pela primeira vez. Alguns programas abreviam seu diretório pessoal com o
símbolo ~ (um til).

NOTA O comando cd é um shell embutido. Não funcionaria como um programa separado porque, se fosse
executado como um subprocesso, não poderia (normalmente) alterar o diretório de trabalho atual
de seu pai. Isso pode não parecer uma distinção particularmente importante no momento, mas
há momentos em que conhecer esse fato pode esclarecer a confusão.

2.4.2 mkdir
O comando mkdir cria um novo diretório dir:

$ mkdir você

2.4.3 é rm
O comando rmdir remove o diretório dir:

$ rmdir você

Comandos Básicos e Hierarquia de Diretórios 17


Machine Translated by Google

Se dir não estiver vazio, este comando falhará. No entanto, se você for impaciente, você
provavelmente não deseja excluir laboriosamente todos os arquivos e subdiretórios dentro do dir primeiro.
Você pode usar rm -r dir para excluir um diretório e seu conteúdo, mas tenha cuidado! Este é um dos poucos
comandos que podem causar sérios danos, especialmente se você o executar como superusuário. A opção -r

especifica a exclusão recursiva para excluir repetidamente tudo dentro do diretório. Não use o sinalizador -r com
globs como uma estrela (*). E acima de tudo, sempre verifique seu comando antes de executá-lo.

2.4.4 Shell Globbing (“Coringas”)


O shell pode corresponder padrões simples a nomes de arquivos e diretórios, um processo conhecido como
globbing. Isso é semelhante ao conceito de curingas em outros sistemas.
O mais simples deles é o caractere glob *, que informa ao shell para corresponder a qualquer número de
caracteres arbitrários. Por exemplo, o comando a seguir imprime uma lista de arquivos no diretório atual:

$ eco *

O shell combina argumentos contendo globs para nomes de arquivos, substitutos


os nomes de arquivo para esses argumentos e, em seguida, executa a linha de comando revisada. A
substituição é chamada de expansão porque o shell substitui todos os nomes de arquivo correspondentes
por uma expressão simplificada. Aqui estão algumas maneiras de usar para expandir nomes de arquivos: *

• at* se expande para todos os nomes de arquivo que começam com at.

• *at se expande para todos os nomes de arquivo que terminam com at.

• *at* se expande para todos os nomes de arquivo que contêm at.

Se nenhum arquivo corresponder a um glob, o shell bash não executará nenhuma expansão e o
O comando é executado com caracteres literais, como *. Por exemplo, tente um comando como echo
*dfkdsafh.

OBSERVAÇÃO Se você estiver acostumado com o prompt de comando do Windows, poderá digitar instintivamente *.* para
corresponder a todos os arquivos. Quebre este hábito agora. No Linux e em outras versões do Unix, você deve
usar * para corresponder a todos os arquivos. No shell do Unix, *.* corresponde apenas a arquivos e diretórios

que contenham o caractere ponto (.) em seus nomes. Os nomes de arquivo Unix não precisam de extensões e
geralmente não as carregam.

Outro caractere glob do shell, o ponto de interrogação (?), instrui o shell


para corresponder exatamente a um caractere arbitrário. Por exemplo, b?at corresponde ao barco
e pirralho.
Se você não quiser que o shell expanda um glob em um comando, coloque o glob entre aspas simples
(''). Por exemplo, o comando echo '*' imprime uma estrela.
Você achará isso útil para alguns dos comandos descritos no próximo

18 Capítulo 2
Machine Translated by Google

seção, como grep e find. (Você aprenderá mais sobre citações na Seção 11.2.)

OBSERVAÇÃO É importante lembrar que o shell executa expansões antes de executar os comandos e
somente então. Portanto, se um * chegar a um
nada
comando
com ele;sem
cabe
expandir,
ao comando
o shelldecidir
não fará
o que
mais
quer
fazer.

Há mais recursos de correspondência de padrões do shell, mas * e ?


são o que você precisa saber agora. A Seção 2.7 descreve o comportamento do glob com aqueles
arquivos engraçados que começam com um ponto.

2.5 Comandos Intermediários


Esta seção descreve os comandos intermediários mais essenciais do Unix.

2.5.1 pega
O comando grep imprime as linhas de um arquivo ou fluxo de entrada que corresponde a uma
expressão. Por exemplo, para imprimir as linhas no arquivo /etc/ passwd que contém a raiz do
texto, digite isto:

$ grep root /etc/passwd

O comando grep é extraordinariamente útil ao operar em vários arquivos ao mesmo tempo


porque imprime o nome do arquivo além da linha correspondente.
Por exemplo, se você quiser verificar todos os arquivos em /etc que contenham a palavra root,
você pode usar este comando:

$ grep root /etc/*

Duas das opções grep mais importantes são -i (para correspondências que não
diferenciam maiúsculas de minúsculas) e -v (que inverte a pesquisa - ou seja, imprime todas
as linhas que não correspondem). Há também uma variante mais poderosa chamada egrep
(que é apenas um sinônimo de grep -E).
grep entende expressões regulares, padrões que são fundamentados na teoria da
ciência da computação e são muito comuns em utilitários Unix. As expressões regulares são
mais poderosas do que os padrões de estilo curinga e têm uma sintaxe diferente. Há três
coisas importantes a serem lembradas sobre expressões regulares:

• .* corresponde a qualquer número de caracteres, incluindo nenhum (como o * em


globs e curingas).
• .+ corresponde a qualquer um ou mais caracteres.
• . corresponde exatamente a um caractere arbitrário.

Comandos Básicos e Hierarquia de Diretórios 19


Machine Translated by Google

NOTA A página de manual do grep(1) contém uma descrição detalhada de expressões regulares, mas pode ser um
pouco difícil de ler. Para saber mais, você pode ler Mastering Regular Expressions, 3ª edição, de
Jeffrey EF Friedl (O'Reilly, 2006), ou ver o capítulo de expressões regulares de Programming Perl, 4ª
edição, de Tom Christensen et al.
(O'Reilly, 2012). Se você gosta de matemática e está interessado em saber de onde vêm as expressões
regulares, procure Introduction to Automata Theory, Languages, and Computation, 3ª edição, de Jeffrey
Ullman e John Hopcroft (Prentice Hall, 2006).

2.5.2 menos
O comando less é útil quando um arquivo é muito grande ou quando a saída de um comando é longa
e rola para fora do topo da tela.
Para percorrer um arquivo grande como /usr/ share/ dict/ words, você pode usar o comando
less /usr/share/dict/words. Ao executar menos, você verá o conteúdo do arquivo uma tela de cada vez.
Pressione a barra de espaço para avançar no arquivo e pressione b (minúsculas) para retroceder uma
tela inteira. Para sair, pressione q.

OBSERVAÇÃO O comando less é uma versão aprimorada de um programa mais antigo chamado more. Os
desktops e servidores Linux têm menos, mas não é padrão em muitos sistemas embarcados e outros
sistemas Unix. Se você se deparar com uma situação em que não pode usar menos, tente mais.

Você também pode procurar texto dentro de menos. Por exemplo, para pesquisar para frente
para uma palavra, você pode digitar /palavra, e para pesquisar para trás, você pode usar ?palavra.
Ao encontrar uma correspondência, pressione n para continuar a pesquisa.
Como você aprenderá na Seção 2.14, você pode enviar a saída padrão de praticamente
qualquer programa diretamente para a entrada padrão de outro programa. Isso é excepcionalmente
útil quando você tem um comando com muita saída para filtrar e gostaria de usar algo como menos
para visualizar a saída. Aqui está um exemplo de envio da saída de um comando grep para less:

$ grep ie /usr/share/dict/words | menos

Experimente este comando por si mesmo. Você provavelmente encontrará muitos usos
semelhantes por menos.

2.5.3 pwd
O programa pwd (imprimir diretório de trabalho) simplesmente exibe o nome do diretório de trabalho
atual. Você pode estar se perguntando por que precisa disso quando a maioria das distribuições Linux
configura contas de usuário com o diretório de trabalho atual no prompt. Existem duas razões.

Primeiro, nem todos os prompts incluem o diretório de trabalho atual, especialmente porque você
pode querer se livrar dele em seu próprio prompt, pois ocupa muito espaço. Se você fizer isso, você
precisa de pwd.
Segundo, os links simbólicos sobre os quais você aprenderá na Seção 2.17.2 podem às vezes
obscurecer o verdadeiro caminho completo do diretório de trabalho atual. Use pwd -P para eliminar
essa confusão.

20 Capítulo 2
Machine Translated by Google

2.5.4 diferença

Para ver as diferenças entre dois arquivos de texto, use diff:

$ arquivo diff1 arquivo2

Várias opções podem controlar o formato da saída, e o formato de saída padrão geralmente é o mais
compreensível para seres humanos. No entanto, a maioria dos programadores prefere a saída de diff -u quando
precisa enviar a saída para outra pessoa, porque as ferramentas automatizadas têm mais facilidade com esse
formato.

2.5.5 arquivo

Se você vir um arquivo e não tiver certeza de seu formato, tente usar o comando file para ver se o sistema
consegue adivinhar:

$ arquivo arquivo

Você pode se surpreender com o quanto esse comando de aparência inocente pode fazer.

2.5.6 encontrar e localizar

É frustrante quando você sabe que um determinado arquivo está em uma árvore de diretórios em algum
lugar, mas você simplesmente não sabe onde. Execute find para localizar o arquivo no diretório da seguinte forma:

$ find dir -name file -print

Como a maioria dos programas nesta seção, find é capaz de algumas coisas extravagantes.
No entanto, não tente opções como -exec antes de conhecer o formulário mostrado aqui de cor e entender
por que você precisa das opções -name e -print .
O comando find aceita caracteres especiais de correspondência de padrões, como *, mas você deve colocá-
los entre aspas simples ('*') para proteger os caracteres especiais do recurso globbing do próprio shell.
(Lembre-se da Seção 2.4.4 que o shell expande globs antes de executar comandos.)

A maioria dos sistemas também possui um comando de localização para localizar arquivos. Em vez de
pesquisar um arquivo em tempo real, o locate pesquisa um índice que o sistema cria periodicamente.
Pesquisar com localizar é muito mais rápido que localizar, mas se o arquivo que você está procurando for mais
recente que o índice, localize não o encontrará.

2.5.7 cabeça e cauda

Os comandos head e tail permitem que você visualize rapidamente uma parte de um arquivo ou fluxo de
dados. Por exemplo, head /etc/passwd mostra as primeiras 10 linhas do arquivo de senha e tail /etc/passwd
mostra as últimas 10 linhas.
Para alterar o número de linhas a serem exibidas, use a opção -n , onde n é o número de linhas que
você deseja ver (por exemplo, head -5 /etc/passwd). Para imprimir linhas começando na linha n, use tail +n.

Comandos Básicos e Hierarquia de Diretórios 21


Machine Translated by Google

2.5.8 classificar

O comando sort coloca rapidamente as linhas de um arquivo de texto em ordem


alfanumérica. Se as linhas do arquivo começarem com números e você quiser classificar
em ordem numérica, use a opção -n . A opção -r inverte a ordem da classificação.

2.6 Alterando sua senha e shell


Use o comando passwd para alterar sua senha. A senha antiga será solicitada e a nova
senha será solicitada duas vezes.
As melhores senhas tendem a ser longas frases “sem sentido” que são fáceis de
lembrar. Quanto maior a senha (em termos de comprimento de caracteres), melhor;
tente para 16 caracteres ou mais. (Nos tempos antigos, o número de caracteres que
você poderia usar era limitado, então você foi aconselhado a adicionar caracteres
estranhos e tal.)
Você pode alterar seu shell com o comando chsh (para uma alternativa como zsh, ksh
ou tcsh), mas lembre-se de que este livro assume que você está executando o bash,
portanto, se você fizer uma alteração, alguns dos exemplos podem não funcionar .

Arquivos de 2,7 pontos

Mude para seu diretório pessoal se você ainda não estiver lá, digite ls para dar uma olhada
e execute ls -a. Você vê a diferença na saída?
Ao executar ls sem o -a, você não verá os arquivos de configuração chamados de dot files.
São arquivos e diretórios cujos nomes começam com um ponto (.).
Arquivos de pontos comuns são .bashrc e .login, e também existem diretórios de pontos,
como .ssh.
Não há nada de especial em arquivos ou diretórios de pontos. Alguns programas
não os mostram por padrão para que você não veja uma bagunça completa ao listar o
conteúdo do seu diretório pessoal. Por exemplo, ls não lista arquivos de ponto, a menos
que você use a opção -a . Além disso, globs de shell não correspondem a arquivos de
ponto, a menos que você use explicitamente um padrão como .*.

OBSERVAÇÃO Você pode ter problemas com globs porque .* corresponde . e .. (a corrente e
diretórios pais). Você pode querer usar um padrão como .[^.]* ou .??* para obter todos os
arquivos de ponto, exceto os diretórios atual e pai.

2.8 Ambiente e Variáveis de Shell


O shell pode armazenar variáveis temporárias, chamadas de variáveis de shell,
contendo os valores de strings de texto. Variáveis de shell são muito úteis para
acompanhar valores em scripts, e algumas variáveis de shell controlam a maneira como
o shell se comporta. (Por exemplo, o shell bash lê a variável PS1 antes de exibir o
prompt.)

22 Capítulo 2
Machine Translated by Google

Para atribuir um valor a uma variável shell, use o sinal de igual (=). Aqui está um
exemplo simples:

$ COISA = blá

O exemplo anterior define o valor da variável denominada STUFF como blah.


Para acessar esta variável, use $STUFF (por exemplo, tente executar echo $STUFF). Você
aprenderá sobre os muitos usos de variáveis de shell no Capítulo 11.

OBSERVAÇÃO Não coloque espaços ao redor do = ao atribuir uma variável.

Uma variável de ambiente é como uma variável de shell, mas não é específica do
shell. Todos os processos em sistemas Unix possuem armazenamento variável de ambiente.
A principal diferença entre as variáveis de ambiente e de shell é que o sistema operacional
passa todas as variáveis de ambiente do shell para os programas executados pelo shell,
enquanto as variáveis do shell não podem ser acessadas nos comandos que você executa.

Você atribui uma variável de ambiente com o comando de exportação do shell .


Por exemplo, se você quiser transformar a variável shell $STUFF em uma variável de
ambiente, use o seguinte:

$ COISA = blá
$ exportação COISAS

Como os processos filhos herdam as variáveis de ambiente de seus pais, muitos


programas os lêem para configuração e opções. Por exemplo, você pode colocar suas
opções de linha de comando menos favoritas na variável de ambiente LESS e menos usará
essas opções quando você executá-la. (Muitas páginas de manual contêm uma seção
chamada AMBIENTE que descreve essas variáveis.)

2.9 O Caminho de Comando


PATH é uma variável de ambiente especial que contém o caminho do comando (ou
caminho para abreviar), uma lista de diretórios do sistema que o shell procura ao tentar
localizar um comando. Por exemplo, quando você executa ls, o shell pesquisa os diretórios
listados em PATH para o programa ls . Se programas com o mesmo nome aparecerem em
vários diretórios no caminho, o shell executará o primeiro programa correspondente.

Se você executar echo $PATH, verá que os componentes do caminho estão separados
por dois pontos (:). Por exemplo:

$ echo $ PATH
/usr/local/bin:/usr/bin:/bin

Comandos Básicos e Hierarquia de Diretórios 23


Machine Translated by Google

Para dizer ao shell para procurar em mais lugares por programas, altere o PATH
variável de ambiente. Por exemplo, usando este comando, você pode adicionar um diretório dir ao
início do caminho para que o shell olhe em dir
antes de procurar em qualquer um dos outros diretórios PATH :

$ PATH=dir:$PATH

Ou você pode anexar um nome de diretório ao final da variável PATH ,


fazendo com que o shell olhe no diretório por último:

$ PATH=$PATH:dir

OBSERVAÇÃO Você pode apagar acidentalmente todo o seu caminho se digitar $PATH incorretamente ao
modificar seu caminho. Se isso acontecer, não entre em pânico! O dano não é permanente; você
pode simplesmente iniciar um novo shell. (Para um efeito duradouro, você precisa digitá-lo
incorretamente ao editar um determinado arquivo de configuração e, mesmo assim, não é difícil
corrigi-lo.) A maneira mais fácil de retornar ao normal é fechar a janela do terminal atual e iniciar outra.

2.10 Caracteres Especiais


Ao discutir o Linux com outras pessoas, você deve saber alguns nomes para alguns dos caracteres
especiais que encontrará. Se você se diverte com esse tipo de coisa, veja o “Jargon File” (http://
www.catb.org/ jargon/ html/) ou seu companheiro impresso, The New Hacker's Dictionary, 3rd edition,
de Eric S. Raymond (MIT Press, 1996).

A Tabela 2-1 descreve um conjunto selecionado de caracteres especiais, muitos dos quais você
já viu neste capítulo. Alguns utilitários, como a linguagem de programação Perl, usam quase todos
esses caracteres especiais! (Lembre-se de que esses são os nomes americanos para os personagens.)

Tabela 2-1: Caracteres especiais

Personagem Nome(s) Usos

*
estrela, asterisco Expressão regular, caractere glob
. ponto Diretório atual, delimitador de arquivo/nome de host
! bang Negação, histórico de comando

pipe Canais de comando

|/ (para frente) barra Delimitador de diretório, comando de pesquisa

\ invertida Literais, macros (nunca diretórios)

$ dólar Variáveis, fim de linha


'
tick, (simples) backtick Strings literais
`
de aspas, backquote Substituição de comando
"
aspas duplas Cordas semiliterais
^ acento circunflexo
Negação, início de linha

24 Capítulo 2
Machine Translated by Google

Personagem Nome(s) Usos


~
til, squiggle hash, Negação, atalho de diretório

# sustenido, libra Comentários, pré-processador, substituições

[] (quadrado) colchetes, Gamas

{} colchetes (curvas) sublinhado, Blocos de instrução, intervalos

_ sob Substituto barato para um espaço usado quando os


espaços não são desejados ou permitidos, ou quando os
algoritmos de preenchimento automático ficam confusos

NOTA Você verá frequentemente caracteres de controle marcados com um acento circunflexo; por exemplo, ^C para CTRL-C.

2.11 Edição de linha de comando


À medida que você brinca com o shell, observe que você pode editar a linha de comando
usando as teclas de seta para a esquerda e para a direita, bem como percorrer os comandos
anteriores usando as setas para cima e para baixo. Isso é padrão na maioria dos sistemas Linux.
No entanto, é uma boa ideia esquecer as teclas de seta e usar o controle
combinações de teclas em vez disso. Se você aprender os listados na Tabela 2-2, descobrirá
que é mais capaz de inserir texto nos muitos programas Unix que usam esses
pressionamentos de tecla padrão.

Tabela 2-2: Teclas de linha de comando

Teclas Ação

CTRL-B Mova o cursor para a esquerda

CTRL-F Mova o cursor para a direita

CTRL-P Visualize o comando anterior (ou mova o cursor para cima)

CTRL-N Visualize o próximo comando (ou mova o cursor para baixo)

CTRL-A Mova o cursor para o início da linha

CTRL-E Mova o cursor para o final da linha

CTRL-W Apagar a palavra anterior

CTRL-U Apagar do cursor até o início da linha

CTRL-K Apagar do cursor até o final da linha

CTRL-Y Colar texto apagado (por exemplo, de CTRL-U)

2.12 Editores de texto


Falando em edição, é hora de aprender um editor. Para levar a sério o Unix, você deve ser capaz
de editar arquivos de texto sem danificá-los. A maioria das partes do sistema usa arquivos de
configuração de texto simples (como os de /etc). Não é difícil editar arquivos, mas você fará isso
com tanta frequência que precisará de uma ferramenta poderosa para o trabalho.

Comandos Básicos e Hierarquia de Diretórios 25


Machine Translated by Google

Você deve tentar aprender um dos dois editores de texto Unix padrão de fato, vi e Emacs. A
maioria dos magos do Unix são religiosos sobre sua escolha de editor, mas não os ouvem. Basta
escolher por si mesmo. Se você escolher um que corresponda à sua maneira de trabalhar, será
mais fácil aprender. Basicamente, a escolha se resume a isso:

•Se você quer um editor que pode fazer quase tudo e tem extenso
ajuda online, e você não se importa de digitar um pouco mais para obter esses recursos,
experimente o Emacs.

•Se velocidade é tudo, dê uma chance; ele “joga” um pouco como um videogame.

Aprendendo os editores vi e Vim: Unix Text Processing, 7ª edição, por Arnold


Robbins, Elbert Hannah e Linda Lamb (O'Reilly, 2008), podem contar tudo o que você precisa
saber sobre o vi. Para o Emacs, use o tutorial online: inicie o Emacs, pressione CTRL-H e digite T.
Ou leia o GNU Emacs Manual, 18ª edição, de Richard M. Stallman (Free Software Foundation, 2018).

Você pode ficar tentado a experimentar um editor mais amigável quando


primeiro comece, como nano, Pico, ou um dos inúmeros editores de GUI por aí, mas se você
tende a criar um hábito com a primeira coisa que usa, não quer seguir esse caminho.

OBSERVAÇÃO A edição de texto é onde você começará a ver a diferença entre o terminal e a GUI.
Editores como o vi são executados dentro da janela do terminal, usando a interface de E/ S do
terminal padrão. Os editores de GUI iniciam sua própria janela e apresentam sua própria
interface, independente dos terminais. O Emacs é executado em uma GUI por padrão, mas
também será executado em uma janela de terminal.

2.13 Obtendo Ajuda Online


Os sistemas Linux vêm com uma grande quantidade de documentação. Para comandos básicos,
as páginas de manual (ou páginas de manual ) lhe dirão o que você precisa saber. Por exemplo,
para ver a página de manual do comando ls , execute man da seguinte forma:

$ man ls

A maioria das páginas de manual concentra-se principalmente em informações de


referência, talvez com alguns exemplos e referências cruzadas, mas é só isso. Não espere um
tutorial, e não espere um estilo literário envolvente.
Quando os programas têm muitas opções, a página de manual geralmente lista as opções
de forma sistemática (por exemplo, em ordem alfabética), mas não informa quais são as mais
importantes. Se você for paciente, geralmente poderá encontrar o que precisa saber na página
do manual. Se você estiver impaciente, peça a um amigo — ou pague alguém para ser seu amigo
para que você possa perguntar a ele ou ela.
Para pesquisar uma página de manual por palavra-chave, use a opção -k :

$ man -k palavra- chave

26 Capítulo 2
Machine Translated by Google

Isso é útil se você não souber bem o nome do comando que deseja. Por
exemplo, se você estiver procurando por um comando para classificar algo,
execute:

$ man -k ordenar
--recorte--
comm (1) - compara dois arquivos ordenados linha por linha
qsort (3) - ordena um array
sort (1) - ordena linhas de arquivos de texto
sortm (1) - ordena as mensagens
tsort (1) - executa ordenação topológica
--recorte--

A saída inclui o nome da página do manual, a seção do manual (veja abaixo)


e uma descrição rápida do que a página do manual contém.

OBSERVAÇÃO Se você tiver alguma dúvida sobre os comandos descritos nas seções anteriores,
poderá encontrar as respostas usando o comando man .

As páginas do manual são referenciadas por seções numeradas. Quando


alguém se refere a uma página de manual, geralmente coloca o número da seção
entre parênteses ao lado do nome, como ping(8). A Tabela 2-3 lista as seções e seus números.

Tabela 2-3: Seções do Manual Online

Seção Descrição

1 Comandos do usuário

2 Chamadas de sistema do kernel

3 Documentação da biblioteca de programação Unix de nível superior


4 Interface do dispositivo e informações do driver

5 Descrições de arquivos (arquivos de configuração do sistema)

6 Jogos

7 Formatos de arquivo, convenções e codificações (ASCII, sufixos e assim por diante)


8 Comandos do sistema e servidores

As seções 1, 5, 7 e 8 devem ser bons suplementos para este livro.


A Seção 4 pode ser de uso marginal, e a Seção 6 seria ótima se fosse um pouco
maior. Você provavelmente não conseguirá usar a Seção 3 se não for um programador,
mas poderá entender parte do material da Seção 2 depois de ler mais sobre chamadas
de sistema neste livro.
Alguns termos comuns têm muitas páginas de manual correspondentes em várias
seções. Por padrão, man exibe a primeira página que encontra. Você pode selecionar
uma página de manual por seção. Por exemplo, para ler a descrição do arquivo /etc/
passwd (ao contrário do comando passwd ), você pode inserir o número da seção antes
do nome da página assim:

$ man 5 senha

Comandos Básicos e Hierarquia de Diretórios 27


Machine Translated by Google

As páginas do manual cobrem o essencial, mas há muitas outras maneiras de obter ajuda online
(além de pesquisar na Internet). Se você está apenas procurando uma determinada opção para um
comando, tente inserir um nome de comando seguido por --help ou -h (a opção varia de comando para
comando). Você pode ter um dilúvio (como no caso de ls --help), ou pode encontrar exatamente o que
está procurando.

Algum tempo atrás, o Projeto GNU decidiu que não gostava muito de páginas de manual e
mudou para outro formato chamado info (ou texinfo).
Muitas vezes, essa documentação vai além de uma página de manual típica, mas pode ser mais
complexa. Para acessar um manual de informações, use info com o nome do comando:

comando $ info

Se você não gostar do leitor de informações , poderá enviar a saída para menos
(basta adicionar | menos).
Alguns pacotes despejam sua documentação disponível em /usr/ share/ doc
sem levar em conta sistemas manuais online como man ou info. Consulte este diretório em seu sistema
se estiver procurando por documentação – e, é claro, pesquise na Internet.

2.14 Entrada e Saída do Shell


Agora que você está familiarizado com comandos, arquivos e diretórios básicos do Unix, você está pronto
para aprender como redirecionar a entrada e a saída padrão. Vamos começar com a saída padrão.

Para enviar a saída do comando para um arquivo em vez do terminal, use o >
caractere de redirecionamento:

$ comando > arquivo

O shell cria o arquivo se ele ainda não existir. Se o arquivo existir, o shell
apaga (clobbers) o arquivo original primeiro. (Alguns shells têm parâmetros que impedem o clobbering.
Por exemplo, você pode inserir set -C para evitar o clobbering no bash.)

Você pode anexar a saída ao arquivo em vez de sobrescrevê-lo com


a >> sintaxe de redirecionamento:

$ comando >> arquivo

Esta é uma maneira prática de coletar a saída em um só lugar ao executar


seqüências de comandos relacionados.
Para enviar a saída padrão de um comando para a entrada padrão de outro comando, use a
barra vertical (|). Para ver como isso funciona, tente estes dois comandos:

$ head /proc/cpuinfo
$ head /proc/cpuinfo | tr é AZ

28 Capítulo 2
Machine Translated by Google

Você pode enviar a saída através de quantos comandos canalizados desejar; basta
adicionar outro pipe antes de cada comando adicional.

2.14.1 Erro Padrão


Ocasionalmente, você pode redirecionar a saída padrão, mas descobrir que o programa ainda
imprime algo no terminal. Isso é chamado de erro padrão (stderr); é um fluxo de saída
adicional para diagnóstico e depuração. Por exemplo, este comando produz um erro:

$ ls /ffffffffff > f

Após a conclusão, f deve estar vazio, mas você ainda vê a seguinte mensagem de
erro no terminal como erro padrão:

ls: não é possível acessar /ffffffffff: Arquivo ou diretório inexistente

Você pode redirecionar o erro padrão, se quiser. Por exemplo, para enviar a
saída padrão para f e o erro padrão para e, use a sintaxe 2> , assim:

$ ls /ffffffffff > f 2> e

O número 2 especifica o ID do fluxo que o shell modifica. Stream ID 1 é a saída padrão (o


padrão) e 2 é o erro padrão.
Você também pode enviar o erro padrão para o mesmo local que stdout com a notação
>& . Por exemplo, para enviar a saída padrão e o erro padrão para o arquivo chamado f,
tente este comando:

$ ls /ffffffffff > f 2>&1

2.14.2 Redirecionamento de Entrada Padrão


Para canalizar um arquivo para a entrada padrão de um programa, use o operador < :

$ head < /proc/cpuinfo

Você ocasionalmente encontrará um programa que requer esse tipo de redirecionamento,


mas como a maioria dos comandos Unix aceita nomes de arquivos como argumentos, isso não
é muito comum. Por exemplo, o comando anterior poderia ter sido escrito como head /proc/
cpuinfo.

2.15 Entendendo as mensagens de erro


Ao encontrar um problema em um sistema do tipo Unix, como o Linux, você deve ler a
mensagem de erro. Ao contrário das mensagens de outros sistemas operacionais, os erros do
Unix geralmente informam exatamente o que deu errado.

Comandos Básicos e Hierarquia de Diretórios 29


Machine Translated by Google

2.15.1 Anatomia de uma Mensagem de Erro Unix


A maioria dos programas Unix gera e relata as mesmas mensagens de erro básicas, mas pode
haver diferenças sutis entre a saída de dois programas quaisquer. Aqui está um exemplo que
você certamente encontrará de uma forma ou de outra:

$ ls /dsafsda
ls: não é possível acessar /dsafsda: nenhum arquivo ou diretório

Existem três componentes para esta mensagem:

•O nome do programa, ls. Alguns programas omitem essas informações de identificação, o que
pode ser irritante quando você está escrevendo shell scripts, mas não é grande coisa.

•O nome do arquivo, /dsafsda, que é uma informação mais específica.


Há um problema com este caminho.
• O erro Nenhum arquivo ou diretório indica o problema com o
nome do arquivo.

Juntando tudo, você obtém algo como “ls tentou abrir /dsafsda
mas não podia porque não existe.” Isso pode parecer óbvio, mas essas mensagens podem
ficar um pouco confusas quando você executa um script de shell que inclui um comando errado
com um nome diferente.
Ao solucionar erros, sempre resolva o primeiro erro primeiro. Algum
programas relatam que não podem fazer nada antes de relatar uma série de outros
problemas. Por exemplo, digamos que você execute um programa fictício chamado scumd
e você vê esta mensagem de erro:

scumd: não pode acessar /etc/scumd/config: Nenhum arquivo ou diretório

A seguir, há uma enorme lista de outras mensagens de erro que parecem uma catástrofe
completa. Não deixe que esses outros erros o distraiam. Você provavelmente só precisa criar /
etc/ scumd/ config.

NOTA Não confunda mensagens de erro com mensagens de aviso. Os avisos geralmente parecem erros, mas
contêm a palavra aviso. Um aviso geralmente significa que algo está errado, mas o programa
tentará continuar em execução de qualquer maneira. Para corrigir um problema observado em
uma mensagem de aviso, talvez seja necessário caçar um processo e eliminá-lo antes de fazer
qualquer outra coisa. (Você aprenderá sobre listar e eliminar processos na Seção 2.16.)

2.15.2 Erros Comuns

Muitos erros que você encontrará em programas Unix resultam de coisas que podem dar
errado com arquivos e processos. Muitos desses erros se originam diretamente das
condições que as chamadas de sistema do kernel encontram, então você pode aprender
algo sobre como o kernel envia problemas de volta aos processos observando-os.

30 Capítulo 2
Machine Translated by Google

Não existe tal arquivo ou diretório

Este é o erro número um. Você tentou acessar um arquivo que não existe.
Como o sistema de E/S de arquivo Unix não discrimina muito entre arquivos e diretórios, essa mensagem
de erro abrange os dois casos. Você o obtém quando tenta ler um arquivo que não existe, quando tenta
mudar para um diretório que não existe, quando tenta gravar em um arquivo em um diretório que não
existe e assim por diante . Este erro também é conhecido como ENOENT, abreviação de “Error NO
ENTity”.

NOTA Se você estiver interessado em chamadas de sistema, isso geralmente é o resultado de open() retornando
ENOENTE. Veja a página de manual do open(2) para mais informações sobre os erros que ele pode
encontro.

o arquivo existe

Nesse caso, você provavelmente tentou criar um arquivo que já existe. Isso é comum quando você
tenta criar um diretório com o mesmo nome de um arquivo.

Não é um diretório, é um diretório

Essas mensagens aparecem quando você tenta usar um arquivo como um diretório ou um diretório como um
arquivo. Por exemplo:

$ toque um
$ toque a/b
touch: a/b: Não é um diretório

Observe que a mensagem de erro se aplica apenas à parte a de a /b. Quando você encontrar
esse problema, talvez seja necessário pesquisar um pouco para encontrar o componente do caminho que
está sendo tratado como um diretório.

Não há mais espaço no dispositivo

Você está sem espaço em disco.

Permissão negada

Você recebe esse erro quando tenta ler ou gravar em um arquivo ou diretório que não tem permissão
para acessar (você não tem privilégios suficientes). Este erro também aparece quando você tenta
executar um arquivo que não possui o bit exe cute definido (mesmo que você consiga ler o arquivo).
Você lerá mais sobre permissões na Seção 2.17.

operação não permitida

Isso geralmente acontece quando você tenta matar um processo que não é seu.

Falha de segmentação, erro de barramento

Uma falha de segmentação significa essencialmente que a pessoa que escreveu o programa que você
acabou de executar errou em algum lugar. O programa tentou acessar

Comandos Básicos e Hierarquia de Diretórios 31


Machine Translated by Google

uma parte da memória que não tinha permissão para tocar, e o sistema operacional a matou. Da mesma forma,
um erro de barramento significa que o programa tentou acessar alguma memória de uma forma que não
deveria. Quando você recebe um desses erros, pode estar fornecendo a um programa alguma entrada que ele
não esperava. Em casos raros, pode ser hardware de memória com defeito.

2.16 Listagem e Manipulação de Processos

Lembre-se do Capítulo 1 que um processo é um programa em execução. Cada processo no sistema tem um ID
de processo numérico (PID). Para uma lista rápida de processos em execução, basta executar ps na linha de
comando. Você deve obter uma lista como esta:

$ ps
COMANDO DE TEMPO ESTATÍSTICO PID TTY

520 p0S 0:00 -bash


545 ? S 3:59 /usr/X11R6/bin/ctwm -W
548? S 0:10 xclock -geometria -0-0
2159 pd SW 0:00 /usr/bin/vi lib/addresses
31956 p3 R 0:00 ps

Os campos são os seguintes:

PID O ID do processo.

TTY O dispositivo terminal onde o processo está sendo executado. Mais sobre isso mais tarde.

STAT O status do processo, ou seja, o que o processo está fazendo e onde sua memória reside. Por
exemplo, S significa dormir e R significa correr. (Consulte a página de manual do ps(1) para obter uma
descrição de todos os símbolos.)

TIME A quantidade de tempo de CPU em minutos e segundos que o processo usou até agora. Em
outras palavras, a quantidade total de tempo que o processo gastou executando instruções no
processador. Lembre-se que, como os processos não são executados constantemente, isso é diferente
da hora desde que o processo foi iniciado (ou “hora do relógio”).

COMMAND Este pode parecer óbvio como o comando usado para executar o programa, mas esteja
ciente de que um processo pode alterar este campo de seu valor original. Além disso, o shell pode
executar a expansão glob, e esse campo refletirá o comando expandido em vez do que você inserir no
prompt.

NOTA Os PIDs são exclusivos para cada processo em execução em um sistema. No entanto, após o término de um processo
nates, o kernel pode eventualmente reutilizar o PID para um novo processo.

2.16.1 ps Opções de Comando


O comando ps tem muitas opções. Para tornar as coisas mais confusas, você pode especificar opções em
três estilos diferentes—Unix, BSD e GNU. Muitos

32 Capítulo 2
Machine Translated by Google

as pessoas acham o estilo BSD o mais confortável (talvez porque envolve menos digitação), então é
isso que usaremos neste livro. Aqui estão algumas das combinações de opções mais úteis:

ps x Mostra todos os seus processos em execução.

ps ax Mostra todos os processos no sistema, não apenas os que você possui.

ps u Incluir informações mais detalhadas sobre os processos.

ps w Mostra os nomes completos dos comandos, não apenas o que cabe em uma linha.

Assim como em outros programas, você pode combinar opções, como em ps aux e ps auxw.
Para verificar um processo específico, adicione seu PID à lista de argumentos do
comando ps . Por exemplo, para inspecionar o processo de shell atual, você pode usar ps u $$ ($$
é uma variável de shell que avalia o PID do shell atual).
Você encontrará informações sobre os comandos de administração top e lsof no Capítulo 8. Eles
podem ser úteis para localizar processos, mesmo quando você está fazendo algo diferente da
manutenção do sistema.

2.16.2 Rescisão do Processo


Para encerrar um processo, você envia um sinal – uma mensagem para um processo do kernel – com o
comando kill . Na maioria dos casos, tudo o que você precisa fazer é o seguinte:

$ matar pid

Existem muitos tipos de sinais. O padrão (usado acima) é TERM, ou terminar. Você pode enviar
sinais diferentes adicionando uma opção extra para matar. Por exemplo, para congelar um processo em
vez de finalizá-lo, use o sinal STOP :

$ kill -STOP pid

Um processo parado ainda está na memória, pronto para continuar de onde parou.
Use o sinal CONT para continuar executando o processo novamente:

$ kill -CONT pid

NOTA Usar CTRL-C para encerrar um processo que está sendo executado no terminal atual é o
o mesmo que usar kill para finalizar o processo com o sinal INT (interromper).

O kernel dá à maioria dos processos a chance de limpar depois de receber sinais (com o
mecanismo de tratamento de sinais ). No entanto, alguns processos podem escolher uma ação não
finalizadora em resposta a um sinal, ficar presos no ato de tentar manipulá-lo ou simplesmente ignorá-
lo, então você pode encontrar um processo ainda em execução depois de tentar finalizá-lo. Se isso
acontecer e você realmente precisar matar um processo, a maneira mais brutal de finalizá-lo é com o
sinal KILL . Ao contrário de outros sinais, KILL não pode ser ignorado; na verdade, o sistema operacional
nem dá chance ao processo. O kernel apenas encerra o processo e o remove forçosamente da memória.
Use este método apenas como último recurso.

Comandos Básicos e Hierarquia de Diretórios 33


Machine Translated by Google

Você não deve matar processos indiscriminadamente, especialmente se você não


sabem o que estão fazendo. Você pode estar dando um tiro no pé.
Você pode ver outros usuários digitando números em vez de nomes com kill—
por exemplo, kill -9 em vez de kill -KILL. Isso ocorre porque o kernel usa números para
denotar os diferentes sinais; você pode usar kill dessa forma se souber o número do
sinal que deseja enviar. Execute kill -l para obter um mapeamento de números de sinal
para nomes.

2.16.3 Controle de Trabalho

Shells suportam controle de tarefas, uma maneira de enviar sinais TSTP (semelhante a
STOP) e CONT para programas usando várias teclas e comandos. Isso permite suspender
e alternar entre os programas que você está usando. Por exemplo, você pode enviar um
sinal TSTP com CTRL-Z e, em seguida, iniciar o processo novamente digitando fg (trazer
para primeiro plano) ou bg (mover para segundo plano; consulte a próxima seção).
Mas, apesar de sua utilidade e dos hábitos de muitos usuários experientes, o controle de
tarefas não é necessário e pode ser confuso para iniciantes: é comum que os usuários
pressionem CTRL-Z em vez de CTRL-C, esqueçam o que estavam executando e,
eventualmente, acabem com inúmeros processos suspensos.

NOTA Para ver se você suspendeu acidentalmente algum processo em seu terminal atual, execute
o comando de trabalhos .

Se você deseja executar vários programas, execute cada um em uma janela de


terminal separada, coloque processos não interativos em segundo plano (como explicado
na próxima seção) e aprenda a usar os utilitários screen e tmux .

2.16.4 Processos em segundo plano

Normalmente, quando você executa um comando Unix a partir do shell, você não
obtém o prompt do shell até que o programa termine de ser executado. No entanto,
você pode desanexar um processo do shell e colocá-lo em “fundo” com o e comercial
(&); isso lhe dá o prompt de volta. Por exemplo, se você tem um arquivo grande que
precisa descompactar com gunzip (você verá isso na Seção 2.18) e deseja fazer outras
coisas enquanto ele está em execução, execute um comando como este:

$ gunzip arquivo.gz &

O shell deve responder imprimindo o PID do novo processo em segundo plano e o


prompt deve retornar imediatamente para que você possa continuar trabalhando. Se o
processo demorar muito, ele pode até continuar a ser executado depois que você sair,
o que é particularmente útil se você tiver que executar um programa que processa
muitos números. Se o processo terminar antes de você fazer logout ou fechar a janela
do terminal, o shell geralmente o notifica, dependendo da sua configuração.

34 Capítulo 2
Machine Translated by Google

OBSERVAÇÃO Se você estiver acessando remotamente uma máquina e quiser manter um programa em execução ao
efetuar logout, pode ser necessário usar o comando nohup ; veja sua página de manual para detalhes.

O lado escuro da execução de processos em segundo plano é que eles podem esperar
trabalhar com a entrada padrão (ou pior, ler diretamente do terminal).
Se um programa tentar ler algo da entrada padrão quando estiver em segundo plano, ele
poderá congelar (tente fg para trazê-lo de volta) ou encerrar. Além disso, se o programa
gravar na saída padrão ou no erro padrão, a saída pode aparecer na janela do terminal sem
levar em consideração qualquer outra coisa que esteja sendo executada lá, o que significa
que você pode obter uma saída inesperada quando estiver trabalhando em outra coisa.

A melhor maneira de garantir que um processo em segundo plano não o incomode é


redirecionar sua saída (e possivelmente entrada) conforme descrito na Seção 2.14.
Se a saída espúria dos processos em segundo plano atrapalhar, aprenda a redesenhar
o conteúdo da janela do seu terminal. O shell bash e a maioria dos programas interativos
de tela cheia suportam CTRL-L para redesenhar a tela inteira. Se um programa estiver lendo
a partir da entrada padrão, CTRL-R geralmente redesenha a linha atual, mas pressionar a
sequência errada na hora errada pode deixá-lo em uma situação ainda pior do que antes. Por
exemplo, digitar CTRL-R no prompt do bash coloca você no modo isearch reverso (pressione
ESC para sair).

2.17 Modos de arquivo e permissões


Cada arquivo Unix tem um conjunto de permissões que determinam se você pode ler,
escrever ou executar o arquivo. A execução de ls -l exibe as permissões. Aqui está um
exemplo de tal exibição:

-rw-r--r--1 1 juser somegroup 7041 26 de março 19:34 endnotes.html

O modo 1 do arquivo representa as permissões do arquivo e algumas informações extras


informação. Existem quatro partes para o modo, conforme ilustrado na Figura 2-1.

Permissões do usuário

Permissões de grupo
Modelo Outras permissões

-r-r--r--

Figura 2-1: As partes de um modo de arquivo

O primeiro caractere do modo é o tipo de arquivo. Um traço (-) nesta posição, como
no exemplo, denota um arquivo regular , significando que não há nada de especial no arquivo;
são apenas dados binários ou de texto. Este é de longe o tipo mais comum de arquivo. Os
diretórios também são comuns e são indicados por um d
no slot de tipo de arquivo. (A Seção 3.1 lista os tipos de arquivo restantes.)

Comandos Básicos e Hierarquia de Diretórios 35


Machine Translated by Google

O resto do modo de um arquivo contém as permissões, que se dividem


em três conjuntos: usuário, grupo e outros, nessa ordem. Por exemplo, os caracteres rw no exemplo
são as permissões do usuário, os caracteres r-- que seguem são as permissões do grupo e os caracteres
r-- finais são as outras permissões.

Cada conjunto de permissões pode conter quatro representações básicas:

• r significa que o arquivo é legível.

• w significa que o arquivo é gravável.

• x significa que o arquivo é executável (você pode executá-lo como um programa).

• - significa "nada" (mais especificamente, a permissão para esse slot no


conjunto não foi concedido).

As permissões de usuário (o primeiro conjunto) pertencem ao usuário que possui o arquivo. No


exemplo anterior, isso é juser. O segundo conjunto, permissões de grupo, são para o grupo do arquivo
(algum grupo no exemplo). Qualquer usuário desse grupo pode aproveitar essas permissões. (Use o
comando groups para ver em qual grupo você está e consulte a Seção 7.3.5 para obter mais
informações.)
Todos os outros no sistema têm acesso de acordo com o terceiro conjunto, o
outras permissões, que às vezes são chamadas de permissões mundiais .

OBSERVAÇÃO Cada slot de permissão de leitura, gravação e execução às vezes é chamado de permissão
bit porque a representação subjacente no sistema operacional é uma série de bits.
Portanto, você pode ouvir as pessoas se referirem a partes das permissões como “os bits de leitura”.

Alguns arquivos executáveis têm um s na lista de permissões do usuário em vez de um x. Isso


indica que o executável é setuid, o que significa que quando você executa o programa, ele é executado
como se o proprietário do arquivo fosse o usuário em vez de você. Muitos programas usam esse bit
setuid para executar como root para obter os privilégios necessários para alterar os arquivos do sistema.
Um exemplo é o programa passwd , que precisa alterar o arquivo /etc/ passwd .

2.17.1 Modificando Permissões


Para alterar as permissões em um arquivo ou diretório, use o comando chmod . Primeiro, escolha o
conjunto de permissões que você deseja alterar e, em seguida, escolha o bit a ser alterado. Por exemplo,
para adicionar permissões de leitura (r) de grupo (g) e mundo (o, para “outro”) ao arquivo, você pode
executar estes dois comandos:

$ chmod g+r arquivo


$ chmod o+r arquivo

Ou você pode fazer tudo de uma vez:

$ chmod go+r arquivo

36 Capítulo 2
Machine Translated by Google

Para remover essas permissões, use go-r em vez de go+r.

OBSERVAÇÃO Obviamente, você não deve tornar os arquivos graváveis, pois isso permite que qualquer
pessoa em seu sistema os altere. Mas isso também permitiria que qualquer pessoa conectada à
internet os alterasse? Provavelmente não, a menos que seu sistema tenha uma falha de segurança de rede.
Nesse caso, as permissões de arquivo não o ajudarão de qualquer maneira.

Às vezes, você pode ver pessoas alterando permissões com números, por exemplo:

arquivo $ chmod 644

Isso é chamado de alteração absoluta porque define todos os bits de permissão de uma só
vez. Para entender como isso funciona, você precisa saber como representar os bits de permissão
em forma octal (cada numeral representa um número na base 8, 0 a 7 e corresponde a um conjunto
de permissões). Veja a página de manual do chmod(1) ou o manual de informações para mais
informações.
Você realmente não precisa saber como construir modos absolutos se você
preferem usá-los; apenas memorize os modos que você usa com mais frequência.
A Tabela 2-4 lista os mais comuns.

Tabela 2-4: Modos de permissão absoluta

Modo Significado Usado para

644 usuário: leitura/gravação; grupo, outro: ler arquivos

600 usuário: ler/escrever; grupo, outro: nenhum arquivos

755 usuário: ler/escrever/executar; grupo, diretórios, programas


outro: ler/executar

700 usuário: ler/escrever/executar; grupo, outro: diretórios, programas


Nenhum

711 usuário: ler/escrever/executar; grupo, outro: diretórios


executar

Os diretórios também têm permissões. Você pode listar o conteúdo de um diretório se for legível,
mas só poderá acessar um arquivo em um diretório se o diretório for executável. Você precisa de
ambos na maioria dos casos; um erro comum que as pessoas cometem ao definir as permissões de
diretórios é remover acidentalmente a permissão de execução ao usar modos absolutos.

Por fim, você pode especificar um conjunto de permissões padrão com o comando shell
umask , que aplica um conjunto predefinido de permissões a qualquer novo arquivo que você criar.
Em geral, use umask 022 se quiser que todos possam ver todos os arquivos e diretórios que você
criar e use umask 077 se não quiser. Se você quiser aplicar a máscara de permissões desejada a
novas janelas e sessões posteriores, você precisa colocar o comando umask com o modo desejado
em um de seus arquivos de inicialização, conforme discutido no Capítulo 13.

Comandos Básicos e Hierarquia de Diretórios 37


Machine Translated by Google

2.17.2 Trabalhando com Links Simbólicos


Um link simbólico é um arquivo que aponta para outro arquivo ou diretório, criando efetivamente
um alias (como um atalho no Windows). Links simbólicos oferecem acesso rápido a caminhos de
diretórios obscuros.
Em uma longa listagem de diretórios, os links simbólicos se parecem com isso (observe o l
como o tipo de arquivo no modo de arquivo):

lrwxrwxrwx 1 ruser users 11 27 fev 13:52 somedir -> /home/origdir

Se você tentar acessar algum diretório neste diretório, o sistema lhe dará /home/
origdir em vez disso. Links simbólicos são simplesmente nomes de arquivos que apontam para
outros nomes. Seus nomes e os caminhos para os quais apontam não precisam significar nada. No
exemplo anterior, /home/ origdir não precisa existir.
De fato, se /home/ origdir não existir, qualquer programa que acesse algumdir
retorna um erro informando que somedir não existe (exceto para ls somedir, um comando que
informa estupidamente que somedir é somedir). Isso pode ser desconcertante porque você pode ver
algo chamado somedir bem na frente de seus olhos.

Essa não é a única maneira pela qual os links simbólicos podem ser confusos. Outro problema
é que você não pode identificar as características de um destino de link apenas observando o nome
do link; você deve seguir o link para ver se ele vai para um arquivo ou diretório. Seu sistema também
pode ter links que apontam para outros links, que são chamados de links simbólicos encadeados e
podem ser um incômodo quando você está tentando localizá-los.

Para criar um link simbólico do destino para o nome do link, use ln -s da seguinte forma:

$ ln -s nome do link de destino

O argumento linkname é o nome do link simbólico, o destino


argumento é o caminho do arquivo ou diretório para o qual o link aponta , e o sinalizador -s
especifica um link simbólico (consulte o aviso a seguir).
Ao fazer um link simbólico, verifique o comando duas vezes antes de executá-lo, pois várias
coisas podem dar errado. Por exemplo, se você acidentalmente inverter a ordem dos argumentos
(ln -s linkname target), você se divertirá se linkname for um diretório que já existe. Se este for o
caso (e geralmente é), ln cria um link chamado target dentro de linkname, e o link apontará para si
mesmo, a menos que linkname seja um caminho completo. Se algo der errado ao criar um link
simbólico para um diretório, verifique se há links simbólicos errados nesse diretório e remova-os.

Links simbólicos também podem causar dores de cabeça quando você não sabe que eles
existem. Por exemplo, você pode editar facilmente o que pensa ser uma cópia de um arquivo, mas na
verdade é um link simbólico para o original.

AVISO Não se esqueça da opção -s ao criar um link simbólico. Sem ele, ln cria um link físico, dando um nome de arquivo
real adicional a um único arquivo. O novo nome de arquivo tem o status do antigo; ele aponta (links)
diretamente para os dados do arquivo em vez de para outro nome de arquivo, como faz um link
simbólico. Links físicos podem ser ainda mais confusos do que links simbólicos. A menos que você
entenda o material da Seção 4.6, evite usá-lo.

38 Capítulo 2
Machine Translated by Google

Com todos esses avisos sobre links simbólicos, você pode estar se perguntando por que
alguém iria querer usá-los. Como se vê, suas armadilhas são significativamente superadas pelo
poder que fornecem para organizar arquivos e sua capacidade de corrigir facilmente pequenos
problemas. Um caso de uso comum é quando um programa espera encontrar um arquivo ou
diretório específico que já existe em algum outro lugar do sistema. Você não deseja fazer uma cópia
e, se não puder alterar o programa, basta criar um link simbólico dele para o local real do arquivo
ou diretório.

2.18 Arquivando e compactando arquivos


Agora que você aprendeu sobre arquivos, permissões e possíveis erros, você precisa dominar
gzip e tar, dois utilitários comuns para compactar e agrupar arquivos e diretórios.

2.18.1 gzip
O programa gzip (GNU Zip) é um dos atuais programas de compressão padrão do Unix. Um arquivo
que termina com .gz é um arquivo GNU Zip. Use o arquivo gunzip.gz
para descompactar <arquivo>.gz e remover o sufixo; para compactar o arquivo novamente, use o
arquivo gzip .

2.18.2 leva
Ao contrário dos programas ZIP para outros sistemas operacionais, o gzip não cria arquivos de
arquivos; ou seja, ele não compacta vários arquivos e diretórios em um único arquivo. Para criar
um arquivo, use tar em vez disso:

$ tar arquivo cvf.tar arquivo1 arquivo2 ...

Arquivos criados pelo tar geralmente têm um sufixo .tar (isso é por convenção; não é
obrigatório). Por exemplo, no comando anterior, file1, file2 e assim por diante são os nomes dos
arquivos e diretórios que você deseja arquivar em <archive>.tar. O sinalizador c ativa o modo de
criação. Os sinalizadores v e f têm funções mais específicas.

O sinalizador v ativa a saída de diagnóstico detalhada, fazendo com que o tar imprima os
nomes dos arquivos e diretórios no archive quando os encontrar.
Adicionar outro v faz com que o tar imprima detalhes como tamanho do arquivo e permissões.
Se você não quiser que o tar diga o que está fazendo, omita o sinalizador v .
O sinalizador f denota a opção de arquivo. O próximo argumento na linha de comando após o
sinalizador f deve ser o arquivo morto a ser criado pelo tar (no exemplo anterior, é <archive>.tar).
Você deve usar esta opção sempre seguida de um nome de arquivo, exceto com unidades de fita.
Para usar a entrada ou saída padrão, defina o nome do arquivo com um traço (-).

Comandos Básicos e Hierarquia de Diretórios 39


Machine Translated by Google

Descompactando arquivos .tar

Para descompactar um arquivo .tar com tar use o sinalizador x :

$ tar xvf archive.tar

Neste comando, o sinalizador x coloca o tar no modo de extração (descompactação) . Você pode
extraia partes individuais do arquivo digitando os nomes das partes no final da linha de comando,
mas você deve saber seus nomes exatos. (Para saber com certeza, veja o modo de índice descrito a
seguir.)

OBSERVAÇÃO Ao usar o modo de extração, lembre-se de que o tar não remove o arquivo .tar arquivado após
extrair seu conteúdo.

Usando o modo de índice

Antes de descompactar, geralmente é uma boa ideia verificar o conteúdo de um arquivo .tar
arquivo com o modo de índice usando o sinalizador t em vez do sinalizador x .
Este modo verifica a integridade básica do arquivo e imprime os nomes de todos os arquivos dentro
dele. Se você não testar um arquivo antes de descompactá-lo, pode acabar despejando uma grande
quantidade de arquivos no diretório atual, o que pode ser muito difícil de limpar.

Ao verificar um arquivo com o modo t , verifique se tudo está em uma estrutura de diretório
racional; ou seja, todos os nomes de caminho de arquivo no arquivo devem começar com o mesmo
diretório. Se não tiver certeza, crie um diretório temporário, altere para ele e extraia. (Você sempre
* ..
pode usar mv se o arquivo não criou uma bagunça.)

Ao descompactar, considere usar a opção p para preservar as permissões.


Use isso no modo de extração para substituir seu umask e obter as permissões exatas especificadas
no arquivo. A opção p é o padrão quando você está trabalhando como superusuário. Se você
estiver tendo problemas com permissões e propriedade ao descompactar um arquivo como
superusuário, certifique-se de esperar até que o comando termine e você receba o prompt do shell
de volta. Embora você queira extrair apenas uma pequena parte de um arquivo, tar

deve percorrer a coisa toda, e você não deve interromper o processo porque ele define as permissões
somente após verificar todo o arquivo.
Confirme todas as opções e modos do tar nesta seção na memória. Se você estiver tendo
problemas, faça alguns cartões de memória flash. Isso pode soar como escola primária, mas é muito
importante evitar erros por descuido com este comando.

2.18.3 Arquivos compactados (.tar.gz)


Muitos iniciantes acham confuso que os arquivos sejam normalmente encontrados compactados,
com nomes de arquivos terminando em .tar.gz. Para descompactar um arquivo compactado, trabalhe
do lado direito para o esquerdo; livre-se do .gz primeiro e depois se preocupe com o .tar. Por exemplo,
esses dois comandos descompactam e descompactam <file>.tar.gz:

$ gunzip arquivo.tar.gz
$ tar arquivo xvf.tar

40 Capítulo 2
Machine Translated by Google

Ao começar, não há problema em fazer isso um passo de cada vez, primeiro


executando gunzip para descompactar e depois tar para verificar e descompactar. Para
criar um arquivo compactado, faça o inverso: execute primeiro o tar e depois o gzip . Faça
isso com bastante frequência e logo você memorizará como funciona o processo de
arquivamento e compactação. Mas mesmo que você não faça isso com tanta frequência,
você pode ver o quão cansativo toda a digitação pode se tornar e você começará a procurar
atalhos. Vamos dar uma olhada nesses agora.

2.18.4 zcat

O método mostrado não é a maneira mais rápida ou eficiente de invocar o tar


em um arquivo compactado e desperdiça espaço em disco e tempo de E/S do kernel. Uma
maneira melhor é combinar as funções de arquivamento e compactação com uma
tubulação. Por exemplo, este pipeline de comando descompacta <file>.tar.gz:

$ zcat arquivo.tar.gz | tar xvf -

O comando zcat é o mesmo que gunzip -dc. A opção -d decom pressiona e a


opção -c envia o resultado para a saída padrão (neste caso, para o comando tar ).

Porque é tão comum usar o zcat, a versão do tar que vem com
Linux tem um atalho. Você pode usar z como uma opção para invocar automaticamente
o gzip no arquivo; isso funciona tanto para extrair um arquivo (com os modos x ou t no tar)
quanto para criar um (com c). Por exemplo, use o seguinte para verificar um arquivo
compactado:

$ tar ztvf arquivo.tar.gz

No entanto, tente lembrar que você está realmente realizando duas etapas
ao pegar o atalho.

NOTA Um arquivo .tgz é o mesmo que um arquivo .tar.gz . O sufixo destina-se a caber em sistemas de arquivos FAT
(baseados em MS-DOS).

2.18.5 Outros Utilitários de Compressão


Mais dois programas de compactação são xz e bzip2, cujos arquivos compactados terminam
com .xz e .bz2, respectivamente. Embora um pouco mais lento que o gzip, esses arquivos
de texto geralmente compactam um pouco mais. Os programas de descompactação a serem
usados são unxz e bunzip2 , e as opções de ambos estão próximas o suficiente de seu gzip
contrapartes que você não precisa aprender nada de novo.
A maioria das distribuições Linux vem com programas zip e unzip que são compatíveis
com os arquivos ZIP em sistemas Windows. Eles funcionam nos arquivos .zip usuais , bem
como em arquivos de extração automática que terminam em .exe. Mas se você encontrar um
arquivo que termina em .Z, você encontrou uma relíquia criada pelo programa de compressão ,
que já foi o padrão Unix. O programa gunzip pode descompactar esses arquivos, mas o gzip
não os cria.

Comandos Básicos e Hierarquia de Diretórios 41


Machine Translated by Google

2.19 Fundamentos da hierarquia de diretórios do Linux


Agora que você sabe como examinar arquivos, alterar diretórios e ler páginas de manual, está
pronto para começar a explorar seus arquivos e diretórios do sistema.
Os detalhes da estrutura de diretórios do Linux são descritos no Filesystem Hierarchy Standard,
ou FHS (https:// refspecs.linuxfoundation.org/ fhs.shtml), mas um breve passo a passo deve ser
suficiente por enquanto.
A Figura 2-2 oferece uma visão geral simplificada da hierarquia, mostrando alguns dos
diretórios em /, /usr e /var. Observe que a estrutura de diretório em /usr contém alguns dos mesmos
nomes de diretório que /.

bin/dev/ etc/ usr/ home/ lib/ sbin/tmp/var/

bin/man/lib/ local/ sbin/ compartilhar/ log/tmp/

Figura 2-2: Hierarquia de diretórios do Linux

Aqui estão os subdiretórios mais importantes na raiz:

/bin Contém programas prontos para execução (também conhecidos como executáveis),
incluindo a maioria dos comandos básicos do Unix, como ls e cp. A maioria dos programas
em /bin estão em formato binário, tendo sido criados por um compilador C, mas alguns são
scripts de shell em sistemas modernos.

/dev Contém arquivos de dispositivo. Você aprenderá mais sobre isso no Capítulo 3.

/etc Este diretório principal de configuração do sistema (pronuncia -se EHT-see) contém a
senha do usuário, inicialização, dispositivo, rede e outros arquivos de configuração.

/home Mantém os diretórios pessoais (pessoais) para usuários regulares. A maioria das
instalações Unix estão em conformidade com este padrão.

/lib Uma abreviação de library, este diretório contém arquivos de biblioteca contendo código
que os executáveis podem usar. Existem dois tipos de bibliotecas: estáticas e compartilhadas.
O diretório /lib deve conter apenas bibliotecas compartilhadas, mas outros diretórios lib, como /
usr/ lib, contêm ambas as variedades, bem como outros arquivos auxiliares. (Discutiremos
bibliotecas compartilhadas com mais detalhes no Capítulo 15.)

/proc Fornece estatísticas do sistema por meio de uma interface de diretório e arquivo
navegável. Grande parte da estrutura de subdiretórios /proc no Linux é única, mas muitas
outras variantes do Unix têm recursos semelhantes. O diretório /proc contém informações
sobre os processos em execução no momento, bem como alguns parâmetros do kernel.

42 Capítulo 2
Machine Translated by Google

/run Contém dados de tempo de execução específicos do sistema, incluindo determinados IDs de
processo, arquivos de soquete, registros de status e, em muitos casos, log do sistema. Esta é uma
adição relativamente recente ao diretório raiz; em sistemas mais antigos, você pode encontrá-lo em /
var/ run. Em sistemas mais novos, /var/ run é um link simbólico para /run.

/sys Este diretório é semelhante ao /proc , pois fornece uma interface de dispositivo e sistema.
Você lerá mais sobre /sys no Capítulo 3.

/sbin O local para executáveis do sistema. Os programas nos diretórios /sbin estão relacionados ao
gerenciamento do sistema, portanto, usuários comuns geralmente não têm /sbin
componentes em seus caminhos de comando. Muitos dos utilitários encontrados aqui não funcionam
se não forem executados como root.

/tmp Uma área de armazenamento para arquivos menores e temporários com os quais você não
se importa muito. Qualquer usuário pode ler e escrever de /tmp, mas o usuário pode não ter
permissão para acessar os arquivos de outro usuário lá. Muitos programas usam esse diretório
como um espaço de trabalho. Se algo for extremamente importante, não coloque em /tmp porque a
maioria das distribuições limpa /tmp
quando a máquina inicializa e alguns até removem seus arquivos antigos periodicamente. Além
disso, não deixe /tmp encher de lixo porque seu espaço geralmente é compartilhado com algo crítico (o
resto de /, por exemplo).

/usr Embora seja pronunciado “user”, este subdiretório não possui arquivos de usuário.
Em vez disso, ele contém uma grande hierarquia de diretórios, incluindo a maior parte do sistema
Linux. Muitos dos nomes de diretório em /usr são os mesmos do diretório raiz (como /usr/ bin e /usr/
lib), e contêm o mesmo tipo de arquivo. (A razão pela qual o diretório raiz não contém o sistema
completo é principalmente histórica - no passado, era para manter os requisitos de espaço baixos para
a raiz.)

/var O subdiretório variável, onde os programas gravam informações que podem mudar ao longo do
tempo. Registro do sistema, rastreamento de usuários, caches e outros arquivos que os programas
do sistema criam e gerenciam estão aqui. (Você notará um diretório / var/ tmp aqui, mas o sistema não
o limpa na inicialização.)

2.19.1 Outros subdiretórios raiz


Existem alguns outros subdiretórios interessantes no diretório raiz:

/boot Contém arquivos do carregador de inicialização do kernel. Esses arquivos pertencem


apenas ao primeiro estágio do procedimento de inicialização do Linux, portanto, você não
encontrará informações sobre como o Linux inicia seus serviços neste diretório.
Consulte o Capítulo 5 para saber mais sobre isso.

/media Um ponto de anexo básico para mídia removível, como unidades flash, encontrado em
muitas distribuições.

/opt Pode conter software adicional de terceiros. Muitos sistemas não usam /opt.

Comandos Básicos e Hierarquia de Diretórios 43


Machine Translated by Google

2.19.2 O diretório /usr


O diretório / usr pode parecer relativamente limpo à primeira vista, mas uma rápida olhada em /usr/
bin e /usr/ lib revela que há muito aqui; /usr é onde reside a maioria dos programas e dados do espaço
do usuário. Além de /usr/ bin, / usr/ sbin e /usr/ lib, / usr contém o seguinte:

/include Contém arquivos de cabeçalho usados pelo compilador C.


/local É onde os administradores podem instalar seu próprio software. Sua estrutura deve se
parecer com a de / e /usr.

/man Contém páginas de manual.


/share Contém arquivos que devem funcionar em outros tipos de máquinas Unix sem perda de
funcionalidade. Geralmente são arquivos de dados auxiliares que programas e bibliotecas lêem
conforme necessário. No passado, as redes de máquinas compartilhavam esse diretório de um
servidor de arquivos, mas hoje um compartilhamento
O diretório usado dessa maneira é raro porque não há restrições de espaço realistas para esses
tipos de arquivos em sistemas contemporâneos. Em vez disso, em distribuições Linux, você
encontrará /man, / info e muitos outros subdiretórios aqui porque é uma convenção de fácil
compreensão.

2.19.3 Localização do Kernel

Em sistemas Linux, o kernel normalmente é um arquivo binário /vmlinuz ou /boot/


vmlinuz. Um carregador de inicialização carrega esse arquivo na memória e o coloca em movimento
quando o sistema inicializa. (Você encontrará detalhes sobre o carregador de inicialização no Capítulo 5.)
Uma vez que o carregador de inicialização inicia o kernel, o arquivo principal do kernel não é mais
usado pelo sistema em execução. No entanto, você encontrará muitos módulos que o kernel
carrega e descarrega sob demanda durante a operação normal do sistema. Chamados de módulos
de kernel carregáveis, eles estão localizados em /lib/ modules.

2.20 Executando Comandos como Superusuário


Antes de prosseguir, você deve aprender a executar comandos como superusuário. Você pode
ficar tentado a iniciar um shell de root, mas isso tem muitas desvantagens:

•Você não tem registro de comandos que alteram o sistema.

• Você não tem registro dos usuários que realizaram alterações no sistema
comandos.

•Você não tem acesso ao seu ambiente shell normal.

•Você tem que digitar a senha de root (se você tiver uma).

44 Capítulo 2
Machine Translated by Google

2.20.1 sudo
A maioria das distribuições usa um pacote chamado sudo para permitir que os administradores
executem comandos como root quando estiverem logados como eles mesmos. Por exemplo, no
Capítulo 7, você aprenderá a usar o vipw para editar o arquivo /etc/ passwd . Você poderia fazer assim:

$ sul vipw

Ao executar este comando, o sudo registra essa ação com o serviço syslog no recurso local2.
Você também aprenderá mais sobre logs do sistema no Capítulo 7.

2.20.2 /etc/sudoers
É claro que o sistema não permite que qualquer usuário execute comandos como superusuário;
você deve configurar os usuários privilegiados em seu arquivo /etc/ sudoers . O pacote sudo tem
muitas opções (que você provavelmente nunca usará), o que torna a sintaxe em /etc/ sudoers um
tanto complicada. Por exemplo, este arquivo dá ao usuário1 e ao usuário2 o poder de executar
qualquer comando como root sem ter que digitar uma senha:

User_Alias ADMINS = usuário1, usuário2

ADMINISTRADORES TODOS = NOPASSWD: TODOS

raiz TODOS=(TODOS) TODOS

A primeira linha define um alias de usuário ADMINS com os dois usuários e a segunda linha
concede os privilégios. A parte ALL = NOPASSWD: ALL significa que os usuários no alias ADMINS
podem usar sudo para executar comandos como root. O segundo ALL significa “qualquer comando”.

O primeiro ALL significa “qualquer host”. (Se você tiver mais de uma máquina, poderá definir diferentes
tipos de acesso para cada máquina ou grupo de máquinas, mas não abordaremos esse recurso.)

A raiz ALL=(ALL) ALL significa simplesmente que o superusuário também pode usar
sudo para executar qualquer comando em qualquer host. O extra (ALL) significa que o
superusuário também pode executar comandos como qualquer outro usuário. Você pode estender
esse privilégio aos usuários ADMINS adicionando (ALL) à segunda linha /etc/ sudoers , conforme
mostrado aqui:

ADMINISTRADORES TODOS = (TODOS) NOPASSWD: TODOS

OBSERVAÇÃO Use o comando visudo para editar / etc/sudoers. Este comando verifica erros de sintaxe de arquivo
depois que você salva o arquivo.

Comandos Básicos e Hierarquia de Diretórios 45


Machine Translated by Google

2.20.3 sudo Logs


Embora entraremos em logs com mais detalhes posteriormente neste livro, você pode
encontrar os logs sudo na maioria dos sistemas com este comando:

$ journalctl SYSLOG_IDENTIFIER=sudo

Em sistemas mais antigos, você precisará procurar um arquivo de log em /var/ log,
como /var/ log/ auth.log.
É isso para o sudo por enquanto. Se você precisar usar seus recursos mais avançados,
veja as páginas de manual do sudoers(5) e sudo(8). (A mecânica real da troca de usuários
é abordada no Capítulo 7.)

2.21 Olhando para o futuro


Agora você deve saber como fazer o seguinte na linha de comando: executar programas,
redirecionar a saída, interagir com arquivos e diretórios, visualizar listas de processos,
visualizar páginas de manual e, geralmente, percorrer o espaço do usuário de um sistema
Linux. Você também deve ser capaz de executar comandos como superusuário. Você pode
ainda não saber muito sobre os detalhes internos dos componentes do espaço do usuário ou
o que acontece no kernel, mas com o básico de arquivos e processos em seu currículo, você
está no caminho certo. Nos próximos capítulos, você trabalhará com componentes de sistema
do kernel e do espaço do usuário usando as ferramentas de linha de comando que acabou de
aprender.

46 Capítulo 2
Machine Translated by Google

3
DISPOSITIVOS

Este capítulo é um tour básico da


infraestrutura de dispositivos fornecida pelo
kernel em um sistema Linux em funcionamento.
Ao longo da história do Linux, houve muitas
mudanças na forma como o kernel apresenta os
dispositivos ao usuário. Começaremos examinando o sistema
tradicional de arquivos de dispositivos para ver como o kernel
fornece informações de configuração de dispositivos por
meio do sysfs. Nosso objetivo é poder extrair informações sobre os dispo
em um sistema para entender algumas operações rudimentares.
Os capítulos posteriores abordarão a interação com tipos
específicos de dispositivos com mais detalhes.
Machine Translated by Google

É importante entender como o kernel interage com o espaço do usuário quando apresentado
a novos dispositivos. O sistema udev permite que programas de espaço do usuário configurem e
usem automaticamente novos dispositivos. Você verá o funcionamento básico de como o kernel
envia uma mensagem para um processo do espaço do usuário por meio do udev, bem como o que
o processo faz com ele.

3.1 Arquivos do dispositivo

É fácil manipular a maioria dos dispositivos em um sistema Unix porque o kernel apresenta
muitas das interfaces de E/S do dispositivo para os processos do usuário como arquivos. Esses
arquivos de dispositivo às vezes são chamados de nós de dispositivo. Além de programadores que
usam operações regulares de arquivos para trabalhar com dispositivos, alguns dispositivos também
são acessíveis a programas padrão como cat, então você não precisa ser um programador para usar
um dispositivo. No entanto, há um limite para o que você pode fazer com uma interface de arquivo,
portanto, nem todos os dispositivos ou recursos de dispositivo são acessíveis com E/S de arquivo padrão.
O Linux usa o mesmo design para arquivos de dispositivo que outros tipos de Unix.
Os arquivos de dispositivo estão no diretório /dev e a execução de ls /dev revela alguns arquivos em /
dev. Então, como você trabalha com dispositivos?
Para começar, considere este comando:

$ echo blá blá > /dev/null

Como qualquer outro comando com saída redirecionada, isso envia algumas coisas da saída
padrão para um arquivo. No entanto, o arquivo é /dev/ null, um dispositivo, então o kernel ignora
suas operações usuais de arquivo e usa um driver de dispositivo nos dados gravados nesse
dispositivo. No caso de /dev/ null, o kernel simplesmente aceita os dados de entrada e os joga fora.

Para identificar um dispositivo e visualizar suas permissões, use ls -l. aqui estão alguns
exemplos:

$ ls -l
brw-rw---- 1 disco raiz 8, 1 set 6 08:37 sda1
crw-rw-rw- 1 root root 1, 3 set 6 08:37 null
prw-r--r-- 1 raiz raiz 0 de março 19:17 confiável
srw-rw-rw- 1 raiz raiz 0 dez 18 07:43 log

Observe o primeiro caractere de cada linha (o primeiro caractere do modo do arquivo).


Se este caractere for b, c, p ou s, o arquivo é um dispositivo. Essas letras significam bloco, caractere,
barra vertical e soquete, respectivamente:

Bloquear dispositivo

Os programas acessam dados de um dispositivo de bloco em blocos fixos. O sda1 no exemplo


anterior é um dispositivo de disco, um tipo de dispositivo de bloco. Os discos podem ser
facilmente divididos em blocos de dados. Como o tamanho total de um dispositivo de bloco é
fixo e fácil de indexar, os processos têm acesso aleatório rápido a qualquer bloco no dispositivo
com a ajuda do kernel.

48 Capítulo 3
Machine Translated by Google

Dispositivo de personagem

Dispositivos de caracteres funcionam com fluxos de dados. Você só pode ler ou escrever
caracteres em dispositivos de caracteres, conforme demonstrado anteriormente com /dev/ null.
Os dispositivos de caracteres não têm tamanho; quando você lê ou grava em um, o kernel
geralmente executa uma operação de leitura ou gravação nele.
As impressoras diretamente conectadas ao seu computador são representadas por dispositivos
de caracteres. É importante observar que durante a interação com o dispositivo de caractere, o
kernel não pode fazer backup e reexaminar o fluxo de dados após ele ter passado os dados
para um dispositivo ou processo.

Dispositivo de tubulação

Os pipes nomeados são como dispositivos de caractere, com outro processo na outra extremidade
do fluxo de E/S em vez de um driver de kernel.

Dispositivo de soquete

Sockets são interfaces de propósito especial que são frequentemente usadas para
comunicação entre processos. Eles são frequentemente encontrados fora do /dev
diretório. Arquivos de soquete representam soquetes de domínio Unix; você aprenderá mais
sobre eles no Capítulo 10.

Nas listagens de arquivos de ls -l de dispositivos de bloco e caractere, os números


antes das datas são os números de dispositivos principais e secundários que o kernel usa para
identificar o dispositivo. Dispositivos semelhantes geralmente têm o mesmo número principal,
como sda3 e sdb1 (ambos são partições de disco rígido).

NOTA Nem todos os dispositivos possuem arquivos de dispositivo, porque as interfaces de E/ S do dispositivo de
bloco e caractere não são apropriadas em todos os casos. Por exemplo, as interfaces de rede não
possuem arquivos de dispositivo. É teoricamente possível interagir com uma interface de rede usando
um dispositivo de caractere único, mas como seria difícil, o kernel oferece outras interfaces de E/ S.

3.2 O caminho do dispositivo sysfs


O diretório /dev tradicional do Unix é uma maneira conveniente para os processos do usuário
referenciarem e interagirem com dispositivos suportados pelo kernel, mas também é um esquema
muito simplista. O nome do dispositivo em /dev informa um pouco sobre o dispositivo, mas geralmente
não o suficiente para ser útil. Outro problema é que o kernel atribui os dispositivos na ordem em que
são encontrados, portanto, um dispositivo pode ter um nome diferente entre as reinicializações.

Para fornecer uma visão uniforme para dispositivos conectados com base em seus
atributos de hardware reais, o kernel do Linux oferece a interface sysfs por meio de um sistema de
arquivos e diretórios. O caminho base para dispositivos é /sys/ devices. Por exemplo, o disco rígido
SATA em /dev/ sda pode ter o seguinte caminho em sysfs:

/sys/devices/pci0000:00/0000:00:17.0/ata3/host0/target0:0:0/0:0:0:0/block/sda

Dispositivos 49
Machine Translated by Google

Como você pode ver, este caminho é bastante longo comparado com o nome do
arquivo /dev/ sda , que também é um diretório. Mas você não pode realmente comparar os
dois caminhos porque eles têm propósitos diferentes. O arquivo /dev permite que os processos
do usuário usem o dispositivo, enquanto o caminho /sys/ devices é usado para visualizar
informações e gerenciar o dispositivo. Se você listar o conteúdo de um caminho de dispositivo
como o anterior, verá algo como o seguinte:

Alinhamento_deslocamento descarte_alinhamento suportes tamanho removível evento


bdi inflight ro slaves eventos
dispositivo de sda2 sda5 sda1
events_async power events_poll_msecs fila Estado
desenvolvimento de
ext_range range subsistema
capacidade vestígio

Os arquivos e subdiretórios aqui devem ser lidos principalmente por programas e


não por humanos, mas você pode ter uma ideia do que eles contêm e representam olhando
para um exemplo como o arquivo /dev . A execução de cat dev neste diretório exibe os
números 8:0, que são os números de dispositivo principal e secundário de /dev/ sda.

Existem alguns atalhos no diretório / sys . Por exemplo, /sys/ block


deve conter todos os dispositivos de bloco disponíveis em um sistema. No entanto, esses
são apenas links simbólicos; você executaria ls -l /sys/block para revelar os verdadeiros
caminhos sysfs.
Pode ser difícil encontrar a localização sysfs de um dispositivo em /dev. Use o comando
udevadm da seguinte forma para mostrar o caminho e vários outros atributos interessantes:

$ udevadm info --query=all --name=/dev/sda

Você encontrará mais detalhes sobre o udevadm e todo o sistema udev na Seção
3.5.

3.3 dd e Dispositivos
O programa dd é extremamente útil quando se trabalha com dispositivos de blocos e
caracteres. Sua única função é ler de um arquivo ou fluxo de entrada e gravar em um arquivo
ou fluxo de saída, possivelmente fazendo alguma conversão de codificação no caminho. Um
recurso dd particularmente útil em relação aos dispositivos de bloco é que você pode processar
um pedaço de dados no meio de um arquivo, ignorando o que vem antes ou depois.

AVISO dd é muito poderoso, portanto, certifique-se de saber o que está fazendo ao executá-lo. É muito fácil
corromper arquivos e dados em dispositivos cometendo um erro descuidado. Geralmente, é
útil gravar a saída em um novo arquivo se você não tiver certeza do que ele fará.

dd copia dados em blocos de tamanho fixo. Veja como usar dd com um dispositivo de
caractere, utilizando algumas opções comuns:

$ dd if=/dev/zero of=new_file bs=1024 contagem=1

50 Capítulo 3
Machine Translated by Google

Como você pode ver, o formato de opção dd difere dos formatos de opção da maioria dos
outros comandos Unix; é baseado em um antigo estilo IBM Job Control Language (JCL). Em vez
de usar o caractere traço (-) para sinalizar uma opção, você nomeia uma opção e define seu
valor com o sinal de igual (=) . O exemplo anterior copia um único bloco de 1.024 bytes de /dev/
zero (um fluxo contínuo de zero bytes) para new_file.

Estas são as opções dd importantes:

if=file O arquivo de entrada. O padrão é a entrada padrão.


of=file O arquivo de saída. O padrão é a saída padrão.
bs=size O tamanho do bloco. dd lê e grava tantos bytes de dados por vez. Para
abreviar grandes blocos de dados, você pode usar b e k para significar 512 e
1.024 bytes, respectivamente. Portanto, o exemplo anterior poderia ler bs=1k em
vez de bs=1024.
ibs=size, obs=size Os tamanhos dos blocos de entrada e saída. Se você puder
usar o mesmo tamanho de bloco para entrada e saída, use a opção bs ; se não,
use ibs e obs para entrada e saída, respectivamente.
count=num O número total de blocos a serem copiados. Ao trabalhar com um arquivo
enorme - ou com um dispositivo que fornece um fluxo infinito de dados, como /dev/ zero -
você deseja que o dd pare em um ponto fixo; caso contrário, você pode desperdiçar muito
espaço em disco, tempo de CPU ou ambos. Use a contagem com o pulo
parâmetro para copiar um pequeno pedaço de um grande arquivo ou dispositivo.

skip=num Pule os primeiros blocos num no arquivo de entrada ou fluxo e não os copie
para a saída.

3.4 Resumo do nome do dispositivo


Às vezes, pode ser difícil encontrar o nome de um dispositivo (por exemplo, ao particionar
um disco). Aqui estão algumas maneiras de descobrir o que é:

•Consulte o udevd usando o udevadm (consulte a Seção 3.5).


•Procure o dispositivo no diretório / sys .
•Adivinhe o nome a partir da saída do comando journalctl -k (que imprime as mensagens do
kernel) ou do log do sistema do kernel (consulte a Seção 7.1).
Essa saída pode conter uma descrição dos dispositivos em seu sistema.
•Para um dispositivo de disco que já está visível para o sistema, você pode verificar a saída do
comando mount .
• Execute cat /proc/devices para ver os dispositivos de bloco e caractere para os quais seu
sistema possui drivers atualmente. Cada linha consiste em um número e um nome. O
número é o número principal do dispositivo conforme descrito na Seção 3.1. Se você
conseguir adivinhar o dispositivo pelo nome, procure em /dev pelo caractere ou dispositivo
de bloco com o número principal correspondente e você encontrou os arquivos do
dispositivo.

Dispositivos 51
Machine Translated by Google

Entre esses métodos, apenas o primeiro é confiável, mas requer o udev. Se você se
deparar com uma situação em que o udev não esteja disponível, tente os outros métodos,
mas lembre-se de que o kernel pode não ter um arquivo de dispositivo para seu hardware.

As seções a seguir listam os dispositivos Linux mais comuns e suas convenções de


nomenclatura.

3.4.1 Discos Rígidos: /dev/sd*


A maioria dos discos rígidos conectados aos sistemas Linux atuais correspondem a nomes
de dispositivos com um prefixo sd , como /dev/ sda, / dev/ sdb e assim por diante. Esses
dispositivos representam discos inteiros; o kernel cria arquivos de dispositivo separados, como /dev/
sda1 e /dev/ sda2, para as partições em um disco.
A convenção de nomenclatura requer uma pequena explicação. A parte sd do nome significa
disco SCSI. Small Computer System Interface (SCSI) foi originalmente desenvolvido como um
padrão de hardware e protocolo para comunicação entre dispositivos como discos e outros
periféricos. Embora o hardware SCSI tradicional não seja usado na maioria das máquinas
modernas, o protocolo SCSI está em toda parte devido à sua adaptabilidade. Por exemplo,
dispositivos de armazenamento USB o usam para se comunicar. A história em discos SATA
(Serial ATA, um barramento de armazenamento comum em PCs) é um pouco mais complicada,
mas o kernel do Linux ainda usa comandos SCSI em um certo ponto ao falar com eles.

Para listar os dispositivos SCSI em seu sistema, use um utilitário que percorre os
caminhos dos dispositivos fornecidos pelo sysfs. Uma das ferramentas mais sucintas é o lsscsi.
Aqui está o que você pode esperar ao executá-lo:

$ lsscsi
[0:0:0:0]1 disco2 ATA WDC WD3200AAJS-2 01.0 /dev/sda3
[2:0:0:0] disco FLASH Drive UT_USB20 0,00 /dev/sdb

A primeira coluna 1 identifica o endereço do dispositivo no sistema, a segunda 2 descreve


que tipo de dispositivo é e a última 3 indica onde encontrar o arquivo do dispositivo. Todo o
resto é informação do fornecedor.
O Linux atribui dispositivos a arquivos de dispositivos na ordem em que seus drivers
encontram os dispositivos. Assim, no exemplo anterior, o kernel encontrou primeiro o disco e
depois a unidade flash.
Infelizmente, esse esquema de atribuição de dispositivo tradicionalmente causa problemas
ao reconfigurar o hardware. Digamos, por exemplo, que você tenha um sistema com três
discos: /dev/ sda, / dev/ sdb e /dev/ sdc. Se /dev/ sdb
explode e você deve removê-lo para que a máquina possa funcionar novamente, o antigo /dev/
sdc passa para /dev/ sdb e não há mais um /dev/ sdc. Se você estivesse se referindo aos nomes
dos dispositivos diretamente no arquivo fstab (consulte a Seção 4.2.8), você teria que fazer
algumas alterações nesse arquivo para que as coisas (principalmente) voltassem ao normal. Para
resolver esse problema, muitos sistemas Linux usam o Identificador Único Universal (UUID;
consulte a Seção 4.2.4) e/ou o mapeamento de dispositivo de disco estável do Gerenciador de
Volume Lógico (LVM).

52 Capítulo 3
Machine Translated by Google

Esta discussão mal arranhou a superfície de como usar discos e outros dispositivos de
armazenamento em sistemas Linux. Consulte o Capítulo 4 para obter mais informações sobre
como usar discos. Mais adiante neste capítulo, examinaremos como o suporte SCSI funciona
no kernel do Linux.

3.4.2 Discos Virtuais: /dev/xvd*, /dev/vd*

Alguns dispositivos de disco são otimizados para máquinas virtuais, como instâncias da AWS e
VirtualBox. O sistema de virtualização Xen usa o prefixo /dev/ xvd e /dev/ vd é um tipo semelhante.

3.4.3 Dispositivos de Memória Não Volátil: /dev/nvme*


Alguns sistemas agora usam a interface Non-Volatile Memory Express (NVMe) para se
comunicar com alguns tipos de armazenamento de estado sólido. No Linux, esses dispositivos
aparecem em /dev/ nvme*. Você pode usar o comando nvme list para obter uma lista desses
dispositivos em seu sistema.

3.4.4 Mapeador de dispositivos: /dev/dm-*, /dev/mapper/*


Um nível acima dos discos e outros armazenamentos de blocos diretos em alguns sistemas
é o LVM, que usa um sistema de kernel chamado mapeador de dispositivos. Se você vir
dispositivos de bloco começando com /dev/ dm- e links simbólicos em /dev/ mapper, seu
sistema provavelmente o usa. Você aprenderá tudo sobre isso no Capítulo 4.

3.4.5 Unidades de CD e DVD: /dev/sr*

O Linux reconhece a maioria das unidades de armazenamento óptico como dispositivos


SCSI /dev/ sr0, / dev/ sr1 e assim por diante. No entanto, se a unidade usa uma interface
mais antiga, ela pode aparecer como um dispositivo PATA, conforme discutido a seguir. Os
dispositivos / dev/ sr* são somente leitura e são usados apenas para leitura de discos. Para
os recursos de gravação e reescrita de dispositivos ópticos, você usará os dispositivos SCSI
“genéricos”, como /dev/ sg0.

3.4.6 Discos Rígidos PATA: /dev/hd*

PATA (Parallel ATA) é um tipo mais antigo de barramento de armazenamento. Os dispositivos


de bloco Linux /dev/ hda, / dev/ hdb, / dev/ hdc e /dev/ hdd são comuns em versões mais antigas
do kernel Linux e com hardware mais antigo. Essas são atribuições fixas com base nos pares
de dispositivos nas interfaces 0 e 1. Às vezes, você pode encontrar uma unidade SATA
reconhecida como um desses discos. Isso significa que a unidade SATA está sendo executada
em modo de compatibilidade, o que prejudica o desempenho. Verifique as configurações do
BIOS para ver se você pode alternar o controlador SATA para o modo nativo.

3.4.7 Terminais: /dev/tty*, /dev/pts/* e /dev/tty


Terminais são dispositivos para mover caracteres entre um processo de usuário e um
dispositivo de E/S, geralmente para saída de texto para uma tela de terminal. O terminal

Dispositivos 53
Machine Translated by Google

A interface do dispositivo remonta a um longo caminho, desde os dias em que os terminais eram
dispositivos baseados em máquinas de escrever e muitos eram conectados a uma única máquina.
A maioria dos terminais são dispositivos pseudoterminais , terminais emulados que
entendem os recursos de E/S dos terminais reais. Em vez de falar com um hardware real, o kernel
apresenta a interface de E/S para um software, como a janela do terminal shell na qual você
provavelmente digita a maioria dos comandos.

Dois dispositivos terminais comuns são /dev/ tty1 (o primeiro console virtual) e /dev/ pts/ 0 (o
primeiro dispositivo pseudoterminal). O próprio diretório /dev/ pts é um sistema de arquivos dedicado.

O dispositivo / dev/ tty é o terminal de controle do processo atual. Se um programa está atualmente
lendo e gravando em um terminal, este dispositivo é um sinônimo para aquele terminal. Um processo
não precisa estar conectado a um terminal.

Modos de exibição e consoles virtuais

O Linux tem dois modos de exibição principais: modo texto e modo gráfico (o Capítulo 14 apresenta
os sistemas de janelas que usam esse modo). Embora os sistemas Linux tradicionalmente sejam
inicializados no modo de texto, a maioria das distribuições agora usa parâmetros de kernel e
mecanismos de exibição gráfica provisória (bootsplashes como plymouth) para ocultar completamente
o modo de texto enquanto o sistema está inicializando. Nesses casos, o sistema alterna para o modo
gráfico completo perto do final do processo de inicialização.

O Linux suporta consoles virtuais para multiplexar a exibição. Cada console virtual pode ser
executado em modo gráfico ou texto. No modo texto, você pode alternar entre os consoles com uma
combinação de teclas de função ALT—por exemplo, ALT-F1 leva você para /dev/ tty1, ALT-F2 vai para /
dev/ tty2 e assim por diante. Muitos desses consoles virtuais podem ser ocupados por um processo getty
executando um prompt de login, conforme descrito na Seção 7.4.

Um console virtual usado no modo gráfico é um pouco diferente. Em vez de obter uma atribuição
de console virtual da configuração init, um ambiente gráfico assume um console virtual gratuito, a
menos que seja direcionado para usar um específico. Por exemplo, se você tem processos getty
rodando em tty1
e tty2, um novo ambiente gráfico assume o tty3. Além disso, uma vez no modo gráfico, você
normalmente deve pressionar uma combinação de teclas de função CTRL-ALT-para alternar para outro
console virtual em vez do simples ALT-
combinação de teclas de função.
O resultado de tudo isso é que se você quiser ver seu console de texto depois
seu sistema inicializar, pressione CTRL-ALT-F1. Para retornar ao ambiente gráfico, pressione ALT-
F2, ALT-F3 e assim por diante, até chegar ao ambiente gráfico.

NOTA Algumas distribuições usam tty1 no modo gráfico. Neste caso, você precisará tentar outros
consoles.

54 Capítulo 3
Machine Translated by Google

Se você tiver problemas para trocar de console devido a uma entrada com defeito
mecanismo ou alguma outra circunstância, você pode tentar forçar o sistema a mudar de
console com o comando chvt . Por exemplo, para alternar para tty1, execute o seguinte como
root:

# capítulo 1

3.4.8 Portas seriais: /dev/ttyS*, /dev/ttyUSB*, /dev/ttyACM*


Tipo RS-232 mais antigo e portas seriais semelhantes são representadas como verdadeiros
dispositivos terminais. Você não pode fazer muito na linha de comando com dispositivos de porta
serial porque há muitas configurações para se preocupar, como taxa de transmissão e controle
de fluxo, mas você pode usar o comando screen para se conectar a um terminal adicionando o
caminho do dispositivo como um argumento. Você pode precisar de permissão de leitura e
gravação no dispositivo; às vezes você pode fazer isso adicionando-se a um grupo específico,
como dialout.
A porta conhecida como COM1 no Windows é /dev/ ttyS0; COM2 é /dev/ ttyS1; e assim por
diante. Adaptadores seriais USB plug-in aparecem com USB e ACM com os nomes /dev/ ttyUSB0, /
dev/ ttyACM0, / dev/ ttyUSB1, / dev/ ttyACM1 e assim por diante.
Algumas das aplicações mais interessantes envolvendo portas seriais são placas
baseadas em microcontroladores que você pode conectar ao seu sistema Linux para
desenvolvimento e teste. Por exemplo, você pode acessar o console e ler o loop eval-print das
placas CircuitPython por meio de uma interface serial USB. Tudo o que você precisa fazer é
conectar um, procurar o dispositivo (geralmente /dev/ ttyACM0) e conectá-lo com a tela.

3.4.9 Portas paralelas: /dev/lp0 e /dev/lp1


Representando um tipo de interface que foi amplamente substituído por USB e redes, os
dispositivos de porta paralela unidirecional /dev/ lp0 e /dev/ lp1
correspondem a LPT1: e LPT2: no Windows. Você pode enviar arquivos (como um arquivo a
ser impresso) diretamente para uma porta paralela com o comando cat , mas pode ser
necessário fornecer à impressora uma alimentação de formulário extra ou redefinir posteriormente.
Um servidor de impressão como o CUPS é muito melhor para lidar com a interação com uma
impressora.
As portas paralelas bidirecionais são /dev/ parport0 e /dev/ parport1.

3.4.10 Dispositivos de áudio: /dev/snd/*, /dev/dsp, /dev/audio e mais


O Linux tem dois conjuntos de dispositivos de áudio. Existem dispositivos separados para
a interface do sistema Advanced Linux Sound Architecture (ALSA) e o antigo Open Sound
System (OSS). Os dispositivos ALSA estão em /dev/ snd
diretório, mas é difícil trabalhar com eles diretamente. Os sistemas Linux que usam ALSA suportam
dispositivos compatíveis com versões anteriores do OSS se o suporte do kernel do OSS estiver
carregado no momento.

Dispositivos 55
Machine Translated by Google

Algumas operações rudimentares são possíveis com o OSS dsp e áudio


dispositivos. Por exemplo, o computador reproduz qualquer arquivo WAV enviado para /dev/ dsp. No
entanto, o hardware pode não fazer o que você espera devido a incompatibilidades de frequência.
Além disso, na maioria dos sistemas, o dispositivo geralmente está ocupado assim que você faz login.

NOTA O som do Linux é um assunto confuso devido às muitas camadas envolvidas. Acabamos de conversar
sobre os dispositivos no nível do kernel, mas normalmente existem servidores de espaço do usuário,
como áudio de pulso, que gerenciam o áudio de diferentes fontes e atuam como intermediários entre os
dispositivos de som e outros processos do espaço do usuário.

3.4.11 Criação de arquivo de dispositivo

Em qualquer sistema Linux razoavelmente recente, você não cria seus próprios arquivos de dispositivo;
eles são criados por devtmpfs e udev (consulte a Seção 3.5). No entanto, é instrutivo ver como fazer isso
e, em raras ocasiões, pode ser necessário criar um pipe nomeado ou um arquivo de soquete.

O comando mknod cria um dispositivo. Você deve saber o nome do dispositivo, bem como seus

números maiores e menores. Por exemplo, criar /dev/ sda1 é uma questão de usar o seguinte comando:

# mknod /dev/sda1 b 8 1

O b 8 1 especifica um dispositivo de bloco com um número maior 8 e um número menor 1. Para


dispositivos de caractere ou pipe nomeado, use c ou p em vez de b (omita os números maior e menor para
pipes nomeados).
Em versões mais antigas do Unix e Linux, manter o diretório /dev era um desafio. Com cada
atualização significativa do kernel ou adição de driver, o kernel poderia suportar mais tipos de
dispositivos, o que significa que haveria um novo conjunto de números maiores e menores a serem
atribuídos aos nomes dos arquivos dos dispositivos. Para enfrentar este desafio de manutenção, cada
sistema teve um MAKEDEV
programa em /dev para criar grupos de dispositivos. Ao atualizar seu sistema, você tentaria encontrar
uma atualização para MAKEDEV e depois executá-la para criar novos dispositivos.

Este sistema estático tornou-se desajeitado, então uma substituição estava em ordem. A primeira
tentativa de corrigi-lo foi devfs, uma implementação de espaço do kernel de /dev que continha todos os
dispositivos que o kernel atual suportava. No entanto, houve uma série de limitações, o que levou ao
desenvolvimento do udev e do devtmpfs.

3,5 udev
Já falamos sobre como a complexidade desnecessária no kernel é perigosa porque você pode
facilmente introduzir instabilidade no sistema. O gerenciamento de arquivos de dispositivos é um
exemplo: você pode criar arquivos de dispositivos no espaço do usuário, então por que você faria isso no
kernel? O kernel do Linux pode enviar notificações para um processo de espaço do usuário chamado
udevd ao detectar um novo dispositivo no

56 Capítulo 3
Machine Translated by Google

o sistema (por exemplo, quando alguém conecta uma unidade flash USB). Esse processo udevd
pode examinar as características do novo dispositivo, criar um arquivo de dispositivo e, em seguida,
executar qualquer inicialização do dispositivo.

NOTA Você quase certamente verá o udevd rodando em seu sistema como systemd-udevd porque é uma parte do
mecanismo de inicialização que você verá no Capítulo 6.

Essa era a teoria. Infelizmente, há um problema com essa abordagem - os arquivos do


dispositivo são necessários no início do procedimento de inicialização, portanto, o udevd também deve
ser iniciado mais cedo. Mas para criar arquivos de dispositivo, o udevd não pode depender de nenhum
dispositivo que deve ser criado, e precisa executar sua inicialização inicial muito rapidamente para que
o resto do sistema não fique parado esperando o udevd iniciar.

3.5.1 devtmpfs
O sistema de arquivos devtmpfs foi desenvolvido em resposta ao problema de disponibilidade do
dispositivo durante a inicialização (consulte a Seção 4.2 para obter mais detalhes sobre sistemas de arquivos).
Este sistema de arquivos é semelhante ao suporte devfs mais antigo, mas simplificado. O kernel cria
arquivos de dispositivo conforme necessário, mas também notifica o udevd que um novo dispositivo
está disponível. Ao receber este sinal, o udevd não cria os arquivos do dispositivo, mas executa a
inicialização do dispositivo juntamente com a configuração de permissões e notifica outros processos
de que novos dispositivos estão disponíveis.
Além disso, ele cria vários links simbólicos em /dev para identificar melhor os dispositivos. Você pode
encontrar exemplos no diretório /dev/ disk/ by-id, onde cada disco anexado possui uma ou mais entradas.

Por exemplo, considere os links para um disco típico (anexado em /dev/ sda)
e suas partições em /dev/ disk/ by-id:

$ ls -l /dev/disk/by-id
lrwxrwxrwx 1 root root 9 de julho de 26 10:23 scsi-SATA_WDC_WD3200AAJS-_WD-WMAV2FU80671 -> ../../sda
lrwxrwxrwx 1 root root 10 Jul 26 10:23 scsi-SATA_WDC_WD3200AAJS-_WD-WMAV2FU80671-part1 ->
../../sda1
lrwxrwxrwx 1 root root 10 Jul 26 10:23 scsi-SATA_WDC_WD3200AAJS-_WD-WMAV2FU80671-part2 ->
../../sda2
lrwxrwxrwx 1 root root 10 Jul 26 10:23 scsi-SATA_WDC_WD3200AAJS-_WD-WMAV2FU80671-part5 ->
../../sda5

O processo udevd nomeia os links por tipo de interface e, em seguida, por informações de
fabricante e modelo, número de série e partição (se aplicável).

NOTA O “tmp” em devtmpfs indica que o sistema de arquivos reside na memória principal com
capacidade de leitura/ gravação por processos de espaço de usuário; essa característica permite que
o udevd crie esses links simbólicos. Veremos mais alguns detalhes na Seção 4.2.12.

Mas como o udevd sabe quais links simbólicos criar e como os cria? A próxima seção
descreve como o udevd faz seu trabalho.

No entanto, você não precisa saber nada disso ou de qualquer outro

Dispositivos 57
Machine Translated by Google

material neste capítulo para continuar com o livro. Na verdade, se esta é sua primeira vez
olhando para dispositivos Linux, você é altamente encorajado a pular para o próximo capítulo
para começar a aprender sobre como usar discos.

3.5.2 Operação e Configuração do udevd


O daemon udevd funciona da seguinte forma:

1. O kernel envia ao udevd um evento de notificação, chamado uevent, por meio de um


ligação de rede interna.

2. O udevd carrega todos os atributos no uevent.

3. O udevd analisa suas regras, filtra e atualiza o uevent com base nessas regras e executa
ações ou define mais atributos de acordo.

Um uevent de entrada que o udevd recebe do kernel pode parecer


this (você aprenderá como obter essa saída com o monitor udevadm --property
comando na Seção 3.5.4):

AÇÃO=alterar
DEVNAME=sde

DEVPATH=/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/1-1.2:1.0/host4/
target4:0:0/4:0:0:3/block/sde
DEVTYPE=disco

DISK_MEDIA_CHANGE=1
MAIOR=8
MENOR=64
SEQNUM = 2752
SUBSISTEMA=bloco

UDEV_LOG=3

Esse evento específico é uma alteração em um dispositivo. Depois de receber o uevent, o


udevd sabe o nome do dispositivo, o caminho do dispositivo sysfs e vários outros atributos
associados às propriedades; agora está pronto para iniciar o processamento de regras.

Os arquivos de regras estão nos diretórios /lib/ udev/ rules.de / etc/ udev/ rules.d . As
regras em /lib são os padrões e as regras em /etc são substituições.
Uma explicação completa das regras seria tediosa, e você pode aprender muito mais na
página de manual do udev(7), mas aqui estão algumas informações básicas sobre como o
udevd as lê:

1. O udevd lê as regras do início ao fim de um arquivo de regras.

2. Após ler uma regra e possivelmente executar sua ação, o udevd continua lendo o arquivo
de regras atual para obter regras mais aplicáveis.
3. Existem diretivas (como GOTO) para pular partes dos arquivos de regras, se necessário.
Eles geralmente são colocados no topo de um arquivo de regras para pular o arquivo
inteiro se for irrelevante para um dispositivo específico que o udevd está configurando.

58 Capítulo 3
Machine Translated by Google

Vejamos os links simbólicos do exemplo /dev/ sda na Seção 3.5.1. Esses links
foram definidos por regras em /lib/ udev/ rules.d/
60-armazenamento persistente.regras. Dentro, você verá as seguintes linhas:

# ATA
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}=
"ata_id --export $devnode"

# Dispositivos ATAPI (SPC-3 ou posterior)


KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5",ATTRS{scsi_
level}=="[6-9]*", IMPORT{program}="ata_id --export $devnode"

Essas regras correspondem a discos ATA e mídia ótica apresentados por meio do subsistema
SCSI do kernel (consulte a Seção 3.6). Você pode ver que existem algumas regras para capturar
diferentes maneiras de representar os dispositivos, mas a ideia é que o udevd tentará combinar um
dispositivo começando com sd ou sr mas sem um número (com o KERNEL=="sd*[ !0-9]|sr*"
expressão), bem como um subsistema (SUBSYSTEMS=="scsi") e, finalmente, alguns outros
atributos, dependendo do tipo de dispositivo. Se todas essas expressões condicionais forem
verdadeiras em qualquer uma das regras, o udevd passará para a próxima e última expressão:

IMPORT{program}="ata_id --export $tempnode"

Isso não é condicional. Em vez disso, é uma diretiva para importar variáveis do comando /
lib/ udev/ ata_id . Se você tiver um disco desse tipo, tente você mesmo na linha de comando. Isso
parecerá assim:

# /lib/udev/ata_id --export /dev/sda


ID_ATA=1
ID_TYPE=disco
ID_BUS=ata
ID_MODEL=WDC_WD3200AAJS-22L7A0
ID_MODEL_ENC=WDC\x20WD3200AAJS22L7A0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
\x20\x20\x20\x20\x20\x20\x20\x20\x20
ID_REVISION=01.03E10
ID_SERIAL=WDC_WD3200AAJS-22L7A0_WD-WMAV2FU80671
--recorte--

A importação agora configura o ambiente para que todos os nomes de variáveis nesta saída
sejam configurados para os valores mostrados. Por exemplo, qualquer regra a seguir agora
reconhecerá ENV{ID_TYPE} como disco.
Nas duas regras que vimos até agora, uma nota especial é ID_SERIAL. Em cada
regra, esta condicional aparece em segundo lugar:

ENV{ID_SERIAL}!="?*"

Essa expressão é avaliada como verdadeira se ID_SERIAL não estiver definido. Portanto,
se ID_SERIAL for definido, a condicional será falsa, a regra atual inteira não se aplicará e o
udevd passará para a próxima regra.

Dispositivos 59
Machine Translated by Google

Por que isso está aqui? O objetivo dessas duas regras é executar ata_id para encontrar
o número de série do dispositivo de disco e, em seguida, adicione esses atributos à cópia
de trabalho atual do uevent. Você encontrará esse padrão geral em muitas regras do udev.

Com ENV{ID_SERIAL} definido, o udevd agora pode avaliar essa regra posteriormente no
rules, que procura por quaisquer discos SCSI anexados:

KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disco", ENV{ID_


SERIAL}=="?*",SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"

Você pode ver que esta regra requer que ENV{ID_SERIAL} seja definido e tem uma
diretiva:

SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"

Esta diretiva diz ao udevd para adicionar um link simbólico para o dispositivo de
entrada. Então agora você sabe de onde vieram os links simbólicos do dispositivo!
Você pode estar se perguntando como diferenciar uma expressão condicional de
uma diretiva. As condicionais são indicadas por dois sinais de igual (==) ou um estrondo igual
(!=), e as diretivas por um único sinal de igual (=), um sinal de mais igual (+=) ou dois pontos
igual (:=).

3.5.3 udevadm
O programa udevadm é uma ferramenta de administração para o udevd. Você pode
recarregar as regras do udevd e acionar eventos, mas talvez os recursos mais poderosos do
udevadm sejam a capacidade de pesquisar e explorar dispositivos do sistema e a capacidade
de monitorar uevents à medida que o udevd os recebe do kernel. A sintaxe do comando
pode ser um pouco complicada, no entanto. Existem formas longas e curtas para a maioria
das opções; vamos usar os longos aqui.
Vamos começar examinando um dispositivo do sistema. Voltando ao exemplo na Seção
3.5.2, para ver todos os atributos do udev usados e gerados em conjunto com as regras para
um dispositivo como /dev/ sda, execute o seguinte comando:

$ udevadm info --query=all --name=/dev/sda

A saída fica assim:

P: /dispositivos/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda
N:sda
S: disk/by-id/ata-WDC_WD3200AAJS-22L7A0_WD-WMAV2FU80671
S: disk/by-id/scsi-SATA_WDC_WD3200AAJS-_WD-WMAV2FU80671
S: disk/by-id/wwn-0x50014ee057faef84
S: disco/por caminho/pci-0000:00:1f.2-scsi-0:0:0:0
E: DEVLINKS=/dev/disk/by-id/ata-WDC_WD3200AAJS-22L7A0_WD-WMAV2FU80671 /dev/
disco/por-id/scsi
-SATA_WDC_WD3200AAJS-_WD-WMAV2FU80671 /dev/disk/by-id/wwn-0x50014ee057faef84 /
dev/disco/por
-path/pci-0000:00:1f.2-scsi-0:0:0:0
E: DEVNAME=/dev/sda

60 Capítulo 3
Machine Translated by Google

E: DEVPATH=/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/
sda
E: DEVTYPE=disco
E: ID_ATA=1
E: ID_ATA_DOWNLOAD_MICROCODE=1
E: ID_ATA_FEATURE_SET_AAM=1
--recorte--

O prefixo em cada linha indica um atributo ou outra característica do dispositivo. Neste


caso, o P: na parte superior é o caminho do dispositivo sysfs, o N: é o nó do dispositivo (ou seja,
o nome dado ao arquivo /dev ), S: indica um link simbólico para o nó do dispositivo que o udevd
colocou em /dev de acordo com suas regras, e E: é a informação adicional do dispositivo
extraída nas regras do udevd. (Houve muito mais saída neste exemplo do que era necessário
mostrar aqui; tente o comando você mesmo para ter uma ideia do que ele faz.)

3.5.4 Monitoramento de Dispositivo

Para monitorar uevents com udevadm, use o comando monitor :

$ udevadm monitor

A saída (por exemplo, quando você insere um dispositivo de mídia flash) se parece com
este exemplo abreviado:

KERNEL[658299.569485] adicionar /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)


KERNEL[658299.569667] adicionar /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
KERNEL[658299.570614] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host15 (scsi)

KERNEL[658299.570645] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host15/scsi_host/host15


(scsi_host)
UDEV [658299.622579] adicionar /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2 (usb)
UDEV [658299.623014] adicionar /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0 (usb)
UDEV [658299.623673] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/host15 (scsi)

UDEV [658299.623690] add /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/


host15/scsi_host/host15 (scsi_host)
--recorte--

Há duas cópias de cada mensagem nesta saída porque o padrão


O comportamento é imprimir tanto a mensagem de entrada do kernel (marcada com
KERNEL) quanto as mensagens de processamento do udevd. Para ver apenas os eventos
do kernel, adicione a opção --kernel e, para ver apenas os eventos de processamento do udevd,
use --udev. Para ver todo o uevent de entrada, incluindo os atributos conforme mostrado na
Seção 3.5.2, use a opção --property . As opções --udev e --property juntas mostram o uevent
após o processamento.
Você também pode filtrar eventos por subsistema. Por exemplo, para ver apenas as
mensagens do kernel relacionadas a alterações no subsistema SCSI, use este comando:

$ udevadm monitor --kernel --subsystem-match=scsi

Para saber mais sobre o udevadm, consulte a página de manual do udevadm(8).

Dispositivos 61
Machine Translated by Google

Há muito mais no udev. Por exemplo, há um daemon chamado udisksd que escuta
eventos para anexar discos automaticamente e notificar outros processos de que novos discos
estão disponíveis.

3.6 Aprofundado: SCSI e o Kernel Linux


Nesta seção, veremos o suporte SCSI no kernel do Linux como uma forma de explorar parte da
arquitetura do kernel do Linux. Você não precisa saber nenhuma dessas informações para usar
discos, então se você estiver com pressa para usar um, vá para o Capítulo 4. Além disso, o
material aqui é mais avançado e teórico por natureza do que o que que você viu até agora, então
se você quiser continuar na prática, você definitivamente deveria pular para o próximo capítulo.

Vamos começar com um pouco de fundo. A configuração de hardware SCSI tradicional


é um adaptador de host vinculado a uma cadeia de dispositivos em um barramento SCSI,
conforme mostrado na Figura 3-1. O adaptador host está conectado a um computador. O
adaptador de host e os dispositivos têm um ID SCSI e pode haver 8 ou 16 IDs por barramento,
dependendo da versão SCSI. Alguns administradores podem usar o termo destino SCSI para se
referir a um dispositivo e sua ID SCSI porque uma extremidade de uma sessão no protocolo SCSI
é chamada de destino.

Computador

Adaptador de host SCSI Disco Disco CD/DVD


ID 7 ID 1 ID 0 ID 4

Barramento SCSI

Figura 3-1: Barramento SCSI com adaptador de host e dispositivos

Qualquer dispositivo pode se comunicar com outro por meio do conjunto de comandos SCSI
em um relacionamento ponto a ponto. O computador não está diretamente conectado à cadeia de
dispositivos, portanto, deve passar pelo adaptador host para se comunicar com discos e outros
dispositivos. Normalmente, o computador envia comandos SCSI ao adaptador host para retransmitir
aos dispositivos, e os dispositivos retransmitem as respostas de volta por meio do adaptador host.

Versões mais recentes de SCSI, como Serial Attached SCSI (SAS), oferecem
desempenho excepcional, mas você provavelmente não encontrará dispositivos SCSI verdadeiros
na maioria das máquinas. Você encontrará com mais frequência dispositivos de armazenamento
USB que usam comandos SCSI. Além disso, os dispositivos que suportam ATAPI (como unidades
de CD/DVD ROM) usam uma versão do conjunto de comandos SCSI.
Os discos SATA também aparecem em seu sistema como dispositivos SCSI, mas são
ligeiramente diferentes porque a maioria deles se comunica através de uma camada de
tradução na biblioteca libata (consulte a Seção 3.6.2). Alguns controladores SATA
(especialmente controladores RAID de alto desempenho) realizam essa conversão no hardware.

62 Capítulo 3
Machine Translated by Google

Como tudo isso se encaixa? Considere os dispositivos mostrados no sistema a seguir:

$ lsscsi
ATA
[0:0:0:0] disco WDC WD3200AAJS-2 01.0 /dev/sda
[1:0:0:0] cd/dvd DVD tipo fino A DS8A5SH XA15 /dev/sr0
Leitor de cartão USB 2.0
[2:0:0:0] disco 0100 /dev/sdb
CF [2:0:0:1] disco Leitor USB 2.0
de cartão SM
sdc
XD 0100 /dev/
USB 2.0
[2:0:0:2] disco 0100 /dev/sdd CardReader
FLASHSD 0100 /dev/sde
MS [2:0:0:3] disk CardReader
USB 2.0
[3:0:0:0] disco 0.00 /dev/sdf Conduzir UT_USB20

Os números entre colchetes são, da esquerda para a direita, o número do adaptador


host SCSI, o número do barramento SCSI, o ID SCSI do dispositivo e o LUN (número da
unidade lógica, uma subdivisão adicional de um dispositivo). Neste exemplo, há quatro
adaptadores conectados (scsi0, scsi1, scsi2 e scsi3), cada um com um único barramento
(todos com número de barramento 0) e apenas um dispositivo em cada barramento (todos com
destino 0). O leitor de cartão USB em 2:0:0 tem quatro unidades lógicas, porém - uma para cada
tipo de cartão flash que pode ser inserido. O kernel atribuiu um arquivo de dispositivo diferente
para cada unidade lógica.
Apesar de não serem dispositivos SCSI, os dispositivos NVMe às vezes podem aparecer
na saída lsscsi com um N como o número do adaptador.

NOTA Se você quiser experimentar o lsscsi por conta própria, talvez seja necessário instalá-lo como um
pacote.

A Figura 3-2 ilustra a hierarquia de driver e interface dentro do kernel para essa configuração
de sistema específica, desde os drivers de dispositivo individuais até os drivers de bloco. Ele não
inclui os drivers genéricos SCSI (sg) .
Embora esta seja uma estrutura grande e possa parecer esmagadora no início, o fluxo
de dados na figura é muito linear. Vamos começar a dissecá-lo examinando o subsistema SCSI
e suas três camadas de drivers:

•A camada superior trata das operações para uma classe de dispositivo. Por exemplo, o driver
sd (disco SCSI) está nesta camada; ele sabe como traduzir solicitações da interface do
dispositivo de bloco do kernel em comandos específicos do disco no protocolo SCSI e vice-
versa.
•A camada intermediária modera e roteia as mensagens SCSI entre
as camadas superior e inferior e mantém o controle de todos os barramentos e dispositivos
SCSI conectados ao sistema.
•A camada inferior lida com ações específicas de hardware. Os motoristas
aqui enviam mensagens de protocolo SCSI de saída para adaptadores de host ou
hardware específicos, e eles extraem mensagens de entrada do hardware.
A razão para essa separação da camada superior é que, embora as mensagens
SCSI sejam uniformes para uma classe de dispositivo (como a classe de disco),
diferentes tipos de adaptadores de host têm procedimentos variados para enviar as
mesmas mensagens.

Dispositivos 63
Machine Translated by Google

Kernel Linux

Interface de dispositivo de bloco (/dev/sda, /dev/sr0, etc.)

Subsistema SCSI

Driver de disco (sd) Driver de CD/DVD (sr)

Protocolo SCSI e gerenciamento de host

Ponte ATA Ponte de armazenamento USB

Subsistema USB
Subsistema USB

tradutor de libata Driver de armazenamento USB

Driver de host SATA Núcleo USB

Driver de host USB

Hardware

Flash USB Leitor de cartão USB


Disco SATA CD/DVD
Dirigir (CF, xD, MS, SD)

Figura 3-2: Esquema do subsistema Linux SCSI

As camadas superior e inferior contêm muitos drivers diferentes, mas é


importante lembrar que, para qualquer arquivo de dispositivo em seu sistema, o
kernel (quase sempre) usa um driver de camada superior e um driver de camada inferior.
Para o disco em /dev/ sda em nosso exemplo, o kernel usa o driver de camada
superior sd e o driver de camada inferior da ponte ATA.

64 Capítulo 3
Machine Translated by Google

Há momentos em que você pode usar mais de um driver de camada superior para
um dispositivo de hardware (consulte a Seção 3.6.3). Para dispositivos SCSI de hardware
verdadeiros, como um disco conectado a um adaptador host SCSI ou um controlador RAID
de hardware, os drivers da camada inferior se comunicam diretamente com o hardware
abaixo. No entanto, para a maioria dos hardwares anexados ao subsistema SCSI, a história
é diferente.

3.6.1 Armazenamento USB e SCSI


Para que o subsistema SCSI converse com o hardware de armazenamento USB comum,
conforme mostrado na Figura 3-2, o kernel precisa de mais do que apenas um driver SCSI
de camada inferior. Uma unidade flash USB representada por /dev/ sdf entende os
comandos SCSI, mas para realmente se comunicar com a unidade, o kernel precisa saber
como se comunicar através do sistema USB.
Em resumo, o USB é bastante semelhante ao SCSI — possui classes de
dispositivos, barramentos e controladores de host. Portanto, não deve ser surpresa
que o kernel do Linux inclua um subsistema USB de três camadas que se assemelha
ao subsistema SCSI, com drivers de classe de dispositivo na parte superior, um núcleo de
gerenciamento de barramento no meio e drivers de controlador de host na parte inferior.
Assim como o subsistema SCSI passa comandos SCSI entre seus componentes, o
subsistema USB passa mensagens USB entre seus componentes. Existe até um comando
lsusb que é semelhante ao lsscsi.
A parte que realmente nos interessa aqui é o driver de armazenamento USB no
topo. Este driver atua como um tradutor. De um lado, o driver fala SCSI e, do outro,
fala USB. Como o hardware de armazenamento inclui comandos SCSI dentro de suas
mensagens USB, o driver tem um trabalho relativamente fácil: ele reempacota principalmente
os dados.
Com os subsistemas SCSI e USB instalados, você tem quase tudo o que precisa
para se comunicar com a unidade flash. O último link ausente é o driver de camada
inferior no subsistema SCSI porque o driver de armazenamento USB faz parte do subsistema
USB, não do subsistema SCSI. (Por motivos organizacionais, os dois subsistemas não
devem compartilhar um driver.) Para que os subsistemas conversem entre si, um driver de
ponte SCSI simples de camada inferior conecta-se ao driver de armazenamento do
subsistema USB.

3.6.2 SCSI e ATA

O disco rígido SATA e a unidade óptica mostradas na Figura 3-2 usam a mesma
interface SATA. Para conectar os drivers SATA específicos do kernel ao subsistema
SCSI, o kernel emprega um driver de ponte, como nos drives USB, mas com um
mecanismo diferente e complicações adicionais. A unidade óptica fala ATAPI, uma versão
dos comandos SCSI codificados no protocolo ATA. No entanto, o disco rígido não usa
ATAPI e não codifica nenhum comando SCSI!

O kernel Linux usa parte de uma biblioteca chamada libata para reconciliar SATA
(e ATA) com o subsistema SCSI. Para os drives ópticos que falam ATAPI, esta é uma
tarefa relativamente simples de empacotar e extrair SCSI

Dispositivos 65
Machine Translated by Google

comandos de entrada e saída do protocolo ATA. Mas para o disco rígido, a tarefa é muito
mais complicada porque a biblioteca deve fazer uma tradução completa de comandos.

O trabalho da unidade óptica é semelhante a digitar um livro de inglês em um


computador. Você não precisa entender sobre o que é o livro para fazer esse trabalho, nem
precisa entender inglês. Mas a tarefa para o disco rígido é mais como ler um livro em
alemão e digitá-lo no computador como uma tradução para o inglês. Nesse caso, você
precisa entender os dois idiomas, bem como o conteúdo do livro.

Apesar dessa dificuldade, o libata realiza essa tarefa e possibilita conectar interfaces e
dispositivos ATA/SATA ao subsistema SCSI. (Normalmente, há mais drivers envolvidos do
que apenas um driver host SATA mostrado na Figura 3-2, mas eles não são mostrados para
simplificar.)

3.6.3 Dispositivos SCSI Genéricos

Quando um processo de espaço do usuário se comunica com o subsistema SCSI,


normalmente o faz por meio da camada de dispositivo de bloco e/ou outro serviço do
kernel que fica em cima de um driver de classe de dispositivo SCSI (como sd ou sr). Em
outras palavras, a maioria dos processos do usuário nunca precisa saber nada sobre
dispositivos SCSI ou seus comandos.
No entanto, os processos do usuário podem ignorar os drivers de classe de dispositivo e fornecer SCSI
comandos de protocolo diretamente aos dispositivos por meio de seus dispositivos
genéricos. Por exemplo, considere o sistema descrito na Seção 3.6, mas desta vez, dê uma
olhada no que acontece quando você adiciona a opção -g ao lsscsi para mostrar os
dispositivos genéricos:

$ lsscsi -g
[0:0:0:0] disco ATA WDC WD3200AAJS-2 01.0 /dev/sda 1/dev/sg0
[1:0:0:0] cd/dvd Slimtype DVD A DS8A5SH XA15 /dev/sr0 /dev/sg1
[2:0:0:0] disco USB2.0disco
CardReader
[2:0:0:2]
[2:0:0:3]
CF
disco
[2:0:0:1]
disco 0100 /dev/sdb /dev/sg2
[3:0:0:0] disco USB 2.0 CardReader SM XD 0100 /dev/sdc /dev/sg3
USB 2.0 CardReader 0100 /dev/sdd /dev/sg4
FLASH MS CardReader SD 0100 /dev/sde /dev/sg5
USB 2.0 Conduzir UT_USB20 0.00 /dev/sdf /dev/sg6

Além do arquivo de dispositivo de bloco usual, cada entrada lista um arquivo de


dispositivo genérico SCSI na última coluna 1. Por exemplo, o dispositivo genérico para a
unidade óptica em /dev/ sr0 é /dev/ sg1.
Por que você iria querer usar um dispositivo genérico? A resposta tem a ver com a
complexidade do código no kernel. À medida que as tarefas se tornam mais complicadas, é
melhor deixá-las fora do kernel. Considere escrever e ler CD/DVD.
Ler um disco óptico é uma operação bastante simples, e existe um driver de kernel
especial para isso.
No entanto, gravar um disco óptico é significativamente mais difícil do que ler, e
nenhum serviço crítico do sistema depende da ação de gravação.
Não há motivo para ameaçar o espaço do kernel com essa atividade. Portanto, para gravar
em um disco óptico no Linux, você executa um programa de espaço do usuário que se
comunica com um dispositivo SCSI genérico, como /dev/ sg1. Este programa pode ser um
pouco mais ineficiente que um driver de kernel, mas é muito mais fácil de construir e manter.

66 Capítulo 3
Machine Translated by Google

3.6.4 Métodos de acesso múltiplo para um único dispositivo

Os dois pontos de acesso (sr e sg) para uma unidade óptica do espaço do usuário são ilustrados
para o subsistema Linux SCSI na Figura 3-3 (todos os drivers abaixo da camada inferior SCSI
foram omitidos). O processo A lê da unidade usando o driver sr e o processo B grava na unidade
com o driver sg .
No entanto, processos como esses normalmente não seriam executados simultaneamente
para acessar o mesmo dispositivo.

Processo do usuário A Processo do usuário B

(lê do drive) (grava discos)

Kernel Linux

Interface de dispositivo de bloco

Subsistema SCSI

Driver de CD/DVD (sr) Driver genérico (sg)

Protocolo SCSI e gerenciamento de host

Driver de camada inferior

Hardware da unidade óptica

Figura 3-3: Esquema do driver de dispositivo óptico

Na Figura 3-3, o processo A lê do dispositivo de bloco. Mas os processos do usuário


realmente lêem os dados dessa maneira? Normalmente, a resposta é não, não diretamente.
Há mais camadas no topo dos dispositivos de bloco e ainda mais pontos de acesso para discos
rígidos, como você aprenderá no próximo capítulo.

Dispositivos 67
Machine Translated by Google
Machine Translated by Google

4
DISCOS E SISTEMAS DE ARQUIVOS

No Capítulo 3, vimos uma visão geral de alguns


dos dispositivos de disco de nível superior que o
kernel disponibiliza. Neste capítulo, vamos discutir
em detalhes como trabalhar com discos em um Linux
sistema. Você aprenderá como particionar discos, criar e manter
os sistemas de arquivos que vão dentro de partições de disco e
trabalhar com espaço de troca.
Lembre-se de que os dispositivos de disco têm nomes como /dev/ sda, o primeiro disco
do subsistema SCSI. Esse tipo de dispositivo de bloco representa o disco inteiro, mas há
muitos componentes e camadas diferentes dentro de um disco.
A Figura 4-1 ilustra um esquema de um disco Linux simples (observe que a figura não
está em escala). À medida que avança neste capítulo, você aprenderá onde cada peça se
encaixa.
Machine Translated by Google

Tabela de partição

Partição Partição

Sistema de arquivos Estruturas de dados do sistema de arquivos

Dados do arquivo

Figura 4-1: Esquema típico de disco do Linux

As partições são subdivisões de todo o disco. No Linux, eles são indicados com um número
após o dispositivo de bloco inteiro, então eles têm nomes como /dev/ sda1
e /dev/ sdb3. O kernel apresenta cada partição como um dispositivo de bloco, assim como faria
com um disco inteiro. As partições são definidas em uma pequena área do disco chamada tabela

de partição (também chamada de rótulo de disco).

NOTA Várias partições de dados já foram comuns em sistemas com discos grandes porque os PCs mais antigos
podiam inicializar apenas a partir de certas partes do disco. Além disso, os administradores usavam
partições para reservar uma certa quantidade de espaço para áreas do sistema operacional; por
exemplo, eles não queriam que os usuários pudessem preencher todo o sistema e impedir o
funcionamento de serviços críticos. Essa prática não é exclusiva do Unix; você ainda encontrará
muitos novos sistemas Windows com várias partições em um único disco. Além disso, a maioria dos
sistemas tem uma partição swap separada.

O kernel possibilita que você acesse um disco inteiro e uma de suas partições ao mesmo tempo,
mas você normalmente não faria isso a menos que estivesse copiando o disco inteiro.

O Linux Logical Volume Manager (LVM) adiciona mais flexibilidade a partições e dispositivos
de disco tradicionais e agora está em uso em muitos sistemas. Abordaremos o LVM na Seção 4.4.

A próxima camada acima da partição é o sistema de arquivos, o banco de dados de


arquivos e diretórios com os quais você está acostumado a interagir no espaço do usuário.
Exploraremos os sistemas de arquivos na Seção 4.2.

70 Capítulo 4
Machine Translated by Google

Como você pode ver na Figura 4-1, se você deseja acessar os dados em um
arquivo, você precisa usar o local de partição apropriado da tabela de partições e, em
seguida, pesquisar o banco de dados do sistema de arquivos nessa partição pelos
dados de arquivo desejados.
Para acessar dados em um disco, o kernel do Linux usa o sistema de camadas
mostrado na Figura 4-2. O subsistema SCSI e tudo o mais descrito na Seção 3.6 são
representados por uma única caixa. Observe que você pode trabalhar com o disco através
do sistema de arquivos, bem como diretamente através dos dispositivos de disco.
Você verá como os dois métodos funcionam neste capítulo. Para simplificar as coisas, o
LVM não é representado na Figura 4-2, mas possui componentes na interface do dispositivo
de bloco e alguns componentes de gerenciamento no espaço do usuário.
Para entender como tudo se encaixa, vamos começar por baixo com as partições.

Processos do usuário

Kernel Linux
Acesso ao dispositivo bruto (direto)

Chamadas do sistema Arquivos de dispositivo (nós)

Sistema de arquivo

Interface de dispositivo de bloco e mapeamento de partição

Subsistema SCSI e outros drivers

Dispositivo de armazenamento

Figura 4-2: Esquema do kernel para acesso ao disco

Discos e Sistemas de Arquivos 71


Machine Translated by Google

4.1 Particionando Dispositivos de Disco

Existem muitos tipos de tabelas de partição. Não há nada de especial em uma tabela de partição - é
apenas um monte de dados que dizem como os blocos no disco são divididos.

A tabela tradicional, que remonta aos dias do PC, é a encontrada dentro do Master Boot Record
(MBR), e tem muitas limitações. A maioria dos sistemas mais recentes usa a Tabela de Partição de
Identificador Globalmente Exclusivo (GPT).
Aqui estão algumas das muitas ferramentas de particionamento do Linux:

parted (“editor de partição”) Uma ferramenta baseada em texto que suporta MBR e GPT.

gparted Uma versão gráfica do parted.


fdisk A ferramenta tradicional de particionamento de disco Linux baseada em texto. Versões
recentes do fdisk suportam o MBR, GPT e muitos outros tipos de tabelas de partição, mas as
versões mais antigas eram limitadas ao suporte ao MBR.

Porque ele suporta tanto o MBR quanto o GPT há algum tempo, e


é fácil executar comandos únicos para obter rótulos de partição, usaremos parted
para exibir tabelas de partição. No entanto, ao criar e alterar tabelas de partição, usaremos o fdisk.
Isto irá ilustrar ambas as interfaces, e porque é que muitas pessoas preferem a interface fdisk devido
à sua natureza interactiva e ao facto de não fazer quaisquer alterações no disco até que tenha
oportunidade de as rever (discutiremos isto brevemente ).

NOTA Há uma diferença crítica entre particionamento e manipulação do sistema de arquivos: o


A tabela de partição define limites simples no disco, enquanto um sistema de arquivos é um sistema de
dados muito mais complexo. Por esta razão, usaremos ferramentas separadas para particionar e criar
sistemas de arquivos (veja a Seção 4.2.2).

4.1.1 Visualizando uma Tabela de Partições

Você pode ver a tabela de partições do seu sistema com parted -l. Esta saída de amostra mostra dois
dispositivos de disco com dois tipos diferentes de tabelas de partição:

# separou -l
Modelo: ATA KINGSTON SM2280S (scsi)
1 disco /dev/sda: 240 GB
Tamanho do setor (lógico/físico): 512B/512B
Tabela de partição: msdos
Sinalizadores de disco:

Número Início Fim Tamanho


de arquivos 1049kB
Tipo de
223GB
sistema Bandeiras
1 223GB ext4 primário 223GB 240GB 17.0GB estendido bota
2
5 223 GB 240 GB 17,0 GB lógica linux-swap (v1)

Modelo: Disco Flash Genérico (scsi)


2 Disco /dev/sdf: 4284MB

72 Capítulo 4
Machine Translated by Google

Tamanho do setor (lógico/físico): 512B/512B


Tabela de partição: gpt
Sinalizadores de disco:

Número Início Fim Nome do sistema de Bandeiras


1 Tamanho 1049kB 1050MB 1049MB arquivos myfirst
2 1050 MB 4284 MB 3235 MB meu segundo

O primeiro dispositivo (/ dev/ sda) 1 usa a tradicional tabela de partições MBR (que parted
chama msdos), e o segundo (/ dev/ sdf ) 2 contém uma GPT.
Observe que os dois tipos de tabela armazenam diferentes conjuntos de parâmetros. Em particular, a
tabela MBR não tem coluna Nome porque os nomes não existem nesse esquema. (Eu escolhi
arbitrariamente os nomes myfirst e mysecond na GPT.)

OBSERVAÇÃO Cuidado com os tamanhos das unidades ao ler as tabelas de partição. A saída do parted mostra
um tamanho aproximado baseado no que o parted acha que é mais fácil de ler. Por outro lado, fdisk -l
mostra um número exato, mas na maioria dos casos, as unidades são “setores” de 512 bytes, o que
pode ser confuso porque pode parecer que você dobrou os tamanhos reais de seu disco e partições.
Um olhar mais atento na visualização da tabela de partição do fdisk também revela as informações de
tamanho do setor.

Noções básicas de MBR

A tabela MBR neste exemplo contém partições primárias, estendidas e lógicas. Uma partição
primária é uma subdivisão normal do disco; partição 1 é um exemplo. O MBR básico tem um limite de
quatro partições primárias, portanto, se você quiser mais de quatro, deverá designar uma como
partição estendida.
Uma partição estendida se divide em partições lógicas, que o sistema operacional pode usar como
faria com qualquer outra partição. Neste exemplo, a partição 2 é uma partição estendida que contém a
partição lógica 5.

NOTA O tipo de sistema de ficheiros que lista a parte não é necessariamente o mesmo que o campo ID do sistema
em suas entradas MBR. O ID do sistema MBR é apenas um número que identifica o tipo de partição; por exemplo, 83 é
uma partição Linux e 82 é uma partição swap Linux. No entanto, o parted tenta ser mais informativo determinando por
conta própria que tipo de sistema de arquivos está nessa partição. Se você absolutamente precisar saber o ID do sistema
para um MBR, use fdisk -l.

Partições LVM: Um Sneak Peek

Ao visualizar sua tabela de partições, se você vir partições rotuladas como LVM (código 8e como
o tipo de partição), dispositivos denominados /dev/dm-* ou referências ao “mapeador de dispositivos”,
seu sistema usa LVM. Nossa discussão começará com o particionamento direto tradicional de disco,
que será um pouco diferente do que está em um sistema usando LVM.

Discos e Sistemas de Arquivos 73


Machine Translated by Google

Só para você saber o que esperar, vamos dar uma olhada rápida em alguns exemplos
de saída do parted -l em um sistema com LVM (uma nova instalação do Ubuntu usando LVM
no VirtualBox). Primeiro, há uma descrição da tabela de partição real, que se parece
principalmente com o esperado, exceto pelo sinalizador lvm :

Modelo: ATA VBOX HARDDISK (scsi)


Disco /dev/sda: 10,7 GB
Tamanho do setor (lógico/físico): 512B/512B
Tabela de partição: msdos
Sinalizadores de disco:

Número Início Fim Tamanho Tipo Sinalizadores do sistema de arquivos


1 1049kB 10,7GB 10,7GB primário bota, lvm

Depois, existem alguns dispositivos que parecem ser partições, mas são chamados
de discos:

Modelo: mapeador de dispositivos Linux (linear) (dm)


Disco /dev/mapper/ubuntu--vg-swap_1: 1023 MB
Tamanho do setor (lógico/físico): 512B/512B
Tabela de partição: loop
Sinalizadores de disco:

Número Início Fim Tamanho


Sistema de Bandeiras
1 arquivos 0.00B 1023MB 1023MB linux-swap(v1)

Modelo: mapeador de dispositivos Linux (linear) (dm)


Disco /dev/mapper/ubuntu--vg-root: 9672 MB
Tamanho do setor (lógico/físico): 512B/512B
Tabela de partição: loop
Sinalizadores de disco:

Número Início Fim Tamanho


Sinalizadores do sistema de arquivos
1 0.00B 9672MB 9672MB ext4

Uma maneira simples de pensar sobre isso é que as partições foram separadas de
alguma forma da tabela de partições. Você verá o que realmente está acontecendo na
Seção 4.4.

OBSERVAÇÃO Você obterá uma saída muito menos detalhada com fdisk -l; no caso anterior, você
não verá nada além de uma partição física rotulada como LVM.

Leitura inicial do kernel

Ao ler inicialmente a tabela MBR, o kernel do Linux produz uma saída de depuração
como esta (lembre-se de que você pode visualizar isso com journalctl -k):

sda:sda1 sda2<sda5>

74 Capítulo 4
Machine Translated by Google

A parte sda2 < sda5 > da saída indica que /dev/ sda2 é uma partição estendida contendo uma
partição lógica, /dev/ sda5. Normalmente, você ignorará a própria partição estendida porque
normalmente se preocupa apenas em acessar as partições lógicas que ela contém.

4.1.2 Modificando Tabelas de Partição


A visualização de tabelas de partição é uma operação relativamente simples e inofensiva.
Alterar as tabelas de partição também é relativamente fácil, mas fazer esse tipo de alteração no
disco envolve riscos. Tenha em mente o seguinte:

•A alteração da tabela de partições torna bastante difícil recuperar quaisquer dados nas partições que
você exclui ou redefine, pois isso pode apagar a localização dos sistemas de arquivos nessas
partições. Certifique-se de ter um backup se o disco que você está particionando contiver dados
críticos.

•Certifique-se de que nenhuma partição em seu disco de destino esteja em uso no momento. Isso é
uma preocupação porque a maioria das distribuições Linux monta automaticamente qualquer
sistema de arquivos detectado. (Consulte a Seção 4.2.3 para obter mais informações sobre
montagem e desmontagem.)

Quando estiver pronto, escolha seu programa de particionamento. Se quiser usar o parted, você
pode usar o utilitário parted da linha de comando ou uma interface gráfica, como gparted; O fdisk é
bastante fácil de trabalhar na linha de comando.
Todos esses utilitários têm ajuda online e são fáceis de aprender. (Tente usá-los em um dispositivo
flash ou algo semelhante se você não tiver discos sobressalentes.)
Dito isto, há uma grande diferença na maneira como fdisk e parted
trabalhar. Com o fdisk, você projeta sua nova tabela de partições antes de fazer as alterações
reais no disco e faz as alterações somente quando você sai do programa. Mas com o parted, as
partições são criadas, modificadas e removidas conforme você emite os comandos. Você não tem
a chance de revisar a tabela de partição antes de alterá-la.

Essas diferenças também são fundamentais para entender como os dois utilitários interagem
com o kernel. Tanto o fdisk quanto o parted modificam as partições inteiramente no espaço do usuário;
não há necessidade de fornecer suporte ao kernel para reescrever uma tabela de partição, porque o
espaço do usuário pode ler e modificar todo um dispositivo de bloco.
Em algum momento, porém, o kernel deve ler a tabela de partições para apresentar as
partições como dispositivos de bloco para que você possa usá-las. O utilitário fdisk usa um método
relativamente simples. Após modificar a tabela de partições, o fdisk emite uma única chamada de
sistema para dizer ao kernel que ele deve reler a tabela de partições do disco (você verá um exemplo
de como interagir com o fdisk
Em breve). O kernel então gera a saída de depuração, que você pode ver com journalctl -k. Por
exemplo, se você criar duas partições em /dev/ sdf, verá isto:

sdf: sdf1 sdf2

Discos e Sistemas de Arquivos 75


Machine Translated by Google

As ferramentas parted não usam essa chamada de sistema em todo o disco; em vez disso, eles
sinalizam ao kernel quando partições individuais são alteradas. Depois de processar uma única
alteração de partição, o kernel não produz a saída de depuração anterior.

Existem algumas maneiras de ver as alterações de partição:

•Use o udevadm para observar as mudanças nos eventos do kernel. Por exemplo, o com
mand udevadm monitor --kernel mostrará os dispositivos de partição antigos sendo removidos e
os novos sendo adicionados.

• Verifique /proc/ partitions para obter informações completas sobre a partição.

• Verifique /sys/ block/ device/ para interfaces de sistema de partição alteradas ou /dev para
dispositivos de partição alterados.

FORÇAR UMA RECARGA DA TABELA DE PARTIÇÃO

Se você absolutamente precisar confirmar suas modificações em uma tabela de partição,


poderá usar o comando blockdev para executar a chamada de sistema de estilo antigo que o fdisk emite.
Por exemplo, para forçar o kernel a recarregar a tabela de partição em /dev/sdf, execute isto:

# blockdev --rereadpt /dev/sdf

4.1.3 Criando uma Tabela de Partição


Vamos aplicar tudo o que você acabou de aprender criando uma nova tabela de partição em um disco
novo e vazio. Este exemplo mostra o seguinte cenário:

• Disco de 4 GB (um pequeno dispositivo flash USB, não usado; se você quiser seguir este exemplo,
use qualquer dispositivo de tamanho que você tenha em mãos)

•Tabela de partição estilo MBR

• Duas partições destinadas a serem preenchidas com um sistema de arquivos ext4: 200 MB e
3,8 GB

•Dispositivo de disco em /dev/ sdd; você precisará encontrar a localização do seu próprio dispositivo
com lsblk

Você usará o fdisk para fazer o trabalho. Lembre-se de que este é um comando interativo,

portanto, após garantir que nada no disco esteja montado, você iniciará no prompt de comando com o
nome do dispositivo:

# fdisk /dev/sdd

Você receberá uma mensagem introdutória e, em seguida, um prompt de comando como este:

Comando (m para ajuda):

76 Capítulo 4
Machine Translated by Google

Primeiro, imprima a tabela atual com o comando p (os comandos fdisk são
bastante conciso). Sua interação provavelmente será mais ou menos assim:

Comando (m para ajuda): p


Disco /dev/sdd: 4 GiB, 4284481536 bytes, 8368128 setores
Unidades: setores de 1 * 512 = 512 bytes
Tamanho do setor (lógico/físico): 512 bytes / 512 bytes
Tamanho de E/S (mínimo/ideal): 512 bytes / 512 bytes
Tipo de etiqueta de disco: dos
Identificador de disco: 0x88f290cc

Inicialização Tipo de ID de tamanho dos setores finais


Dispositivo /dev/sdd1 2048 8368127 8366080 4G c W95 FAT32 (LBA)

A maioria dos dispositivos já contém uma partição no estilo FAT, como esta em /
dev/ sdd1. Como você deseja criar novas partições para Linux (e, claro, você tem
certeza de que não precisa de nada aqui), você pode excluir as existentes assim:

Comando (m para ajuda): d


Partição 1 selecionada
A partição 1 foi excluída.

Lembre-se de que o fdisk não faz alterações até que você escreva explicitamente
a tabela de partição, então você ainda não modificou o disco. Se você cometer um erro
do qual não pode se recuperar, use o comando q para sair do fdisk sem escrever as
alterações.
Agora você criará a primeira partição de 200 MB com o comando n :

Comando (m para ajuda): n


Tipo de partição
p primário (0 primário, 0 estendido, 4 livre)
e estendido (contêiner para partições lógicas)
Selecione (padrão p): p
Número da partição (1-4, padrão 1): 1
Primeiro setor (2048-8368127, padrão 2048): 2048
Último setor, +setores ou +tamanho{K,M,G,T,P} (2048-8368127, padrão 8368127): +200M

Criou uma nova partição 1 do tipo 'Linux' e de tamanho 200 MiB.

Aqui, o fdisk solicita o estilo da partição MBR, o número da partição, o início da


partição e seu final (ou tamanho). Os valores padrão são muitas vezes o que você deseja.
A única coisa que mudou aqui é o final/tamanho da partição com a sintaxe + para
especificar um tamanho e uma unidade.
A criação da segunda partição funciona da mesma maneira, exceto que você usará
todos os valores padrão, então não vamos passar por cima disso. Quando terminar de
organizar as partições, use o comando p (print) para revisar:

Comando (m para ajuda): p


[--recorte--]
Inicialização Tipo de ID de tamanho dos setores finais
Dispositivo /dev/sdd1 2048 411647 409600 200M 83 Linux

Discos e Sistemas de Arquivos 77


Machine Translated by Google

/dev/sdd2 411648 8368127 7956480 3.8G 83 Linux

Quando estiver pronto para escrever a tabela de partições, use o comando w :

Comando (m para ajuda): w


A tabela de partição foi alterada.
Chamando ioctl() para reler a tabela de partições.
Sincronizando discos.

Observe que o fdisk não pergunta se você tem certeza como medida de segurança; é sim
ply faz seu trabalho e sai.
Se você estiver interessado em mensagens de diagnóstico adicionais, use journalctl -k
para ver o kernel leia as mensagens mencionadas anteriormente, mas lembre-se de que você
as obterá apenas se estiver usando o fdisk.
Neste ponto, você tem todos os fundamentos para começar a particionar discos, mas
se quiser mais detalhes sobre discos, continue lendo. Caso contrário, pule para a Seção 4.2
para aprender como colocar um sistema de arquivos no disco.

4.1.4 Navegando no Disco e na Geometria da Partição


Qualquer dispositivo com partes móveis introduz complexidade em um sistema de software
porque existem elementos físicos que resistem à abstração. Um disco rígido não é exceção;
mesmo que você possa pensar em um disco rígido como um dispositivo de bloco com acesso
aleatório a qualquer bloco, pode haver sérias consequências de desempenho se o sistema não
for cuidadoso sobre como ele organiza os dados no disco. Considere as propriedades físicas do
disco simples de prato único ilustrado na Figura 4-3.

Cilindro
Cabeça

Fuso

Braço

Prato

Figura 4-3: Vista de cima para baixo de um disco rígido

O disco consiste em um prato giratório em um fuso, com uma cabeça presa a


um braço móvel que pode varrer o raio do disco.
À medida que o disco gira sob a cabeça, a cabeça lê os dados. Quando o braço está em
uma posição, a cabeça pode ler dados apenas de um círculo fixo.
Este círculo é chamado de cilindro porque discos maiores têm mais de um

78 Capítulo 4
Machine Translated by Google

prato, todos empilhados e girando em torno do mesmo eixo. Cada prato pode ter uma ou
duas cabeças, para a parte superior e/ou inferior do prato, e todas as cabeças são presas ao
mesmo braço e se movem em conjunto. Como o braço se move, há muitos cilindros no disco,
desde os pequenos ao redor do centro até os grandes ao redor da periferia do disco. Finalmente,
você pode dividir um cilindro em fatias chamadas setores. Essa forma de pensar a geometria
do disco é chamada de CHS, para setor de cabeça de cilindro; em sistemas mais antigos, você
poderia encontrar qualquer parte do disco endereçando-o com esses três parâmetros.

NOTA Uma pista é a parte de um cilindro que uma única cabeça acessa, então na Figura 4-3, o cilindro
também é uma pista. Você não precisa se preocupar com faixas.

O kernel e os vários programas de particionamento podem informar o que um disco


relata como seu número de cilindros. No entanto, em qualquer disco rígido recente, os valores
relatados são fictícios! O esquema de endereçamento tradicional que usa CHS não se adapta
ao hardware de disco moderno, nem leva em conta o fato de que você pode colocar mais dados
em cilindros externos do que em cilindros internos. O hardware de disco oferece suporte ao
endereçamento de bloco lógico (LBA) para endereçar um local no disco por um número de bloco
(essa é uma interface muito mais direta), mas os remanescentes do CHS permanecem. Por
exemplo, a tabela de partição MBR contém informações CHS, bem como equivalentes de LBA, e
alguns carregadores de inicialização ainda são burros o suficiente para acreditar nos valores CHS
(não se preocupe - a maioria dos carregadores de inicialização Linux usa os valores LBA).

NOTA A palavra setor é confusa, porque os programas de particionamento do Linux podem usá-la para
significar um valor diferente.

OS LIMITES DO CILINDRO SÃO IMPORTANTES?

A ideia de cilindros já foi fundamental para o particionamento porque os cilindros são limites
ideais para partições. Ler um fluxo de dados de um cilindro é muito rápido porque o cabeçote
pode coletar dados continuamente à medida que o disco gira. Uma partição organizada como
um conjunto de cilindros adjacentes também permite acesso rápido e contínuo aos dados porque
o cabeçote não precisa se mover muito entre os cilindros.
Embora os discos pareçam mais ou menos os mesmos de sempre, a noção de
alinhamento preciso das partições tornou-se obsoleta. Alguns programas de particionamento
mais antigos reclamam se você não coloca suas partições precisamente em limites cilíndricos.
Ignore isso; há pouco que você pode fazer, porque os valores CHS relatados de discos
modernos simplesmente não são verdadeiros. O esquema LBA do disco, juntamente com uma
lógica melhor em utilitários de particionamento mais recentes, garante que suas partições
sejam dispostas de maneira razoável.

Discos e Sistemas de Arquivos 79


Machine Translated by Google

4.1.5 Leitura de discos de estado sólido Dispositivos

de armazenamento sem partes móveis, como discos de estado sólido (SSDs), são radicalmente
diferentes de discos giratórios em termos de suas características de acesso. Para estes, o acesso
aleatório não é um problema porque não há cabeça para varrer um prato, mas certas características
podem alterar o desempenho de um SSD.

Um dos fatores mais significativos que afetam o desempenho dos SSDs é o alinhamento da
partição. Ao ler dados de um SSD, você os lê em pedaços (chamados de páginas, que não devem ser
confundidos com páginas de memória virtual) — como 4.096 ou 8.192 bytes por vez — e a leitura deve
começar em um múltiplo desse tamanho.
Isso significa que, se sua partição e seus dados não estiverem em um limite, talvez seja necessário
fazer duas leituras em vez de uma para operações pequenas e comuns, como ler o conteúdo de um
diretório.
Versões razoavelmente novas de utilitários de particionamento incluem lógica para colocar
partições recém-criadas nos deslocamentos apropriados desde o início dos discos, portanto, você
provavelmente não precisa se preocupar com o alinhamento inadequado das partições. As
ferramentas de particionamento atualmente não fazem nenhum cálculo; em vez disso, eles apenas
alinham partições em limites de 1 MB ou, mais precisamente, 2.048 blocos de 512 bytes. Essa é uma
abordagem bastante conservadora porque o limite se alinha com tamanhos de página de 4.096, 8.192 e
assim por diante, até 1.048.576.
No entanto, se você estiver curioso ou quiser garantir que suas partições comecem em um
limite, poderá encontrar facilmente essas informações no /sys/ block
diretório. Aqui está um exemplo para a partição /dev/ sdf2:

$ cat /sys/block/sdf/sdf2/start
1953126

A saída aqui é o deslocamento da partição desde o início do dispositivo, em unidades de 512


bytes (novamente, confusamente chamados de setores pelo sistema Linux). Se este SSD usa páginas
de 4.096 bytes, há oito desses setores em uma página.
Tudo o que você precisa fazer é ver se pode dividir uniformemente o deslocamento da partição por 8.
Nesse caso, você não pode, então a partição não atingiria o desempenho ideal.

4.2 Sistemas de arquivos

O último link entre o kernel e o espaço do usuário para discos é normalmente o sistema de
arquivos; é com isso que você está acostumado a interagir quando executa comandos como ls e cd.
Como mencionado anteriormente, o sistema de arquivos é uma forma de banco de dados; ele fornece
a estrutura para transformar um dispositivo de bloco simples em uma hierarquia sofisticada de arquivos
e subdiretórios que os usuários podem entender.

Ao mesmo tempo, todos os sistemas de arquivos residiam em discos e outras mídias físicas
destinadas exclusivamente ao armazenamento de dados. No entanto, a estrutura de diretórios em
forma de árvore e a interface de E/S dos sistemas de arquivos são bastante versáteis, de modo que os
sistemas de arquivos agora executam uma variedade de tarefas, como as interfaces de sistema que
você vê em /sys e /proc. Os sistemas de arquivos são tradicionalmente implementados no kernel, mas

80 Capítulo 4
Machine Translated by Google

a inovação do 9P do Plano 9 (https:// en.wikipedia.org/ wiki/ 9P_(protocol)) inspirou o


desenvolvimento de sistemas de arquivos de espaço do usuário. O recurso File System in User
Space (FUSE) permite sistemas de arquivos de espaço de usuário no Linux.
A camada de abstração do Virtual File System (VFS) completa a implementação do
sistema de arquivos. Assim como o subsistema SCSI padroniza a comunicação entre diferentes
tipos de dispositivos e comandos de controle do kernel, o VFS garante que todas as
implementações de sistemas de arquivos suportem uma interface padrão para que os aplicativos
do espaço do usuário acessem arquivos e diretórios da mesma maneira.
O suporte a VFS permitiu que o Linux suportasse um número extraordinariamente grande de
sistemas de arquivos.

4.2.1 Tipos de sistema de arquivos

O suporte ao sistema de arquivos Linux inclui designs nativos otimizados para Linux; tipos
estrangeiros, como a família Windows FAT; sistemas de arquivos universais, como ISO 9660; e
muitos outros. A lista a seguir inclui os tipos mais comuns de sistemas de arquivos para
armazenamento de dados. Os nomes dos tipos reconhecidos pelo Linux estão entre parênteses
ao lado dos nomes dos sistemas de arquivos.

•O Quarto Sistema de Arquivos Estendido (ext4) é a iteração atual de uma linha de sistemas
de arquivos nativos do Linux. O Second Extended filesystem (ext2) era um padrão de
longa data para sistemas Linux inspirados em sistemas de arquivos Unix tradicionais,
como o Unix File System (UFS) e o Fast File System (FFS). O terceiro sistema de
arquivos estendido (ext3) adicionou um recurso de diário (um pequeno cache fora da
estrutura de dados normal do sistema de arquivos) para melhorar a integridade dos
dados e acelerar a inicialização. O sistema de arquivos ext4 é uma melhoria incremental
e suporta arquivos maiores que ext2 ou ext3, bem como um número maior de subdiretórios.

Há uma certa quantidade de compatibilidade com versões anteriores na série de


sistemas de arquivos estendidos. Por exemplo, você pode montar sistemas de arquivos
ext2 e ext3 como um ao outro, e você pode montar sistemas de arquivos ext2 e ext3 como
ext4, mas não pode montar ext4 como ext2 ou ext3.

• Btrfs, ou sistema de arquivos B-tree (btrfs), é um sistema de arquivos mais recente


nativo do Linux projetado para escalar além dos recursos do ext4.
• Os sistemas de arquivos FAT (msdos, vfat, exfat) pertencem aos sistemas Microsoft. O
tipo simples msdos suporta a variedade monocase muito primitiva em sistemas MS-
DOS. A maioria das mídias flash removíveis, como cartões SD e unidades USB, contém
partições vfat (até 4 GB) ou exfat (4 GB ou mais) por padrão. Os sistemas Windows
podem usar um sistema de arquivos baseado em FAT ou o mais avançado NT File
System (ntfs).
• XFS é um sistema de arquivos de alto desempenho usado por padrão por algumas
distribuições, como Red Hat Enterprise Linux 7.0 e posteriores.
• HFS+ (hfsplus) é um padrão da Apple usado na maioria dos sistemas Macintosh.
• ISO 9660 (iso9660) é um padrão de CD-ROM. A maioria dos CD-ROMs usa alguma
variedade do padrão ISO 9660.

Discos e Sistemas de Arquivos 81


Machine Translated by Google

EVOLUÇÃO DO SISTEMA DE ARQUIVOS LINUX

A série Extended filesystem tem sido perfeitamente aceitável para a maioria dos
usuários, e o fato de ter permanecido o padrão de fato por tanto tempo é uma prova de
sua utilidade, mas também de sua adaptabilidade. A comunidade de desenvolvimento do
Linux tem a tendência de substituir completamente os componentes que não atendem às
necessidades atuais, mas toda vez que o sistema de arquivos estendido fica aquém, alguém
o atualiza em resposta. No entanto, muitos avanços foram feitos na tecnologia do sistema
de arquivos que mesmo o ext4 não pode utilizar devido ao requisito de compatibilidade com
versões anteriores. Esses avanços estão principalmente em aprimoramentos de escalabilidade
relacionados a um grande número de arquivos, arquivos grandes e cenários semelhantes.
No momento da redação deste artigo, Btrfs é o padrão para uma grande distribuição
Linux. Se isso for um sucesso, é provável que o Btrfs esteja pronto para substituir a série
Extended.

4.2.2 Criando um sistema de arquivos

Se estiver preparando um novo dispositivo de armazenamento, assim que terminar o processo de


particionamento descrito na Seção 4.1, você estará pronto para criar um sistema de arquivos.
Assim como no particionamento, você fará isso no espaço do usuário porque um processo no espaço
do usuário pode acessar e manipular diretamente um dispositivo de bloco.
O utilitário mkfs pode criar vários tipos de sistemas de arquivos. Por exemplo, você
pode criar uma partição ext4 em /dev/ sdf2 com este comando:

# mkfs -t ext4 /dev/sdf2

O programa mkfs determina automaticamente o número de blocos em um dispositivo e define


alguns padrões razoáveis. A menos que você realmente saiba o que está fazendo e sinta vontade de
ler a documentação em detalhes, não os altere.

Quando você cria um sistema de arquivos, o mkfs imprime a saída de diagnóstico à medida que
funciona, incluindo a saída referente ao superbloco. O superbloco é um componente chave no nível
superior do banco de dados do sistema de arquivos e é tão importante que o mkfs cria vários backups
caso o original seja destruído. Considere gravar alguns dos números de backup do superblock quando o
mkfs for executado, caso você precise recuperar o superblock no caso de uma falha de disco (consulte a
Seção 4.2.11).

AVISO A criação do sistema de arquivos é uma tarefa que você deve executar somente após adicionar um novo disco ou
reparticionar um antigo. Você deve criar um sistema de arquivos apenas uma vez para cada nova partição
que não tenha dados preexistentes (ou que tenha dados que você deseja remover). Criar um novo
sistema de arquivos em cima de um sistema de arquivos existente destruirá efetivamente os dados antigos.

82 Capítulo 4
Machine Translated by Google

O QUE É MKFS?

Acontece que mkfs é apenas um frontend para uma série de programas de criação de sistemas de
arquivos, mkfs.fs, onde fs é um tipo de sistema de arquivos. Então, quando você executa mkfs -t ext4,
mkfs , por sua vez, executa mkfs.ext4.

E há ainda mais indireção. Inspecione os arquivos mkfs.* por trás do com


mandos, e você verá o seguinte:

$ ls -l /sbin/mkfs.*
-rwxr-xr-x 1 root root 17896 29 de março 21:49 /sbin/mkfs.bfs
-rwxr-xr-x 1 root root 30280 29 de março 21:49 /sbin/mkfs.cramfs
lrwxrwxrwx 1 raiz raiz 6 de março 30 13:25 /sbin/mkfs.ext2 -> mke2fs
lrwxrwxrwx 1 raiz raiz 6 de março 30 13:25 /sbin/mkfs.ext3 -> mke2fs
lrwxrwxrwx 1 raiz raiz 6 de março 30 13:25 /sbin/mkfs.ext4 -> mke2fs
lrwxrwxrwx 1 raiz raiz -rwxr- 6 de março 30 13:25 /sbin/mkfs.ext4dev -> mke2fs
xr-x 1 raiz raiz 26200 29 de março 21:49 /sbin/mkfs.minix
lrwxrwxrwx 1 root root 7 19 de dezembro de 2011 /sbin/mkfs.msdos -> mkdosfs
lrwxrwxrwx 1 root root 6 de março de 2012 /sbin/mkfs.ntfs -> mkntfs
lrwxrwxrwx 1 root root 7 19 de dezembro de 2011 /sbin/mkfs.vfat -> mkdosfs

Como você pode ver, mkfs.ext4 é apenas um link simbólico para mke2fs. Isso é
importante lembrar se você executar em um sistema sem um comando mkfs específico ou
quando estiver procurando a documentação de um sistema de arquivos específico. O utilitário
de criação de cada sistema de arquivos tem sua própria página de manual, como mke2fs(8).
Isso não deve ser um problema na maioria dos sistemas, porque acessar a página de manual
mkfs.ext4(8) deve redirecioná-lo para a página de manual mke2fs(8), mas lembre-se disso.

4.2.3 Montando um sistema de arquivos

No Unix, o processo de anexar um sistema de arquivos a um sistema em execução é chamado


de montagem. Quando o sistema inicializa, o kernel lê alguns dados de configuração e monta a
raiz (/) com base nos dados de configuração.
Para montar um sistema de arquivos, você deve saber o seguinte:

•O dispositivo, localização ou identificador do sistema de arquivos (como uma partição de disco—


onde residem os dados reais do sistema de arquivos). Alguns sistemas de arquivos para
fins especiais, como proc e sysfs, não possuem locais.
•O tipo de sistema de arquivos.
•O ponto de montagem—o local na hierarquia de diretórios do sistema atual onde o sistema de
arquivos será anexado. O ponto de montagem é sempre um diretório normal. Por exemplo,
você pode usar /music como um ponto de montagem para um sistema de arquivos
contendo música. O ponto de montagem não precisa estar diretamente abaixo de /; ele
pode estar em qualquer lugar no sistema.

Discos e Sistemas de Arquivos 83


Machine Translated by Google

A terminologia comum para montar um sistema de arquivos é “montar um dispositivo em um ponto de


montagem”. Para saber o status atual do sistema de arquivos do seu sistema, execute mount. A saída (que
pode ser bastante longa) deve ficar assim:

$ montar
/dev/sda1 em / digite ext4 (rw,errors=remount-ro)
proc em /proc tipo proc (rw,noexec,nosuid,nodev)
sysfs em /sys tipo sysfs (rw,noexec,nosuid,nodev)
fusectl em /sys/fs/fuse/connections tipo fusectl (rw)
debugfs em /sys/kernel/debug type debugfs (rw)
securityfs em /sys/kernel/security type securityfs (rw)
udev em /dev tipo devtmpfs (rw,mode=0755)
devpts em /dev/pts tipo devpts (rw,noexec,nosuid,gid=5,mode=0620)
tmpfs em /run digite tmpfs (rw,noexec,nosuid,size=10%,mode=0755)
--recorte--

Cada linha corresponde a um sistema de arquivos atualmente montado, com itens nesta ordem:

1. O dispositivo, como /dev/ sda3. Observe que alguns deles não são dispositivos reais (proc, por
exemplo), mas são substitutos para nomes de dispositivos reais porque esses sistemas de
arquivos de propósito especial não precisam de dispositivos.
2. A palavra em.

3. O ponto de montagem.

4. O tipo de palavra .

5. O tipo de sistema de arquivos, geralmente na forma de um identificador curto.

6. Opções de montagem (entre parênteses). Consulte a Seção 4.2.6 para obter mais detalhes.

Para montar um sistema de arquivos manualmente, use o comando mount da seguinte forma com o tipo
de sistema de arquivos, dispositivo e ponto de montagem desejado:

# mount -t tipo ponto de montagem do dispositivo

Por exemplo, para montar o Fourth Extended filesystem encontrado no dispositivo /dev/ sdf2 em /
home/ extra, use este comando:

# mount -t ext4 /dev/sdf2 /home/extra

Você normalmente não precisa fornecer a opção -t type porque o mount geralmente descobre isso para
você. No entanto, às vezes é necessário distinguir entre dois tipos semelhantes, como os vários sistemas de
arquivos no estilo FAT.
Para desmontar (desanexar) um sistema de arquivos, use o comando umount da seguinte forma:

# umount ponto de montagem

Você também pode desmontar um sistema de arquivos com seu dispositivo em vez de seu ponto de
montagem.

84 Capítulo 4
Machine Translated by Google

OBSERVAÇÃO Quase todos os sistemas Linux incluem um ponto de montagem temporário, / mnt, que normalmente
é usado para teste. Sinta-se à vontade para usá-lo ao experimentar com seu sistema, mas se você
pretende montar um sistema de arquivos para uso prolongado, encontre ou crie outro local.

4.2.4 UUID do sistema de arquivos

O método de montagem de sistemas de arquivos discutido na seção anterior depende dos nomes
dos dispositivos. No entanto, os nomes dos dispositivos podem mudar porque dependem da ordem em
que o kernel encontra os dispositivos. Para resolver esse problema, você pode identificar e montar
sistemas de arquivos por seu identificador universalmente exclusivo (UUID), um padrão da indústria para
“números de série” exclusivos para identificar objetos em um sistema de computador. Programas de
criação de sistema de arquivos como mke2fs
gerar um UUID ao inicializar a estrutura de dados do sistema de arquivos.
Para visualizar uma lista de dispositivos e os sistemas de arquivos e UUIDs correspondentes
em seu sistema, use o programa blkid (block ID):

#blkid _
/dev/sdf2: UUID="b600fe63-d2e9-461c-a5cd-d3b373a5e1d2" TYPE="ext4" /dev/
sda1: UUID="17f12d53-c3d7-4ab3-943e-a0a72366c9fa" TYPE="ext4"
PARTUUID="c9a5ebb0-01"
/dev/sda5: UUID="b600fe63-d2e9-461c-a5cd-d3b373a5e1d2" TYPE="troca"
PARTUUID="c9a5ebb0-05"
/dev/sde1: UUID="4859-EFEA" TYPE="vfat"

Neste exemplo, blkid encontrou quatro partições com dados: duas com ext4
sistemas de arquivos, um com uma assinatura de espaço de troca (consulte a Seção 4.3) e outro
com um sistema de arquivos baseado em FAT. Todas as partições nativas do Linux possuem UUIDs
padrão, mas a partição FAT não. Você pode fazer referência à partição FAT com o número de série do
volume FAT (neste caso, 4859-EFEA).
Para montar um sistema de arquivos por seu UUID, use a opção de montagem UUID . Por
exemplo, para montar o primeiro sistema de arquivos da lista anterior em /home/
extra, digite:

# mount UUID=b600fe63-d2e9-461c-a5cd-d3b373a5e1d2 /home/extra

Normalmente, você não monta sistemas de arquivos manualmente por UUID assim, porque
normalmente conhece o dispositivo e é muito mais fácil montar um dispositivo pelo nome do que
pelo UUID maluco. Ainda assim, é importante entender os UUIDs. Por um lado, eles são a maneira
preferida de montar sistemas de arquivos não-LVM em /etc/ fstab automaticamente no momento da
inicialização (consulte a Seção 4.2.8). Além disso, muitas distribuições usam o UUID como ponto de
montagem quando você insere uma mídia removível. No exemplo anterior, o sistema de arquivos FAT
está em um cartão de mídia flash. Um sistema Ubuntu com alguém logado montará esta partição em /
media/ user/ 4859-EFEA após a inserção. O daemon udevd descrito no Capítulo 3 trata do evento inicial
para a inserção do dispositivo.

Você pode alterar o UUID de um sistema de arquivos, se necessário (por exemplo, se você
copiou o sistema de arquivos completo de outro lugar e agora precisa distingui-lo do original). Veja a
página de manual do tune2fs(8) para saber como fazer isso em um sistema de arquivos ext2/ext3/ext4.

Discos e Sistemas de Arquivos 85


Machine Translated by Google

4.2.5 Buffer de disco, cache e sistemas de arquivos

O Linux, como outras variantes do Unix, armazena em buffer as gravações no disco. Isso significa que o

kernel geralmente não grava alterações imediatamente nos sistemas de arquivos quando os processos
solicitam alterações. Em vez disso, ele armazena essas alterações na RAM até que o kernel determine um
bom momento para gravá-las no disco. Este sistema de buffer é transparente para o usuário e proporciona
um ganho de desempenho muito significativo.

Quando você desmonta um sistema de arquivos com umount, o kernel sincroniza automaticamente
com o disco, gravando as alterações em seu buffer no disco. Você também pode forçar o kernel a fazer isso a
qualquer momento executando o comando sync , que por padrão sincroniza todos os discos no sistema. Se
por algum motivo você não puder desmontar um sistema de arquivos antes de desligar o sistema, certifique-se
de executar a sincronização primeiro.

Além disso, o kernel usa a RAM para armazenar em cache os blocos à medida que são lidos de um disco.
Portanto, se um ou mais processos acessarem repetidamente um arquivo, o kernel não precisará ir para o disco
repetidamente - ele pode simplesmente ler o cache e economizar tempo e recursos.

4.2.6 Opções de montagem do sistema de arquivos

Há muitas maneiras de alterar o comportamento do comando de montagem , o que muitas vezes você
precisará fazer ao trabalhar com mídia removível ou realizar manutenção do sistema. Na verdade, o número total
de opções de montagem é impressionante. A extensa página de manual do mount(8) é uma boa referência, mas
é difícil saber por onde começar e o que você pode ignorar com segurança. Você verá as opções mais úteis nesta
seção.

As opções se dividem em duas categorias aproximadas: gerais e específicas do sistema de arquivos.


As opções gerais normalmente funcionam para todos os tipos de sistema de arquivos e incluem -t para
especificar o tipo de sistema de arquivos, conforme mostrado anteriormente. Em contraste, uma opção
específica do sistema de arquivos pertence apenas a certos tipos de sistema de arquivos.
Para ativar uma opção do sistema de arquivos, use a opção -o seguida pela opção.
Por exemplo, -o remount,rw remonta um sistema de arquivos já montado como somente leitura no modo
leitura-gravação.

Opções gerais curtas

As opções gerais têm uma sintaxe curta. Os mais importantes são:

-r A opção -r monta o sistema de arquivos no modo somente leitura. Isso tem vários usos, desde
proteção contra gravação até bootstrapping. Você não precisa especificar essa opção ao acessar um
dispositivo somente leitura, como um CD-ROM; o sistema fará isso por você (e também informará sobre o
status somente leitura). -n A opção -n assegura que mount não tente atualizar o banco de dados de
montagem de tempo de execução do sistema, /etc/ mtab. Por padrão, a operação de montagem falha

quando não pode gravar neste arquivo, portanto, esta opção é importante no momento da inicialização
porque a partição raiz (incluindo o banco de dados de montagem do sistema) é

86 Capítulo 4
Machine Translated by Google

somente leitura no início. Você também achará essa opção útil ao tentar corrigir um problema do
sistema no modo de usuário único, porque o banco de dados de montagem do sistema pode não
estar disponível no momento.

-t A opção -t type especifica o tipo de sistema de arquivos.

Opções longas

Opções curtas como -r são muito limitadas para o número cada vez maior de opções de montagem ;
há poucas letras no alfabeto para acomodar todas as opções possíveis. As opções curtas também são
problemáticas porque é difícil determinar o significado de uma opção com base em uma única letra. Muitas
opções gerais e todas as opções específicas do sistema de arquivos usam um formato de opção mais longo
e flexível.

Para usar opções longas com mount na linha de comando, comece com -o seguido pelas palavras-
chave apropriadas separadas por vírgulas. Aqui está um exemplo completo, com as opções longas seguindo
-o:

# mount -t vfat /dev/sde1/two -o ro,uid=1000

As duas opções longas aqui são ro e uid=1000. A opção ro especifica o modo somente leitura e é a
mesma que a opção -r short. A opção uid=1000 diz ao kernel para tratar todos os arquivos no sistema de
arquivos como se o ID do usuário 1000 fosse o
proprietário.

As opções longas mais úteis são estas:

exec, noexec Habilita ou desabilita a execução de programas no sistema


de arquivos. suid, nosuid Habilita ou desabilita programas setuid . ro
Monta o sistema de arquivos no modo somente leitura (assim como a
opção -r short).

rw Monta o sistema de arquivos no modo leitura-gravação.

OBSERVAÇÃO Há uma diferença entre arquivos de texto Unix e DOS, principalmente na forma como as linhas terminam.
No Unix, apenas um avanço de linha (\n, ASCII 0x0A) marca o fim de uma linha, mas o DOS usa um
retorno de carro (\r, ASCII 0x0D) seguido por um avanço de linha. Houve muitas tentativas de conversão
automática no nível do sistema de arquivos, mas estas sempre são problemáticas. Editores de texto como o
vim podem detectar automaticamente o estilo de nova linha de um arquivo e mantê-lo adequadamente. É
mais fácil manter os estilos uniformes dessa maneira.

4.2.7 Remontando um sistema de arquivos

Haverá momentos em que você precisará alterar as opções de montagem para um sistema de arquivos
montado atualmente; a situação mais comum é quando você precisa tornar um sistema de arquivos somente
leitura gravável durante a recuperação de falhas. Nesse caso, você precisa reconectar o sistema de arquivos
no mesmo ponto de montagem.

Discos e Sistemas de Arquivos 87


Machine Translated by Google

O comando a seguir remonta o diretório raiz no modo leitura-gravação (você precisa da opção
-n porque o comando mount não pode gravar no banco de dados de montagem do sistema quando a raiz
é somente leitura):

# montar -n -o remontar /

Este comando assume que a lista de dispositivos correta para / está em /etc/ fstab
(como discutido na próxima seção). Se não for, você deve especificar o dispositivo como uma opção
adicional.

4.2.8 A tabela do sistema de arquivos /etc/fstab


Para montar sistemas de arquivos no momento da inicialização e tirar o trabalho penoso da montagem
comando, os sistemas Linux mantêm uma lista permanente de sistemas de arquivos e opções em /etc/
fstab. Este é um arquivo de texto simples em um formato muito simples, como mostra a Listagem 4-1.

UUID=70ccd6e7-6ae6-44f6-812c-51aab8036d29/ext4 errors=remount-ro 0 1
UUID=592dcfd1-58da-4769-9ea8-5f412a896980 nenhum troca sw 0 0
/dev/sr0 /cdrom iso9660 ro,usuário,nosuid,noauto 0 0

Listagem 4-1: Lista de sistemas de arquivos e opções em /etc/fstab

Cada linha corresponde a um sistema de arquivos e é dividida em seis campos.


Da esquerda para a direita, esses campos são:

O dispositivo ou UUID A maioria dos sistemas Linux atuais não usa mais o dispositivo em /etc/
fstab, preferindo o UUID.

O ponto de montagem Indica onde anexar o sistema de arquivos.

O tipo de sistema de arquivos Você pode não reconhecer swap nesta lista; esta é uma partição
swap (veja a Seção 4.3).

Opções Opções longas, separadas por vírgulas.

Informações de backup para uso pelo comando dump O comando dump é um utilitário de
backup há muito obsoleto; este campo não é mais relevante. Você deve sempre configurá-lo para 0.

A ordem do teste de integridade do sistema de arquivos Para garantir que o fsck sempre
seja executado na raiz primeiro, sempre defina como 1 para o sistema de arquivos raiz e 2 para
qualquer outro sistema de arquivos anexado localmente em um disco rígido ou SSD. Use 0 para
desabilitar a verificação de inicialização para todos os outros sistemas de arquivos, incluindo
dispositivos somente leitura, swap e o sistema de arquivos /proc (veja o comando fsck na Seção 4.2.11).

Ao usar mount, você pode usar alguns atalhos se o sistema de arquivos com o qual deseja
trabalhar estiver em /etc/ fstab. Por exemplo, se você estivesse usando a Listagem 4-1 e montando um
CD-ROM, você simplesmente executaria mount /cdrom.
Você também pode tentar montar simultaneamente todas as entradas em /etc/ fstab que
não contém a opção noauto com este comando:

# monte -a

88 Capítulo 4
Machine Translated by Google

A Listagem 4-1 apresenta algumas novas opções—a saber, errors, noauto e user,
porque elas não se aplicam fora do arquivo /etc/ fstab . Além disso, muitas vezes você verá
a opção padrão aqui. Essas opções são definidas da seguinte forma:

padrões Isso define os padrões de montagem : modo de leitura e gravação, habilitar


arquivos de dispositivo, executáveis, o bit setuid e assim por diante. Use isso quando
não quiser dar ao sistema de arquivos nenhuma opção especial, mas quiser preencher
todos os campos em /etc/ fstab. errors Este parâmetro específico do ext2/3/4 define o
comportamento do kernel quando o sistema tem problemas para montar um sistema de
arquivos. O padrão é normalmente errors=continue, o que significa que o kernel deve
retornar um código de erro e continuar rodando. Para que o kernel tente montar novamente
no modo somente leitura, use errors=remount-ro. A configuração errors=panic diz ao kernel
(e ao seu sistema) para parar quando houver um problema com a montagem. noauto Esta
opção diz ao comando mount -a para ignorar a entrada. Use isso para evitar uma
montagem durante a inicialização de um dispositivo de mídia removível, como um
dispositivo de armazenamento flash. user Esta opção permite que usuários sem privilégios
executem mount em uma entrada específica, o que pode ser útil para permitir certos tipos
de acesso a mídias removíveis. Como os usuários podem colocar um arquivo setuid-root
em mídia removível com outro sistema, essa opção também define nosuid, noexec e nodev
(para barrar arquivos de dispositivos especiais). Tenha em mente que para mídia removível
e outros casos gerais, essa opção agora é de uso limitado, porque a maioria dos sistemas
usa ubus junto com outros mecanismos para montar automaticamente a mídia inserida. No
entanto, essa opção pode ser útil em casos especiais quando você deseja conceder
controle sobre a montagem de diretórios específicos.

4.2.9 Alternativas para /etc/fstab

Embora o arquivo /etc/ fstab tenha sido a maneira tradicional de representar sistemas de
arquivos e seus pontos de montagem, existem duas alternativas. O primeiro é um diretório /
etc/ fstab.d , que contém arquivos de configuração de sistemas de arquivos individuais (um
arquivo para cada sistema de arquivos). A ideia é muito semelhante a muitos outros diretórios
de configuração que você verá ao longo deste livro.
Uma segunda alternativa é configurar unidades systemd para os sistemas de arquivos.
Você aprenderá mais sobre systemd e suas unidades no Capítulo 6. No entanto, a configuração
da unidade systemd geralmente é gerada a partir (ou baseada no) arquivo /etc/ fstab , então
você pode encontrar alguma sobreposição em seu sistema.

4.2.10 Capacidade do sistema de arquivos

Para visualizar o tamanho e a utilização de seus sistemas de arquivos atualmente


montados, use o comando df . A saída pode ser muito extensa (e fica cada vez maior, graças
a sistemas de arquivos especializados), mas deve incluir informações sobre seus dispositivos
de armazenamento reais.

Discos e Sistemas de Arquivos 89


Machine Translated by Google

$ df
Sistema de 1K-blocos Usado Disponível Uso% Montado em
arquivos /dev/ 214234312 127989560 75339204 63% /
sda1 /dev/sdd2 3043836 4632 2864872 1% /media/user/uuid

Aqui está uma breve descrição dos campos na saída df :

Sistema de arquivos O dispositivo do sistema de arquivos

1K-blocks A capacidade total do sistema de arquivos em blocos de 1.024 bytes

Usado O número de blocos ocupados


Disponível O número de blocos livres

Use% A porcentagem de blocos em uso

Montado no ponto de montagem

NOTA Se você estiver tendo problemas para encontrar a linha correta na saída df correspondente a um
diretório específico, execute o comando df dir, onde dir é o diretório que você deseja examinar.
Isso limita a saída para o sistema de arquivos para esse diretório. Um uso muito comum é df .,
que limita a saída ao dispositivo que contém seu diretório atual.

Deve ser fácil ver que os dois sistemas de arquivos aqui têm aproximadamente 215 GB
e 3GB de tamanho. No entanto, os números de capacidade podem parecer um pouco
estranhos porque 127.989.560 mais 75.339.204 não é igual a 214.234.312 e 127.989.560
não é 63% de 214.234.312. Em ambos os casos, 5% da capacidade total não é contabilizada. Na
verdade, o espaço está lá, mas está escondido em blocos reservados . Apenas o superusuário
pode usar os blocos reservados do sistema de arquivos quando ele começar a ficar cheio. Esse
recurso evita que os servidores do sistema falhem imediatamente quando ficam sem espaço em
disco.

OBTENDO UMA LISTA DE USO

Se o seu disco ficar cheio e você precisar saber onde estão todos esses arquivos de
mídia que ocupam espaço, use o comando du . Sem argumentos, du imprime o uso do
disco de cada diretório na hierarquia de diretórios, começando no diretório de trabalho
atual. (Essa pode ser uma lista longa; se você quiser ver um exemplo, basta executar cd /;
du para entender. Pressione CTRL-C quando ficar entediado.) O comando du -s ativa o
modo de resumo para imprimir apenas o grande total. Para avaliar tudo (arquivos e
subdiretórios) em um diretório específico, mude para esse diretório e execute du -s *, tendo
em mente que pode haver alguns diretórios dot que este comando não captura.

NOTA O padrão POSIX define um tamanho de bloco de 512 bytes. No entanto, esse tamanho é mais
difícil de ler, portanto, por padrão, a saída df e du na maioria das distribuições Linux está em
blocos de 1.024 bytes. Se você insistir em exibir os números em blocos de 512 bytes, defina o

90 Capítulo 4
Machine Translated by Google

Variável de ambiente POSIXLY_CORRECT . Para especificar explicitamente blocos de 1.024 bytes, use
a opção -k (ambos os utilitários suportam isso). Os programas df e du também têm uma opção -m para
listar capacidades em blocos de 1 MB e uma opção -h para adivinhar o que é mais fácil para uma pessoa
ler, com base nos tamanhos gerais dos sistemas de arquivos.

4.2.11 Verificando e Reparando Sistemas de Arquivos

As otimizações que os sistemas de arquivos Unix oferecem são possibilitadas por um sofisticado
mecanismo de banco de dados. Para que os sistemas de arquivos funcionem perfeitamente, o
kernel precisa confiar que um sistema de arquivos montado não tem erros e também que o
hardware armazena dados de forma confiável. Se existirem erros, podem ocorrer perda de dados e
falhas no sistema.
Além dos problemas de hardware, os erros do sistema de arquivos geralmente são devidos a um
usuário que desliga o sistema de maneira grosseira (por exemplo, puxando o cabo de alimentação).
Nesses casos, o cache do sistema de arquivos anterior na memória pode não corresponder aos dados
no disco, e o sistema também pode estar alterando o sistema de arquivos quando você dá um chute no
computador. Embora muitos sistemas de arquivos suportem journals para tornar a corrupção do sistema
de arquivos muito menos comum, você deve sempre desligar o sistema corretamente. Independentemente
do sistema de arquivos em uso, as verificações do sistema de arquivos ainda são necessárias de vez em
quando para garantir que tudo ainda esteja em ordem.

A ferramenta para verificar um sistema de arquivos é o fsck. Assim como no programa mkfs , há
uma versão diferente do fsck para cada tipo de sistema de arquivos que o Linux suporta. Por exemplo,
quando executado em uma série de sistemas de arquivos estendidos (ext2/ext3/ext4), fsck
reconhece o tipo de sistema de arquivos e inicia o utilitário e2fsck . Portanto, você geralmente não
precisa digitar e2fsck, a menos que o fsck não consiga descobrir o tipo do sistema de arquivos ou
você esteja procurando a página de manual do e2fsck .
As informações apresentadas nesta seção são específicas para a série Extended filesystem e
e2fsck.
Para executar o fsck no modo manual interativo, forneça ao dispositivo ou à montagem
point (conforme listado em /etc/ fstab) como argumento. Por exemplo:

# fsck /dev/sdb1

AVISO Nunca use fsck em um sistema de arquivos montado—o kernel pode alterar os dados do disco enquanto você
executa a verificação, causando incompatibilidades de tempo de execução que podem travar seu
sistema e corromper arquivos. Há apenas uma exceção: se você montar a partição raiz somente leitura
no modo de usuário único, poderá usar fsck nela.

No modo manual, o fsck imprime relatórios de status detalhados em suas passagens, que
deve ficar assim quando não houver problemas:

Passo 1: Verificando inodes, blocos e tamanhos


Passo 2: Verificando a estrutura do diretório
Passo 3: Verificando a conectividade do diretório
Passo 4: Verificando contagens de referência
Passo 5: Verificando as informações do resumo do grupo
/dev/sdb1: arquivos 11/1976 (0,0% não contíguos), 265/7891 blocos

Discos e Sistemas de Arquivos 91


Machine Translated by Google

Se o fsck encontrar um problema no modo manual, ele parará e fará uma pergunta
relevante para corrigir o problema. Essas questões lidam com a estrutura interna do sistema
de arquivos, como reconectar inodes soltos e limpar blocos (inodes são blocos de construção do
sistema de arquivos; você verá como eles funcionam na Seção 4.6). Quando o fsck pergunta sobre
a reconexão de um inode, ele encontrou um arquivo que parece não ter um nome. Ao reconectar
tal arquivo, o fsck coloca o arquivo no diretório lost+found do sistema de arquivos, com um número
como nome do arquivo. Se isso acontecer, você precisa adivinhar o nome com base no conteúdo
do arquivo; o nome do arquivo original provavelmente desapareceu.

Em geral, é inútil passar pelo processo de reparo do fsck se você acabou de desligar o
sistema de forma inadequada, porque o fsck pode ter muitos erros menores para corrigir.
Felizmente, o e2fsck tem uma opção -p que corrige automaticamente problemas comuns sem
perguntar e aborta quando há um erro grave.
Na verdade, as distribuições Linux executam uma variante de fsck -p no momento da inicialização.
(Você também pode ver fsck -a, que faz a mesma coisa.)
Se você suspeitar de um grande desastre em seu sistema, como uma falha de hardware ou
configuração incorreta do dispositivo, você precisa decidir sobre um curso de ação, porque o fsck
pode realmente atrapalhar um sistema de arquivos com problemas maiores. (Um sinal revelador
de que seu sistema tem um problema sério é se o fsck fizer muitas perguntas no modo manual.)

Se você acha que algo muito ruim aconteceu, tente executar fsck -n
para verificar o sistema de arquivos sem modificar nada. Se houver um problema com a configuração
do dispositivo que você acha que pode corrigir (como cabos soltos ou um número incorreto de
blocos na tabela de partições), corrija-o antes de executar o fsck de verdade, ou é provável que
você perca muitos dados .
Se você suspeitar que apenas o superblock está corrompido (por exemplo, porque alguém
gravou no início da partição do disco), você poderá recuperar o sistema de arquivos com um dos
backups de superblock que o mkfs cria.
Use fsck -b num para substituir o superbloco corrompido por um alternativo no bloco num e
espere pelo melhor.
Se você não souber onde encontrar um superblock de backup, poderá executar mkfs -n no
dispositivo para visualizar uma lista de números de backup de superblock sem destruir seus dados.
(Mais uma vez, certifique-se de estar usando -n, ou você realmente destruirá o sistema de arquivos.)

Verificando os sistemas de arquivos

ext3 e ext4 Normalmente, você não precisa verificar os sistemas de arquivos ext3 e ext4
manualmente porque o journal garante a integridade dos dados (lembre-se de que o journal é um
pequeno cache de dados que ainda não foi gravado em um ponto específico do sistema de arquivos).
Se você não desligar o sistema corretamente, pode esperar que o diário contenha alguns
dados. Para liberar o diário em um sistema de arquivos ext3 ou ext4 para o banco de dados regular
do sistema de arquivos, execute e2fsck da seguinte forma:

# e2fsck –fy /dev/ disk_device

No entanto, você pode querer montar um sistema de arquivos ext3 ou ext4 quebrado no
modo ext2, porque o kernel não montará um sistema de arquivos ext3 ou ext4 com um diário não
vazio.

92 Capítulo 4
Machine Translated by Google

O pior caso

Problemas de disco mais graves deixam você com poucas opções:

•Você pode tentar extrair toda a imagem do sistema de arquivos do disco com dd
e transferi-lo para uma partição em outro disco do mesmo tamanho. •Você
pode tentar corrigir o sistema de arquivos o máximo possível, montá-lo em modo somente
leitura e salvar o que puder.
•Você pode tentar debugfs.

Nos dois primeiros casos, você ainda precisa reparar o sistema de arquivos antes de
montá-lo, a menos que queira selecionar os dados brutos manualmente. Se desejar, você pode
optar por responder y a todas as perguntas do fsck digitando fsck -y, mas faça isso como último
recurso, pois podem surgir problemas durante o processo de reparo que você preferiria tratar
manualmente.
A ferramenta debugfs permite examinar os arquivos em um sistema de arquivos e copiá-
los em outro lugar. Por padrão, ele abre sistemas de arquivos em modo somente leitura. Se
você estiver recuperando dados, provavelmente é uma boa ideia manter seus arquivos intactos
para evitar bagunçar ainda mais as coisas.
Agora, se você está realmente desesperado – digamos, com uma falha catastrófica de
disco em suas mãos e sem backups – não há muito que você possa fazer além de esperar que
um serviço profissional possa “raspar os pratos”.

4.2.12 Sistemas de Arquivos de Propósito Especial

Nem todos os sistemas de arquivos representam armazenamento em mídia física. A maioria


das versões do Unix tem sistemas de arquivos que servem como interfaces de sistema. Ou
seja, em vez de servir apenas como meio de armazenar dados em um dispositivo, um sistema
de arquivos pode representar informações do sistema, como IDs de processos e diagnósticos
do kernel. Essa ideia remonta ao mecanismo /dev , que é um modelo inicial de uso de arquivos
para interfaces de E/S. A ideia do /proc veio da oitava edição da pesquisa Unix, implementada
por Tom J. Killian e acelerada quando a Bell Labs (incluindo muitos dos designers originais do
Unix) criou o Plano 9—
um sistema operacional de pesquisa que levou a abstração do sistema de arquivos a um
nível totalmente novo (https:// en.wikipedia.org/ wiki/ Plan_9_from_Bell_Labs).
Alguns dos tipos especiais de sistema de arquivos em uso comum no Linux incluem:

proc Montado em /proc. O nome proc é uma abreviação de processo.


Cada diretório numerado dentro de /proc refere-se ao ID de um processo atual no
sistema; os arquivos em cada diretório representam vários aspectos desse processo. O
diretório /proc/ self representa o processo atual.
O sistema de arquivos proc do Linux inclui uma grande quantidade de informações
adicionais de kernel e hardware em arquivos como /proc/ cpuinfo. Tenha em mente que as
diretrizes de design do kernel recomendam mover informações não relacionadas a
processos de /proc para /sys, portanto, as informações do sistema em /proc podem não
ser a interface mais atual.

sysfs Montado em /sys. (Você viu isso no Capítulo 3.)


tmpfs Montado em /run e outros locais. Com o tmpfs, você pode usar sua memória
física e trocar o espaço como armazenamento temporário. Você pode

Discos e Sistemas de Arquivos 93


Machine Translated by Google

monte tmpfs onde quiser, usando as opções size e nr_blocks long para controlar o tamanho
máximo. No entanto, tome cuidado para não colocar coisas constantemente em um local
tmpfs , porque seu sistema acabará ficando sem memória e os programas começarão a
travar.
squashfs Um tipo de sistema de arquivos somente leitura em que o conteúdo é
armazenado em um formato compactado e extraído sob demanda por meio de um
dispositivo de loopback. Um exemplo de uso é no sistema de gerenciamento de pacotes
snap que monta pacotes no diretório /snap .
overlay Um sistema de arquivos que mescla diretórios em um composto.
Os contêineres geralmente usam sistemas de arquivos de sobreposição; você verá como eles funcionam
no Capítulo 17.

4.3 Espaço de Troca

Nem toda partição em um disco contém um sistema de arquivos. Também é possível aumentar
a RAM em uma máquina com espaço em disco. Se você ficar sem memória real, o sistema de
memória virtual do Linux pode mover automaticamente pedaços de memória para e do
armazenamento em disco. Isso é chamado de troca porque partes de programas ociosos são
trocadas para o disco em troca de partes ativas que residem no disco. A área do disco usada
para armazenar as páginas de memória é chamada de espaço de troca (ou apenas troca).

A saída do comando free inclui o uso de swap atual em kilo bytes da seguinte forma:

$ grátis
total usado gratuitamente

--recorte--
Troca: 514072 189804 324268

4.3.1 Usando uma partição de disco como espaço de troca

Para usar uma partição de disco inteira como swap, siga estas etapas:

1. Certifique-se de que a partição esteja vazia.


2. Execute mkswap dev, onde dev é o dispositivo da partição. Este comando coloca uma
assinatura de troca na partição, marcando-a como espaço de troca (em vez de um sistema
de arquivos ou outro).
3. Execute swapon dev para registrar o espaço com o kernel.

Depois de criar uma partição de troca, você pode colocar uma nova entrada de troca
em seu arquivo /etc/ fstab para fazer o sistema usar o espaço de troca assim que a máquina
inicializar. Aqui está uma entrada de exemplo que usa /dev/ sda5 como uma partição swap:

/dev/sda5 nenhum troca sw 0 0

94 Capítulo 4
Machine Translated by Google

As assinaturas de troca têm UUIDs, portanto, lembre-se de que muitos sistemas agora
os usam em vez de nomes de dispositivos brutos.

4.3.2 Usando um arquivo como espaço de troca

Você pode usar um arquivo comum como espaço de troca se estiver em uma situação em
que seria forçado a reparticionar um disco para criar uma partição de troca.
Você não deve notar nenhum problema ao fazer isso.
Use estes comandos para criar um arquivo vazio, inicializá-lo como swap e adicioná-lo
ao pool de swap:

# dd if=/dev/zero of=swap_file bs=1024k contagem=num_mb


# mkswap swap_file
# swapon swap_file

Aqui, swap_file é o nome do novo arquivo de swap e num_mb é o tamanho


desejado em megabytes.
Para remover uma partição ou arquivo de troca do pool ativo do kernel, use o comando
swapoff . Seu sistema deve ter memória restante livre suficiente (real e swap combinados) para
acomodar quaisquer páginas ativas na parte do pool de swap que você está removendo.

4.3.3 Determinando a quantidade de swap necessária

Ao mesmo tempo, a sabedoria convencional do Unix dizia que você deveria sempre reservar
pelo menos duas vezes mais espaço de troca do que a memória real. Hoje, não apenas as
enormes capacidades de disco e memória disponíveis obscurecem o problema, mas também
a forma como usamos o sistema. Por um lado, o espaço em disco é tão abundante que é
tentador alocar mais que o dobro do tamanho da memória. Por outro lado, você pode nunca
mergulhar no seu espaço de troca porque tem muita memória real.

A regra de “duplicar a memória real” datava de uma época em que vários usuários
estavam conectados a uma máquina. No entanto, nem todos eles estariam ativos, então era
conveniente poder trocar a memória dos usuários inativos quando um usuário ativo precisava
de mais memória.
O mesmo ainda pode valer para uma máquina de usuário único. Se você estiver
executando muitos processos, geralmente não há problema em trocar partes de processos
inativos ou até mesmo partes inativas de processos ativos. No entanto, se você acessa
frequentemente o espaço de troca porque muitos processos ativos querem usar a memória de
uma só vez, você sofrerá sérios problemas de desempenho porque a E/S de disco (mesmo a
de SSDs) é muito lenta para acompanhar o resto do sistema. As únicas soluções são comprar
mais memória, encerrar alguns processos ou reclamar.
Às vezes, o kernel do Linux pode optar por trocar um processo em favor
de um pouco mais de cache de disco. Para evitar esse comportamento, alguns
administradores configuram determinados sistemas sem nenhum espaço de troca. Por
exemplo, servidores de alto desempenho nunca devem mergulhar no espaço de troca e
devem evitar o acesso ao disco, se possível.

Discos e Sistemas de Arquivos 95


Machine Translated by Google

OBSERVAÇÃO É perigoso configurar nenhum espaço de troca em uma máquina de uso geral. Se uma
máquina ficar completamente sem memória real e espaço de troca, o kernel do Linux invoca o
assassino de falta de memória (OOM) para matar um processo a fim de liberar alguma memória.
Você obviamente não quer que isso aconteça com seus aplicativos de desktop. Por outro lado, os
servidores de alto desempenho incluem sistemas sofisticados de monitoramento, redundância e
balanceamento de carga para garantir que nunca cheguem à zona de perigo.

Você aprenderá muito mais sobre como o sistema de memória funciona no Capítulo 8.

4.4 O Gerenciador de Volume Lógico


Até agora, analisamos o gerenciamento direto e o uso de discos por meio de partições,
especificando os locais exatos em dispositivos de armazenamento onde determinados
dados devem residir. Você sabe que acessar um dispositivo de bloco como /dev/ sda1
leva você a um local em um dispositivo específico de acordo com a tabela de partições
em /dev/ sda, mesmo que a localização exata possa ser deixada para o hardware.
Isso geralmente funciona bem, mas tem algumas desvantagens, especialmente
quando se trata de fazer alterações em seus discos após a instalação. Por exemplo, se
você deseja atualizar um disco, você deve instalar o novo disco, partição, adicionar sistemas
de arquivos, possivelmente fazer algumas alterações no carregador de inicialização e outras
tarefas e, finalmente, mudar para o novo disco. Esse processo pode ser propenso a erros e
requer várias reinicializações. Talvez seja pior quando você deseja instalar um disco
adicional para obter mais capacidade - aqui, você precisa escolher um novo ponto de
montagem para o sistema de arquivos nesse disco e esperar que possa distribuir
manualmente seus dados entre os discos antigos e novos.
O LVM lida com esses problemas adicionando outra camada entre os dispositivos
do bloco físico e o sistema de arquivos. A ideia é que você selecione um conjunto de
volumes físicos (geralmente apenas dispositivos de bloco, como partições de disco) para
incluir em um grupo de volumes, que atua como uma espécie de pool de dados genérico.
Em seguida, você separa os volumes lógicos do grupo de volumes.
A Figura 4-4 mostra um esquema de como eles se encaixam em um grupo de
volumes. Esta figura mostra vários volumes físicos e lógicos, mas muitos sistemas
baseados em LVM têm apenas um PV e apenas dois volumes lógicos (para root e swap).

Volume lógico Volume lógico

Grupo de volumes

Volume físico Volume físico

Figura 4-4: Como PVs e volumes lógicos se encaixam em um grupo de volumes

96 Capítulo 4
Machine Translated by Google

Os volumes lógicos são apenas dispositivos de bloco e normalmente contêm sistemas de


arquivos ou assinaturas de troca, para que você possa pensar no relacionamento entre um grupo
de volumes e seus volumes lógicos como semelhante ao de um disco e suas partições. A diferença
crítica é que você normalmente não define como os volumes lógicos são dispostos no grupo de
volumes — o LVM resolve tudo isso.
O LVM permite algumas operações poderosas e extremamente úteis, como:

•Adicione mais PVs (como outro disco) a um grupo de volumes, aumentando seu tamanho.

•Remova PVs enquanto houver espaço suficiente restante para acomodar volumes lógicos
existentes dentro de um grupo de volumes.

•Redimensione volumes lógicos (e, como consequência, redimensione sistemas de arquivos com
o utilitário fsadm ).

Você pode fazer tudo isso sem reiniciar a máquina e, na maioria dos casos,
sem desmontar nenhum sistema de arquivos. Embora a adição de um novo hardware de disco
físico possa exigir um desligamento, os ambientes de computação em nuvem geralmente permitem
adicionar novos dispositivos de armazenamento em bloco em tempo real, tornando o LVM uma
excelente opção para sistemas que precisam desse tipo de flexibilidade.
Vamos explorar o LVM com uma quantidade moderada de detalhes. Primeiro, veremos
como interagir e manipular volumes lógicos e seus componentes e, em seguida, examinaremos
mais de perto como o LVM funciona e o driver do kernel no qual ele é construído. No entanto, a
discussão aqui não é essencial para entender o resto do livro; portanto, se você ficar muito atolado,
sinta-se à vontade para pular para o Capítulo 5.

4.4.2 Trabalhando com LVM


O LVM possui várias ferramentas de espaço do usuário para gerenciar volumes e grupos de
volumes. A maioria deles é baseada no comando lvm , uma ferramenta interativa de uso geral.
Existem comandos individuais (que são apenas links simbólicos para o LVM) para realizar tarefas
específicas. Por exemplo, o comando vgs tem o mesmo efeito que digitar vgs no prompt lvm> da
ferramenta interativa lvm , e você descobrirá que vgs (geralmente em /sbin) é um link simbólico para
lvm.
Usaremos os comandos individuais neste livro.
Nas próximas seções, veremos os componentes de um sistema que
usa volumes lógicos. Os primeiros exemplos vêm de uma instalação padrão do Ubuntu usando
a opção de particionamento LVM, então muitos dos nomes conterão a palavra Ubuntu. No entanto,
nenhum dos detalhes técnicos é específico dessa distribuição.

Listando e Entendendo os Grupos de Volumes

O comando vgs mencionado mostra os grupos de volumes atualmente configurados no sistema.


A saída é bastante concisa. Aqui está o que você pode ver em nosso exemplo de instalação do
LVM:

# vgs
VG #PV #LV #SN Attr VSize VFree
free-vg 1 2 0 wz - n- <10,00g 36,00m

Discos e Sistemas de Arquivos 97


Machine Translated by Google

A primeira linha é um cabeçalho, com cada linha sucessiva representando um grupo de


volumes. As colunas são as seguintes:

VG O nome do grupo de volumes. ubuntu-vg é o nome genérico que o instalador do


Ubuntu atribui ao configurar um sistema com LVM.
#PV O número de volumes físicos que o armazenamento do grupo de volumes compreende.

#LV O número de volumes lógicos dentro do grupo de volumes.


#SN O número de capturas instantâneas de volume lógico . Não entraremos em detalhes
sobre estes.

Attr Vários atributos de status do grupo de volumes. Aqui, w (gravável), z (redimensionável)


e n (política de alocação normal) estão ativos.
VSize O tamanho do grupo de volumes.
VFree A quantidade de espaço não alocado no grupo de volumes.

Esta sinopse de um grupo de volumes é suficiente para a maioria dos propósitos. Se você
quiser se aprofundar um pouco mais em um grupo de volumes, use o comando vgdisplay , que é
muito útil para entender as propriedades de um grupo de volumes. Aqui está o mesmo grupo de
volumes com vgdisplay:

#vgdisplay _
--- Grupo de volumes ---
Nome VG free-vg
ID do sistema
Formato lvm2
Áreas de metadados 1
Sequência de Metadados Nº 3
Acesso VG ler escrever
Status VG redimensionável
LV MÁX. 0
Cur LV 2
Abrir LV 2
PV máximo 0
Cur PV 1
Ato PV 1
Tamanho VG <10,00 GiB
Tamanho PE 4,00 MiB
PE Total 2559
Alocação PE/Tamanho 2550 / 9,96 GiB
PE/tamanho grátis 9 / 36,00 MiB
VG UUID 0zs0TV-wnT5-laOy-vJ0h-rUae-YPdv-pPwaAs

Você já viu um pouco disso antes, mas há alguns novos itens dignos de nota:

Open LV O número de volumes lógicos atualmente em uso.


Cur PV O número de volumes físicos que o grupo de volumes compreende.
Act LV O número de volumes físicos ativos no grupo de volumes.
VG UUID O identificador universalmente exclusivo do grupo de volumes. É possível ter mais
de um grupo de volumes com o mesmo nome em um sistema; neste caso, o UUID pode
ajudá-lo a isolar um determinado. A maioria

98 Capítulo 4
Machine Translated by Google

As ferramentas LVM (como vgrename, que podem ajudá-lo a resolver uma situação
como essa) aceitam o UUID como uma alternativa ao nome do grupo de volumes.
Esteja avisado de que você está prestes a ver muitos UUIDs diferentes; cada
componente do LVM tem um.

Uma extensão física (abreviada como PE na saída vgdisplay ) é um pedaço de


um volume físico, muito parecido com um bloco, mas em uma escala muito maior.
Neste exemplo, o tamanho do PE é 4 MB. Você pode ver que a maioria dos PEs neste
grupo de volumes está em uso, mas isso não é motivo de alarme. Esta é apenas a
quantidade de espaço no grupo de volumes alocado para as partições lógicas (neste
caso, um sistema de arquivos e espaço de troca); ele não reflete o uso real dentro do
sistema de arquivos.

Como listar volumes lógicos

Semelhante aos grupos de volume, os comandos para listar volumes lógicos são lvs para
uma lista curta e lvdisplay para mais detalhes. Aqui está uma amostra de lvs:

#lv _
LV VG Atr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root ubuntu-vg -wi-ao---- <9.01g
swap_1 ubuntu-vg -wi-ao---- 976.00m

Em configurações básicas de LVM, apenas as primeiras quatro colunas são importantes


para entender, e as colunas restantes podem estar vazias, como é o caso aqui (não
abordaremos isso). As colunas relevantes aqui são:

LV O nome do volume lógico.


VG O grupo de volumes onde reside o volume lógico.
Attr Atributos do volume lógico. Aqui, eles são w (graváveis), i
(política de alocação herdada), a (ativo) e o (aberto). Em configurações de grupo de
volumes mais avançadas, mais desses slots estão ativos — em particular, o primeiro, o
sétimo e o nono.

LSize O tamanho do volume lógico.

Executar o lvdisplay mais detalhado ajuda a esclarecer onde um volume lógico se


encaixa em seu sistema. Aqui está a saída para um de nossos volumes lógicos:

# lvdisplay /dev/ubuntu-vg/root
--- Volume lógico ---
Caminho LV /dev/ubuntu-vg/root
Nome LV raiz
Nome VG free-vg
LV UUID CELZaz-PWr3-tr3z-dA3P-syC7-KWsT-4YiUW2
Acesso de gravação LV ler escrever
Host de criação do LV, horário Ubuntu, 13/11/2018 15:48:20 -0500
Status LV disponível
# abrir 1
Tamanho LV <9,01 GiB
LE atual 2306

Discos e Sistemas de Arquivos 99


Machine Translated by Google

Segmentos 1
Alocação você herda
Setores de leitura antecipada auto
- atualmente configurados para 256
Bloquear dispositivo 253:0

Há muitas coisas interessantes aqui, e a maioria é bastante auto-explicativa (observe


que o UUID do volume lógico é diferente daquele de seu grupo de volumes). Talvez a coisa mais
importante que você ainda não viu seja primeiro: LV Path, o caminho do dispositivo do volume
lógico. Alguns sistemas, mas não todos, usam isso como ponto de montagem do sistema de
arquivos ou espaço de troca (em uma unidade de montagem systemd ou /etc/ fstab).

Mesmo que você possa ver os números de dispositivos principais e secundários do


dispositivo de bloco do volume lógico (aqui, 253 e 0), bem como algo que parece um caminho
de dispositivo, não é realmente o caminho que o kernel usa. Uma rápida olhada em /dev/ ubuntu-
vg/ root revela que algo mais está acontecendo:

$ ls -l /dev/ubuntu-vg/root
lrwxrwxrwx 1 root root 7 Nov 14 06:58 /dev/ubuntu-vg/root -> ../dm-0

Como você pode ver, este é apenas um link simbólico para /dev/ dm-0. Vejamos isso
brevemente.

Usando dispositivos de volume lógico

Uma vez que o LVM tenha feito seu trabalho de configuração em seu sistema, os dispositivos
de bloco de volume lógico estão disponíveis em /dev/ dm-0, / dev/ dm-1 e assim por diante, e podem
ser organizados em qualquer ordem. Devido à imprevisibilidade desses nomes de dispositivos, o
LVM também cria links simbólicos para os dispositivos que possuem nomes estáveis com base no
grupo de volumes e nomes de volumes lógicos. Você viu isso na seção anterior com /dev/ ubuntu-
vg/ root.
Há um local adicional para links simbólicos na maioria das implementações: /dev/ mapper.
O formato do nome aqui também é baseado no grupo de volumes e no volume lógico, mas não
há hierarquia de diretórios; em vez disso, os links têm nomes como ubuntu--vg-root. Aqui, o udev
transformou o traço único no grupo de volumes em um traço duplo e, em seguida, separou o
grupo de volumes e os nomes dos volumes lógicos com um único traço.

Muitos sistemas usam os links em /dev/ mapper em suas configurações /etc/ fstab,
systemd e carregador de inicialização para apontar o sistema para os volumes lógicos usados
para sistemas de arquivos e espaço de troca.
De qualquer forma, esses links simbólicos apontam para dispositivos de bloco para os
volumes lógicos e você pode interagir com eles como faria com qualquer outro dispositivo de
bloco: criar sistemas de arquivos, criar partições de troca e assim por diante.

NOTA Se você der uma olhada em / dev/mapper, você também verá um arquivo chamado control. Você
pode estar se perguntando sobre esse arquivo, bem como por que os arquivos de dispositivo de
bloco reais começam com dm-; isso coincide com / dev/mapper de alguma forma? Abordaremos
essas questões no final deste capítulo.

100 Capítulo 4
Machine Translated by Google

Trabalhando com Volumes Físicos

A última peça principal do LVM a ser examinada é o volume físico (PV). Um grupo de volume é
construído a partir de um ou mais PVs. Embora um PV possa parecer uma parte direta do
sistema LVM, ele contém um pouco mais de informação do que aparenta. Assim como grupos
de volumes e volumes lógicos, os comandos LVM para visualizar PVs são pvs (para uma lista
curta) e pvdisplay (para uma visualização mais detalhada). Aqui está a exibição de pvs para nosso
sistema de exemplo:

# pv
fotovoltaica VG Fmt Attr PSize PFree
/dev/sda1 ubuntu-vg lvm2 a-- <10,00g 36,00m

E aqui está pvdisplay:

#pvdisplay _
--- Volume físico ---
Nome do /dev/sda1
Nome VGPV free-vg
Tamanho PV <10,00 GiB / não utilizável 2,00 MiB
Alocável sim
Tamanho PE 4,00MiB
PE Total 2559
PE grátis 9
PE alocado 2550
PV UUID v2Qb1A-XC2e-2G4l-NdgJ-lnan-rjm5-47eMe5

Da discussão anterior sobre grupos de volumes e volumes lógicos,


você deve entender a maior parte dessa saída. Aqui estão algumas notas:

•Não há nenhum nome especial para o PV além do dispositivo de bloco. Não há necessidade de um
— todos os nomes necessários para fazer referência a um volume lógico estão no nível do
grupo de volumes e acima. No entanto, o PV possui um UUID, que é necessário para compor
um grupo de volumes.

•Neste caso, o número de PEs corresponde ao uso no grupo de volumes (que vimos anteriormente),
pois este é o único PV do grupo.

•Há uma pequena quantidade de espaço que o LVM rotula como não utilizável porque não é
suficiente para preencher um PE completo.

•O a nos atributos da saída pvs corresponde a Alocável na saída pvdisplay , e significa


simplesmente que se você deseja alocar espaço para um volume lógico no grupo de
volumes, o LVM pode optar por usar este PV. No entanto, neste caso, existem apenas nove
PEs não alocados (um total de 36 MB), portanto, não há muito disponível para novos volumes
lógicos.

Conforme mencionado anteriormente, os PVs contêm mais do que apenas informações


sobre sua própria contribuição individual para um grupo de volumes. Cada PV contém
metadados de volume físico, informações extensas sobre seu grupo de volumes e seus volumes
lógicos. Vamos explorar os metadados de PV em breve, mas primeiro vamos ter alguma
experiência prática para ver como o que aprendemos se encaixa.

Discos e Sistemas de Arquivos 101


Machine Translated by Google

Construindo um sistema de volume lógico

Vejamos um exemplo de como criar um novo grupo de volumes e alguns volumes lógicos de
dois dispositivos de disco. Combinaremos dois dispositivos de disco de 5 GB e 15 GB em um
grupo de volumes e, em seguida, dividiremos esse espaço em dois volumes lógicos de 10 GB
cada – uma tarefa quase impossível sem LVM. O exemplo mostrado aqui usa discos do VirtualBox.
Embora as capacidades sejam bastante pequenas em qualquer sistema contemporâneo, elas são
suficientes para ilustração.
A Figura 4-5 mostra o esquema de volume. Os novos discos estão em /dev/ sdb
e /dev/ sdc, o novo grupo de volumes será chamado myvg e os dois novos volumes lógicos
serão chamados mylv1 e mylv2.

Volume lógico: Volume lógico:


mylv1 8(10GB) mylv2 8 (10 GB)

Grupo de volume: myvg

Volume físico: Volume físico:


/dev/sdb1 (5 GB) /dev/sdc1 (15 GB)

Figura 4-5: Construindo um sistema de volume lógico

A primeira tarefa é criar uma única partição em cada um desses discos e rotulá-la para LVM.
Faça isso com um programa de particionamento (consulte a Seção 4.1.2), usando o tipo de
partição ID 8e, para que as tabelas de partição fiquem assim:

# parte /dev/sdb print


Modelo: ATA VBOX HARDDISK (scsi)
Disco /dev/sdb: 5616 MB
Tamanho do setor (lógico/físico): 512B/512B
Tabela de partição: msdos
Sinalizadores de disco:

Número Início Fim Tamanho


Digite Sinalizadores do sistema de arquivos
1 1049kB 5616MB 5615MB primário # lvm
parted /dev/sdc print
Modelo: ATA VBOX HARDDISK (scsi)
Disco /dev/sdc: 16,0 GB
Tamanho do setor (lógico/físico): 512B/512B
Tabela de partição: msdos
Sinalizadores de disco:

Número Início Fim Tamanho


Tipo Sinalizadores do sistema de arquivos
1 1049kB 16.0GB 16.0GB primário lvm

102 Capítulo 4
Machine Translated by Google

Você não precisa necessariamente particionar um disco para torná-lo um PV. PVs podem
ser qualquer dispositivo de bloco, mesmo dispositivos de disco inteiro, como /dev/ sdb. No entanto,
o particionamento permite a inicialização a partir do disco e também fornece um meio de identificar os
dispositivos de bloco como volumes físicos LVM.

Criando Volumes Físicos e um Grupo de Volumes

Com as novas partições de /dev/ sdb1 e /dev/ sdc1 em mãos, o primeiro passo com o LVM é designar uma
das partições como um PV e atribuí-la a um novo grupo de volumes. Um único comando, vgcreate, executa
essa tarefa. Veja como criar um grupo de volumes chamado myvg com /dev/ sdb1 como o PV inicial:

# vgcria meuvg /dev/sdb1


Volume físico "/dev/sdb1" criado com sucesso.
Grupo de volume "myvg" criado com sucesso

OBSERVAÇÃO Você também pode criar um PV primeiro em uma etapa separada com o comando pvcreate .
No entanto, vgcreate executa esta etapa em uma partição se nada estiver presente no momento.

Nesse ponto, a maioria dos sistemas detecta automaticamente o novo grupo de volumes;
execute um comando como vgs para verificar (lembrando que pode haver grupos de volumes
existentes em seu sistema que apareçam além do que você acabou de criar):

# vgs
VG #PV #LV #SN Attr VSize VFree
myvg 1 0 0 wz--n- <5,23g <5,23g

OBSERVAÇÃO Se você não vir o novo grupo de volumes, tente executar o pvscan primeiro. Se o seu sistema não
detectar automaticamente as alterações no LVM, você precisará executar o pvscan toda vez que fizer uma
alteração.

Agora você pode adicionar seu segundo PV em /dev/ sdc1 ao grupo de volumes com o comando
vgextend :

# vgextend meuvg /dev/sdc1


Volume físico "/dev/sdc1" criado com sucesso.
Grupo de volume "myvg" estendido com sucesso

A execução de vgs agora mostra dois PVs, e o tamanho é o das duas partições combinadas:

# vgs
VG #PV #LV #SN Attr VSize VFree
meu-vg 2 0 0 wz--n- <20,16g <20,16g

Discos e Sistemas de Arquivos 103


Machine Translated by Google

Criando Volumes Lógicos

A etapa final no nível do dispositivo de bloco é criar os volumes lógicos. Como mencionado
anteriormente, vamos criar dois volumes lógicos de 10 GB cada, mas sinta-se à vontade
para experimentar outras possibilidades, como um grande volume lógico ou vários menores.

O comando lvcreate aloca um novo volume lógico em um grupo de volumes. As


únicas complexidades reais na criação de volumes lógicos simples são determinar os
tamanhos quando há mais de um por grupo de volumes e especificar o tipo de volume
lógico. Lembre-se de que os PVs são divididos em extensões; o número de PEs disponíveis
pode não corresponder ao tamanho desejado. No entanto, ele deve estar próximo o suficiente
para que não apresente uma preocupação, portanto, se esta é sua primeira vez trabalhando
com o LVM, você não precisa prestar atenção aos PEs.

Ao usar lvcreate, você pode especificar o tamanho de um volume lógico por números
capacidade em bytes com a opção --size ou por número de PEs com a opção --
extents .
Então, para ver como isso funciona e para completar o esquema do LVM na
Figura 4-5, vamos criar volumes lógicos chamados mylv1 e mylv2 usando --size:

# lvcreate --size 10g --type linear -n mylv1 myvg


Volume lógico "mylv1" criado.
# lvcreate --size 10g --type linear -n mylv2 myvg
Volume lógico "mylv2" criado.

O tipo aqui é o mapeamento linear, o tipo mais simples quando você não
precisam de redundância ou quaisquer outros recursos especiais (não trabalharemos
com nenhum outro tipo neste livro). Nesse caso, --type linear é opcional porque é o
mapeamento padrão.
Depois de executar esses comandos, verifique se os volumes lógicos existem com
um comando lvs e observe mais de perto o estado atual do grupo de volumes com vgdisplay:

#vgdisplay myvg
--- Grupo de volumes ---
Nome VG myvg
ID do sistema
Formato lvm2
Áreas de metadados 2

Sequência de Metadados Nº 4
Acesso VG ler escrever
Status VG redimensionável
LV MÁX. 0
Cur LV 2

Abrir LV 0
PV máximo 0
Cur PV 2
Ato PV 2
Tamanho VG 20,16 GiB
Tamanho PE 4,00 MiB
PE Total 5162
Alocação PE/Tamanho 5120 / 20,00 GiB

104 Capítulo 4
Machine Translated by Google

PE/tamanho grátis 42 / 168,00 MiB


VG UUID 1pHrOe-e5zy-TUtK-5gnN-SpDY-shM8-Cbokf3

Observe como existem 42 PEs livres porque os tamanhos que escolhemos para os volumes
lógicos não ocupam todas as extensões disponíveis no grupo de volumes.

Manipulando Volumes Lógicos: Criando Partições

Com os novos volumes lógicos disponíveis, agora você pode usá-los colocando sistemas de
arquivos nos dispositivos e montando-os como qualquer partição de disco normal. Como mencionado
anteriormente, haverá links simbólicos para os dispositivos em /dev/ mapper e (neste caso) um
diretório / dev/ myvg para o grupo de volumes. Assim, por exemplo, você pode executar os três
comandos a seguir para criar um sistema de arquivos, montá-lo temporariamente e ver quanto espaço
real você tem em um volume lógico:

# mkfs -t ext4 /dev/mapper/myvg-mylv1


mke2fs 1.44.1 (24 de março de 2018)
Criando sistema de arquivos com 2621440 blocos de 4k e 655360 inodes
UUID do sistema de arquivos: 83cc4119-625c-49d1-88c4-e2359a15a887
Backups de superblocos armazenados em blocos:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632
Alocando tabelas de grupo: feito
Escrevendo tabelas de inode: feito
Criando diário (16384 blocos): concluído
Escrevendo superblocos e informações de contabilidade do sistema de arquivos: done
# mount /dev/mapper/myvg-mylv1 /mnt
# df /mnt
Filesystem 1K-blocks Usado Disponível Use% Montado em
/dev/mapper/myvg-mylv1 10255636 36888 9678076 1% /mnt

Removendo Volumes Lógicos

Ainda não analisamos nenhuma operação no outro volume lógico, mylv2, então vamos usá-lo para
tornar este exemplo mais interessante. Digamos que você descubra que não está realmente usando
esse segundo volume lógico. Você decide removê-lo e redimensionar o primeiro volume lógico para
ocupar o espaço restante no grupo de volumes. A Figura 4-6 mostra nosso objetivo.

Supondo que você já tenha movido ou feito backup de algo importante em


o volume lógico que você vai excluir, e que não está em uso no sistema atual (ou seja, você o
desmontou), primeiro remova-o com lvremove. Ao manipular volumes lógicos com este comando, você
fará referência a eles usando uma sintaxe diferente — separando o grupo de volumes e os nomes dos
volumes lógicos por uma barra (myvg/mylv2):

# lvremove myvg/mylv2
Você realmente deseja remover e DESCARTAR o volume lógico ativo myvg/mylv2? [s/n]: sim

Volume lógico "mylv2" removido com sucesso

Discos e Sistemas de Arquivos 105


Machine Translated by Google

Volume lógico:
mylv1 (20 GB)

Grupo de volume: myvg

Volume físico: Volume físico:


/dev/sdb1 (5 GB) /dev/sdc1 (15 GB)

Figura 4-6: Resultados da reconfiguração de volumes lógicos

AVISO Tenha cuidado ao executar lvremove. Como você não usou essa sintaxe com o
outros comandos LVM que você viu até agora, você pode acidentalmente usar um espaço em
vez da barra. Se você cometer esse erro neste caso específico, o lvremove assume que você
deseja remover todos os volumes lógicos nos grupos de volumes myvg e
mylv2. (Você quase certamente não tem um grupo de volume chamado mylv2, mas esse não é
seu maior problema no momento.) Então, se você não estiver prestando atenção, você pode
remover todos os volumes lógicos em um grupo de volume, não apenas 1.

Como você pode ver nesta interação, o lvremove tenta protegê-lo de erros, verificando
novamente se você realmente deseja remover cada volume lógico destinado à remoção. Ele
também não tentará remover um volume que está em uso.
Mas não assuma apenas que você deve responder a qualquer pergunta que for feita.

Redimensionando Volumes Lógicos e Sistemas de Arquivos

Agora você pode redimensionar o primeiro volume lógico, mylv1. Você pode fazer isso
mesmo quando o volume estiver em uso e seu sistema de arquivos estiver montado. No
entanto, é importante entender que existem duas etapas. Para usar seu volume lógico maior,
você precisa redimensionar tanto ele quanto o sistema de arquivos dentro dele (o que você
também pode fazer enquanto está montado). Mas porque esta é uma operação tão comum, o
comando lvresize que redimensiona um volume lógico tem uma opção (-r) para realizar o
redimensionamento do sistema de arquivos para você também.
Apenas para ilustração, vamos usar dois comandos separados para ver como isso funciona. Há
várias maneiras de especificar a alteração no tamanho de um volume lógico, mas, nesse caso, o método
mais direto é adicionar todos os PEs livres no grupo de volumes ao volume lógico. Lembre-se de que
você pode encontrar esse número com vgdisplay; em nosso exemplo em execução, é 2.602. Aqui está o
comando lvresize para adicionar tudo isso ao mylv1:

# lvresize -l +2602 myvg/mylv1


O tamanho do volume lógico myvg/mylv1 mudou de 10,00 GiB (2560 extensões) para
20,16 GiB (5162 extensões).
Volume lógico myvg/mylv1 redimensionado com sucesso.

106 Capítulo 4
Machine Translated by Google

Agora você precisa redimensionar o sistema de arquivos dentro. Você pode fazer isso
com o comando fsadm . É divertido vê-lo funcionar no modo detalhado (use o -v
opção):

# fsadm -v resize /dev/mapper/myvg-mylv1


fsadm: sistema de arquivos "ext4" encontrado em "/dev/mapper/myvg-mylv1".
fsadm: O tamanho do dispositivo "/dev/mapper/myvg-mylv1" é 21650997248 bytes
fsadm: Analisando tune2fs -l "/dev/mapper/myvg-mylv1"
fsadm: Redimensionando o sistema de arquivos no dispositivo "/dev/mapper/myvg-mylv1" para
21650997248 bytes (2621440 -> 5285888 blocos de 4096 bytes)
fsadm: Executando resize2fs /dev/mapper/myvg-mylv1 5285888
resize2fs 1.44.1 (24 de março de 2018)
O sistema de arquivos em /dev/mapper/myvg-mylv1 é montado em /mnt; redimensionamento on-line
necessário
old_desc_blocks = 2, new_desc_blocks = 3
O sistema de arquivos em /dev/mapper/myvg-mylv1 agora tem 5285888 (4k) blocos de comprimento.

Como você pode ver na saída, o fsadm é apenas um script que sabe como transformar seus
argumentos nos usados por ferramentas específicas do sistema de arquivos, como resize2fs. Por
padrão, se você não especificar um tamanho, ele simplesmente será redimensionado para caber
em todo o dispositivo.
Agora que você viu os detalhes do redimensionamento de volumes, provavelmente está
procurando atalhos. A abordagem muito mais simples é usar uma taxa de sintaxe diferente para o
tamanho e fazer com que lvresize execute o redimensionamento da partição para você, com este
único comando:

# lvresize -r -l +100%FREE myvg/mylv1

É muito bom que você possa expandir um sistema de arquivos ext2/ext3/ext4 enquanto ele
está montado. Infelizmente, não funciona ao contrário. Você não pode reduzir um sistema de
arquivos quando ele está montado. Você não apenas deve desmontar o sistema de arquivos, mas o
processo de redução de um volume lógico exige que você execute as etapas inversas. Portanto, ao
redimensionar manualmente, você precisaria redimensionar a partição antes do volume lógico,
certificando-se de que o novo volume lógico ainda seja grande o suficiente para conter o sistema de
arquivos. Novamente, é muito mais fácil usar lvresize
com a opção -r para que possa coordenar o sistema de arquivos e os tamanhos do volume lógico
para você.

4.4.3 A Implementação do LVM


Com os fundamentos operacionais mais práticos do LVM cobertos, agora podemos dar uma
breve olhada em sua implementação. Como em quase todos os outros tópicos deste livro, o LVM
contém várias camadas e componentes, com uma separação bastante cuidadosa entre as partes
no kernel e no espaço do usuário.
Como você verá em breve, encontrar PVs para descobrir a estrutura dos grupos de volumes
e volumes lógicos é um pouco complicado, e o kernel Linux prefere não lidar com nada disso. Não
há razão para isso acontecer no espaço do kernel; Os PVs são apenas dispositivos de bloco e o
espaço do usuário tem acesso aleatório a dispositivos de bloco. Na verdade, o próprio LVM (mais
especificamente, LVM2 nos sistemas atuais) é apenas o nome de um conjunto de utilitários de
espaço do usuário que conhecem a estrutura do LVM.

Discos e Sistemas de Arquivos 107


Machine Translated by Google

Por outro lado, o kernel lida com o trabalho de rotear uma solicitação de um local no dispositivo
de bloco de um volume lógico para o local verdadeiro em um dispositivo real. O driver para isso é o
mapeador de dispositivos (às vezes abreviado para devmapper), uma nova camada entre os dispositivos
de bloco normais e o sistema de arquivos. Como o nome sugere, a tarefa que o mapeador de dispositivos
executa é como seguir um mapa; você quase pode pensar nisso como traduzir um endereço de rua em
um local absoluto como coordenadas globais de latitude/longitude. (É uma forma de virtualização; a
memória virtual que veremos em outras partes do livro funciona com um conceito semelhante.)

Há alguma cola entre as ferramentas de espaço do usuário do LVM e o mapeador de dispositivos:


alguns utilitários que são executados no espaço do usuário para gerenciar o mapa de dispositivos no kernel.
Vejamos o lado do LVM e o lado do kernel, começando com o LVM.

Utilitários LVM e Varredura de Volumes Físicos

Antes de fazer qualquer coisa, um utilitário LVM deve primeiro varrer os dispositivos de bloco
disponíveis para procurar PVs. As etapas que o LVM deve executar no espaço do usuário são
aproximadamente as seguintes:

1. Encontre todos os PVs no sistema.

2. Encontre todos os grupos de volumes aos quais os PVs pertencem por UUID (este
informações estão contidas nos PVs).

3. Verifique se tudo está completo (ou seja, todos os PVs necessários que pertencem ao grupo de
volumes estão presentes).

4. Localize todos os volumes lógicos nos grupos de volumes.

5. Descubra o esquema para mapear dados dos PVs para os volumes lógicos.

Há um cabeçalho no início de cada PV que identifica o volume


bem como seus grupos de volumes e os volumes lógicos dentro. Os utilitários LVM podem reunir essas
informações e determinar se todos os PVs necessários para um grupo de volumes (e seus volumes
lógicos) estão presentes. Se tudo der certo, o LVM pode trabalhar para obter as informações para o kernel.

NOTA Se você estiver interessado na aparência do cabeçalho LVM em um PV, você pode executar um
mando como este:

# dd if=/dev/sdb1 contagem=1000 | cordas | menos

Neste caso, estamos usando / dev/sdb1 como PV. Não espere que a saída seja muito bonita, mas
mostra as informações necessárias para o LVM.

Qualquer utilitário LVM, como pvscan, lvs ou vgcreate, é capaz de realizar o trabalho de varredura
e processamento de PVs.

O Mapeador de Dispositivos

Depois que o LVM determina a estrutura dos volumes lógicos de todos os cabeçalhos nos PVs, ele se
comunica com o mapeador de dispositivos do kernel

108 Capítulo 4
Machine Translated by Google

driver para inicializar os dispositivos de bloco para os volumes lógicos e carregar suas tabelas de
mapeamento. Ele consegue isso com a chamada de sistema ioctl(2) (uma interface de kernel
comumente usada) no arquivo de dispositivo /dev/ mapper/ control . Não é muito prático tentar
monitorar essa interação, mas é possível ver os detalhes dos resultados com o comando dmsetup .

Para obter um inventário dos dispositivos mapeados atualmente atendidos pelo dispositivo
mapeador, use dmsetup info. Aqui está o que você pode obter para um dos volumes lógicos criados
anteriormente neste capítulo:

# informações do dmsetup
Nome: myvg-mylv1
Estado: ATIVO
Leia adiante: 256
Tabelas presentes: VIVER

Contagem aberta: 0
Número do evento: 0
Maior, menor: 253, 1
Número de alvos: 2
UUID: LVM-1pHrOee5zyTUtK5gnNSpDYshM8Cbokf3OfwX4T0w2XncjGrwct7nwGhpp7l7J5aQ

O número maior e menor do dispositivo corresponde ao /dev/ dm-*


arquivo de dispositivo para o dispositivo mapeado; o número principal para este mapeador de
dispositivo é 253. Como o número secundário é 1, o arquivo de dispositivo é denominado /dev/ dm-1.
Observe que o kernel tem um nome e ainda outro UUID para o dispositivo mapeado. O LVM os
forneceu ao kernel (o UUID do kernel é apenas uma concatenação dos UUIDs do grupo de volumes
e do volume lógico).

NOTA Lembre-se dos links simbólicos como / dev/mapper/myvg-mylv1? O udev cria aqueles em resposta a novos
dispositivos a partir do mapeador de dispositivos, usando um arquivo de regras como vimos na Seção
3.5.2.

Você também pode visualizar a tabela que o LVM deu ao mapeador de dispositivos, por emissão
ndo o comando dmsetup table. Aqui está o que parece para o nosso exemplo anterior quando havia
dois volumes lógicos de 10 GB (mylv1 e mylv2) espalhados pelos dois volumes físicos de 5 GB (/ dev/
sdb1) e 15 GB (/ dev/ sdc1):

#tabela dmsetup
myvg-mylv2: 0 10960896 linear 8:17 2048
myvg-mylv2: 10960896 10010624 linear 8:33 20973568
myvg-mylv1: 0 20971520 linear 8:33 2048

Cada linha fornece um segmento do mapa para um determinado dispositivo mapeado.


Para o dispositivo myvg-mylv2, existem duas partes, e para myvg-mylv1, há uma única. Os campos
após o nome, em ordem, são:

1. O deslocamento inicial do dispositivo mapeado. As unidades estão em “setores” de 512 bytes, ou o


tamanho de bloco normal que você vê em muitos outros dispositivos.

2. O comprimento deste segmento.

3. O esquema de mapeamento. Aqui, é o esquema linear simples de um para um.

Discos e Sistemas de Arquivos 109


Machine Translated by Google

4. O par de número de dispositivo principal e secundário de um dispositivo de origem - ou seja,


o que o LVM chama de volumes físicos. Aqui 8:17 é /dev/ sdb1 e 8:33 é /dev/ sdc1.
5. Um deslocamento inicial no dispositivo de origem.

O interessante aqui é que em nosso exemplo, o LVM escolheu usar o espaço em /dev/
sdc1 para o primeiro volume lógico que criamos (mylv1). O LVM decidiu que queria dispor o
primeiro volume lógico de 10 GB de maneira contígua, e a única maneira de fazer isso era
em /dev/ sdc1. No entanto, ao criar o segundo volume lógico (mylv2), o LVM não teve
escolha a não ser distribuí-lo em dois segmentos entre os dois PVs. A Figura 4-7 mostra o
arranjo.

LV: mylv2 (segmento 1) LV: mylv1 (completo) LV: mylv2 (segmento 2)


Início do PV: 2048 Início do PV: 2048 Início PV: 20973568
Comprimento: 10960896 (5 GB) Comprimento: 20971520 (10 GB) Comprimento: 10010624 (5GB)

PV 8:17 (/dev/sdb1, 5GB) PV 8:33 (/dev/sdc1, 15GB)

Figura 4-7: Como o LVM organiza mylv1 e mylv2

Como consequência adicional, quando removemos mylv2 e expandimos mylv1


para caber o espaço restante no grupo de volumes, o deslocamento inicial original no PV
permaneceu onde estava em /dev/ sdc1, mas todo o resto mudou para incluir o restante dos
PVs:

#tabela dmsetup
myvg-mylv1: 0 31326208 linear 8:33 2048
myvg-mylv1: 31326208 10960896 linear 8:17 2048

A Figura 4-8 mostra o arranjo.

LV: mylv1 (segmento 2) LV: mylv1 (segmento 1)


Início do PV: 2048 Início do PV: 2048
Comprimento: 10960896 (5 GB) Comprimento: 31326208 (15GB)

PV 8:17 (/dev/sdb1, 5GB) PV 8:33 (/dev/sdc1, 15GB)

Figura 4-8: O arranjo depois que removemos mylv2 e expandimos mylv1

Você pode experimentar volumes lógicos e o mapeador de dispositivos para o


conteúdo do seu coração com máquinas virtuais e ver como os mapeamentos se saem.
Muitos recursos, como RAID de software e discos criptografados, são criados no mapeador de
dispositivos.

110 Capítulo 4
Machine Translated by Google

4.5 Olhando para o futuro: discos e espaço do usuário


Em componentes relacionados a disco em um sistema Unix, os limites entre o espaço do usuário e o
kernel podem ser difíceis de caracterizar. Como você viu, o kernel lida com E/S de bloco bruto dos
dispositivos, e as ferramentas do espaço do usuário podem usar a E/S de bloco por meio de arquivos de
dispositivo. No entanto, o espaço do usuário normalmente usa a E/S do bloco apenas para operações
de inicialização, como particionamento, criação do sistema de arquivos e criação do espaço de troca.
Em uso normal, o espaço do usuário usa apenas o suporte ao sistema de arquivos que o kernel fornece
no topo do bloco de E/S.
Da mesma forma, o kernel também lida com a maioria dos detalhes tediosos ao lidar com o espaço de
troca no sistema de memória virtual.
O restante deste capítulo examina brevemente as entranhas de um sistema de arquivos Linux.
Este é um material mais avançado, e você certamente não precisa conhecê-lo para prosseguir com o
livro. Se esta é sua primeira vez, pule para o próximo capítulo e comece a aprender sobre como o Linux
inicializa.

4.6 Dentro de um sistema de arquivos tradicional


Um sistema de arquivos Unix tradicional tem dois componentes principais: um conjunto de blocos de
dados onde você pode armazenar dados e um sistema de banco de dados que gerencia o conjunto
de dados. O banco de dados é centrado em torno da estrutura de dados do inode. Um inode é um
conjunto de dados que descreve um arquivo específico, incluindo seu tipo, por missões e, talvez o
mais importante, onde no conjunto de dados os dados do arquivo residem. Os inodes são identificados
por números listados em uma tabela de inodes.
Nomes de arquivos e diretórios também são implementados como inodes. Um inode de diretório
contém uma lista de nomes de arquivos e links correspondentes a outros inodes.
Para fornecer um exemplo da vida real, criei um novo sistema de arquivos, montei-o e alterei o
diretório para o ponto de montagem. Então, adicionei alguns arquivos e diretórios com estes comandos:

$ mkdir dir_1
$ mkdir dir_2
$ echo a > dir_1/arquivo_1
$ echo b > dir_1/arquivo_2
$ echo c > dir_1/arquivo_3
$ echo d > dir_2/arquivo_4
$ ln dir_1/file_3 dir_2/file_5

Observe que criei dir_2/ file_5 como um link físico para dir_1/ file_3, significando
que esses dois nomes de arquivo realmente representam o mesmo arquivo (mais sobre isso em
breve). Sinta-se livre para tentar isso você mesmo. Ele não precisa necessariamente estar em um novo
sistema de arquivos.
Se você explorar os diretórios neste sistema de arquivos, seu conteúdo aparecerá como
mostrado na Figura 4-9.

NOTA Se você tentar isso em seu próprio sistema, os números dos inodes provavelmente serão diferentes,
especialmente se você executar os comandos para criar os arquivos e diretórios em um sistema de
arquivos existente. Os números específicos não são importantes; é tudo sobre os dados que eles apontam.

Discos e Sistemas de Arquivos 111


Machine Translated by Google

(raiz)

você_1 você_2

arquivo_1 arquivo_2 arquivo_3 arquivo_4 arquivo_5

Figura 4-9: Representação em nível de usuário de um sistema de arquivos

O layout real do sistema de arquivos como um conjunto de inodes,


mostrado na Figura 4-10, não parece tão limpo quanto a representação em nível de usuário.

tabela de inodes

#/contagem/tipo de link conjunto de dados

2 4 você . inodo 2
você_1 ino 12
você_2 inode 7633
12 2 vocês

13 1 Arquivo
. ino 12
.. inodo 2
arquivo_1 ino 13
14 1 Arquivo
arquivo_2 ino 14
arquivo_3 ino 15

15 2 Arquivo

"uma"

16 1 Arquivo

. inode 7633
.. inodo 2
7633 2 vocês
arquivo_4 ino 16
arquivo_5 ino 15

"b"

"c"

"d"

Figura 4-10: Estrutura do inode do sistema de arquivos mostrado na Figura 4-9

Como damos sentido a isso? Para qualquer sistema de arquivos ext2/3/4, você
inicia no inode número 2, que é o inode raiz (tente não confundir isso com o sistema de
arquivos raiz do sistema). Na tabela de inode na Figura 4-10, você pode ver que este é
um inode de diretório (dir), então você pode seguir a seta até o datapool, onde você vê
o conteúdo do diretório raiz: duas entradas

112 Capítulo 4
Machine Translated by Google

nomeados dir_1 e dir_2 correspondentes aos inodes 12 e 7633, respectivamente.


Para explorar essas entradas, volte para a tabela de inodes e observe qualquer um desses inodes.

Para examinar dir_1/ file_2 neste sistema de arquivos, o kernel faz o seguinte:

1. Determina os componentes do caminho: um diretório chamado dir_1, seguido por um componente


chamado file_2.

2. Segue o inode raiz para seus dados de diretório.

3. Localiza o nome dir_1 nos dados do diretório do inode 2, que aponta para o inode
número 12.

4. Procura o inode 12 na tabela de inode e verifica se é um diretório


inode.

5. Segue o link de dados do inode 12 para suas informações de diretório (a segunda caixa
para baixo no conjunto de dados).

6. Localiza o segundo componente do caminho (file_2) no diretório do inode 12


dados históricos. Esta entrada aponta para o inode número 14.

7. Procura o inode 14 na tabela de diretórios. Este é um arquivo inode.

Neste ponto, o kernel conhece as propriedades do arquivo e pode abrir


seguindo o link de dados do inode 14.
Esse sistema, de inodes apontando para estruturas de dados de diretório e estruturas de
dados de diretório apontando para inodes, permite que você crie a hierarquia do sistema de arquivos
com a qual está acostumado. Além disso, observe que os inodes do diretório contêm entradas para .
(o diretório atual) e .. (o diretório pai, exceto o diretório raiz). Isso facilita a obtenção de um ponto de
referência e a navegação de volta pela estrutura de diretórios.

4.6.1 Detalhes do Inode e Contagem de Link


Para visualizar os números de inode de qualquer diretório, use o comando ls -i .
Aqui está o que você obteria na raiz deste exemplo (para informações mais detalhadas sobre o
inode, use o comando stat ):

$ ls -i
12 você_1 7633 você_2

Você provavelmente está se perguntando sobre a contagem de links na tabela de inodes.


Você já viu a contagem de links na saída do comando ls -l comum , mas provavelmente a ignorou.
Como a contagem de links se relaciona com os arquivos da Figura 4-9, em particular o arquivo_5
com “ link físico” ? O campo de contagem de links é o número total de entradas de diretório (em
todos os diretórios) que apontam para um inode. A maioria dos arquivos tem uma contagem de links
de 1 porque eles ocorrem apenas uma vez nas entradas do diretório. Isso é esperado. Na maioria
das vezes, quando você cria um arquivo, você cria uma nova entrada de diretório e um novo inode
para acompanhá-lo.
No entanto, o inode 15 ocorre duas vezes. Primeiro é criado como dir_1/ file_3 e, em seguida, é
vinculado como dir_2/ file_5. Um hard link é apenas uma entrada criada manualmente em um diretório
para um inode que já existe. O comando ln (sem o -s
opção) permite que você crie novos links físicos manualmente.

Discos e Sistemas de Arquivos 113


Machine Translated by Google

É também por isso que a remoção de um arquivo às vezes é chamada de desvinculação. Se você correr
rm dir_1/file_2, o kernel procura por uma entrada chamada file_2 nas entradas do diretório do inode 12. Ao
descobrir que o arquivo_2 corresponde ao inode 14, o kernel remove a entrada do diretório e então subtrai 1
da contagem de links do inode 14. Como resultado, a contagem de links do inode 14 será 0, e o kernel saberá
que não há mais nenhum nome vinculado ao inode. Portanto, agora ele pode excluir o inode e quaisquer
dados associados a ele.

No entanto, se você executar rm dir_1/file_3, o resultado final é que a contagem de links do inode 15 vai
de 2 para 1 (porque dir_2/ file_5 ainda aponta para lá), e o kernel sabe que não deve remover o inode.

A contagem de links funciona da mesma forma para diretórios. Observe que o inode 12
a contagem de links é 2, porque há dois links de inode lá: um para dir_1 nas entradas de diretório para
o inode 2 e o segundo uma auto-referência (.) em suas próprias entradas de diretório. Se você criar um
novo diretório dir_1/ dir_3, a contagem de links para o inode 12 irá para 3 porque o novo diretório incluiria
uma entrada pai (..) que vincula de volta ao inode 12, assim como o link pai do inode 12 aponta para o inode
2.

Há uma pequena exceção na contagem de links. O inode raiz 2 tem uma contagem de links de 4. No
entanto, a Figura 4-10 mostra apenas três links de entrada de diretório. O “quarto” link está no superblock do
sistema de arquivos porque o superblock informa onde encontrar o inode raiz.

Não tenha medo de experimentar em seu sistema. Criar uma estrutura de diretórios e usar
ls -i ou stat para percorrer as peças é inofensivo. Você não precisa ser root (a menos que você monte e
crie um novo sistema de arquivos).

4.6.2 Alocação de Blocos


Ainda falta uma peça na nossa discussão. Ao alocar blocos de pool de dados para um novo arquivo, como
o sistema de arquivos sabe quais blocos estão em uso e quais estão disponíveis? Uma das maneiras mais
básicas é usar uma estrutura de dados de gerenciamento adicional chamada de bitmap de bloco. Nesse
esquema, o sistema de arquivos reserva uma série de bytes, com cada bit correspondendo a um bloco no
datapool. Um valor 0 significa que o bloco está livre e 1 significa que está em uso. Assim, alocar e desalocar
blocos é uma questão de inverter bits.

Problemas em um sistema de arquivos surgem quando os dados da tabela de inode não correspondem
os dados de alocação de blocos ou quando as contagens de links estão incorretas; por exemplo, isso pode
acontecer quando você não desliga um sistema corretamente. Portanto, quando você verifica um sistema de
arquivos, conforme descrito na Seção 4.2.11, o programa fsck percorre a tabela de inodes e a estrutura de
diretórios para gerar novas contagens de links e um novo mapa de alocação de blocos (como o bitmap de
bloco) e, em seguida, compara os dados recém-gerados com o sistema de arquivos no disco.

Se houver incompatibilidades, o fsck deve corrigir as contagens de links e determinar o que fazer com
quaisquer inodes e/ou dados que não surgiram quando atravessaram a estrutura de diretórios. A maioria dos
programas fsck cria esses novos arquivos “órfãos” no diretório perdido+encontrado do sistema de arquivos .

114 Capítulo 4
Machine Translated by Google

4.6.3 Trabalhando com Sistemas de Arquivos no Espaço do Usuário

Ao trabalhar com arquivos e diretórios no espaço do usuário, você não deve se preocupar muito com
a implementação abaixo deles. Espera-se que os processos acessem o conteúdo de arquivos e
diretórios de um sistema de arquivos montado por meio de chamadas de sistema do kernel.
Curiosamente, porém, você tem acesso a certas informações do sistema de arquivos que não
parecem caber no espaço do usuário - em particular, a chamada do sistema stat() retorna números
de inode e contagens de links.
Quando você não está mantendo um sistema de arquivos, você precisa se preocupar com
números de inode, contagens de links e outros detalhes de implementação? Geralmente, não.
Esse material é acessível a programas de modo de usuário principalmente para compatibilidade
com versões anteriores. Além disso, nem todos os sistemas de arquivos disponíveis no Linux
possuem esses sistemas de arquivos internos. A camada de interface VFS garante que as chamadas
do sistema sempre retornem números de inode e contagens de links, mas esses números podem
não significar necessariamente nada.
Você pode não ser capaz de executar operações tradicionais do sistema de arquivos Unix
em sistemas de arquivos não tradicionais. Por exemplo, você não pode usar ln para criar um link
físico em um sistema de arquivos VFAT montado porque sua estrutura de entrada de diretório,
projetada para Windows em vez de Unix/Linux, não suporta esse conceito.

Felizmente, as chamadas de sistema disponíveis para o espaço do usuário em sistemas


Linux fornecem abstração suficiente para um acesso fácil a arquivos - você não precisa saber nada
sobre a implementação subjacente para acessar os arquivos. Além disso, os nomes de arquivos são
flexíveis em formato e os nomes de maiúsculas e minúsculas são suportados, facilitando o suporte
a outros sistemas de arquivos de estilo hierárquico.
Lembre-se, o suporte específico ao sistema de arquivos não precisa necessariamente estar
no kernel. Por exemplo, em sistemas de arquivos de espaço de usuário, o kernel só precisa atuar
como um canal para chamadas de sistema.

Discos e Sistemas de Arquivos 115


Machine Translated by Google
Machine Translated by Google

5
COMO AS BOTAS DO LINUX KERNEL

Agora você conhece a estrutura física e lógica


de um sistema Linux, o que é o kernel e como
trabalhar com processos. este
capítulo irá ensinar a você como o kernel inicia, ou
inicializa. Em outras palavras, você aprenderá como o kernel
se move para a memória e o que ele faz até o ponto em que
o primeiro processo do usuário é iniciado.
Uma visão simplificada do processo de inicialização se parece com isso:

1. O BIOS da máquina ou firmware de inicialização carrega e executa um carregador de inicialização.

2. O carregador de inicialização encontra a imagem do kernel no disco, carrega-a na memória,


e o inicia.

3. O kernel inicializa os dispositivos e seus drivers.

4. O kernel monta o sistema de arquivos raiz.

5. O kernel inicia um programa chamado init com um ID de processo de 1. Este ponto é o início do
espaço do usuário.
Machine Translated by Google

6. init coloca o resto dos processos do sistema em movimento.


7. Em algum momento, o init inicia um processo que permite que você faça login, geralmente no
final ou próximo ao final da sequência de inicialização.

Este capítulo cobre os primeiros estágios, focando na inicialização


carregadores e kernel. O Capítulo 6 continua com o início do espaço do usuário detalhando
o systemd, a versão mais difundida do init em sistemas Linux.
Ser capaz de identificar cada estágio do processo de inicialização será inestimável para
você na correção de problemas de inicialização e na compreensão do sistema como um todo.
No entanto, o comportamento padrão em muitas distribuições Linux muitas vezes torna difícil, se
não impossível, identificar os primeiros estágios de inicialização à medida que eles avançam, então
você provavelmente poderá dar uma boa olhada somente depois que eles forem concluídos e você
Conecte-se.

5.1 Mensagens de inicialização


Os sistemas Unix tradicionais produzem muitas mensagens de diagnóstico na inicialização
que informam sobre o processo de inicialização. As mensagens vêm primeiro do kernel e depois
dos processos e procedimentos de inicialização que o init inicia.
No entanto, essas mensagens não são bonitas ou consistentes e, em alguns casos, nem são
muito informativas. Além disso, as melhorias de hardware fizeram com que o kernel iniciasse
muito mais rápido do que antes; as mensagens passam tão rapidamente que pode ser difícil ver o
que está acontecendo. Como resultado, a maioria das distribuições Linux atuais fazem o possível
para ocultar os diagnósticos de inicialização com telas iniciais e outras formas de preenchimento
para distraí-lo enquanto o sistema é iniciado.
A melhor maneira de visualizar as mensagens de diagnóstico de inicialização e de
tempo de execução do kernel é recuperar o diário do kernel com o comando journalctl .
A execução de journalctl -k exibe as mensagens da inicialização atual, mas você pode visualizar
as inicializações anteriores com a opção -b . Abordaremos o diário com mais detalhes no Capítulo
7.
Se você não tiver o systemd, você pode verificar se há um arquivo de log como /var/ log/
kern.log ou execute o comando dmesg para visualizar as mensagens no buffer de anel do
kernel.
Aqui está uma amostra do que você pode esperar ver no journalctl -k
comando:

microcódigo: microcódigo atualizado antecipadamente para a revisão 0xd6, data = 2019-10-03


Linux versão 4.15.0-112-generic (buildd@lcy01-amd64-027) (gcc versão 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04))
#113-Ubuntu SMP Qui 9 de julho 23:41:39 UTC 2020 (Gratuito 4.15.0-112.113-genérico 4.15.18)

Linha de comando: BOOT_IMAGE=/boot/vmlinuz-4.15.0-112-generic root=UUID=17f12d53-c3d7-4ab3-943e a0a72366c9fa ro quiet


splash vt.handoff=1
CPU compatível com KERNEL:
--recorte--
scsi 2:0:0:0: ATA de acesso direto sd 2:0:0:0: scsi KINGSTON SM2280S 01.R PQ: 0 ANSI: 5
genérico sg0 tipo 0 anexado
sd 2:0:0:0: [sda] 468862128 Blocos lógicos de 512 bytes: (240 GB/224 GiB)

118 Capítulo 5
Machine Translated by Google

sd 2:0:0:0: [sda] A proteção contra gravação está desativada


sd 2:0:0:0: [sda] Modo Sentido: 00 3a 00 00
sd 2:0:0:0: [sda] Cache de gravação: ativado, cache de leitura: ativado, não suporta DPO ou FUA
sda:sda1 sda2<sda5>
sd 2:0:0:0: [sda] Disco SCSI anexado
--recorte--

Depois que o kernel foi iniciado, o procedimento de inicialização do espaço do usuário geralmente gera
mensagens. Essas mensagens provavelmente serão mais difíceis de visualizar e revisar porque na maioria
dos sistemas você não as encontrará em um único arquivo de log.
Os scripts de inicialização são projetados para enviar mensagens ao console que são apagadas após a conclusão
do processo de inicialização. No entanto, isso não é um problema em sistemas Linux porque o systemd captura
mensagens de diagnóstico da inicialização e do tempo de execução que normalmente iriam para o console.

5.2 Inicialização do kernel e opções de inicialização


Na inicialização, o kernel do Linux é inicializado nesta ordem geral:

1. Inspeção da CPU

2. Inspeção de memória

3. Descoberta do barramento do dispositivo

4. Descoberta de dispositivos

5. Configuração do subsistema do kernel auxiliar (rede e similares)

6. Montagem do sistema de arquivos raiz

7. Início do espaço do usuário

As duas primeiras etapas não são muito notáveis, mas quando o kernel chega aos dispositivos, surge a
questão das dependências. Por exemplo, os drivers de dispositivo de disco podem depender do suporte do
barramento e do suporte do subsistema SCSI, como você viu no Capítulo 3. Então, mais tarde no processo de
inicialização, o kernel deve montar um sistema de arquivos raiz antes de iniciar o init.

Em geral, você não terá que se preocupar com as dependências, exceto que alguns componentes
necessários podem ser módulos de kernel carregáveis em vez de parte do kernel principal. Algumas máquinas
podem precisar carregar esses módulos de kernel antes que o verdadeiro sistema de arquivos raiz seja montado.
Abordaremos esse problema e suas soluções alternativas iniciais do sistema de arquivos RAM (initrd) na Seção
6.7.

O kernel emite certos tipos de mensagens indicando que está recebendo


pronto para iniciar seu primeiro processo de usuário:

Liberando memória do kernel não utilizada: 2408K


Gravação protegendo os dados somente leitura do kernel: 20480k
Liberando memória do kernel não utilizada: 2008K
Liberando memória do kernel não utilizada: 1892K

Como o kernel Linux inicializa 119


Machine Translated by Google

Aqui, não apenas o kernel está limpando alguma memória não utilizada, mas também está protegendo
seus próprios dados. Então, se você estiver executando um kernel novo o suficiente, verá o kernel iniciar o
primeiro processo de espaço do usuário como init:

Execute /init como processo de inicialização


com argumentos:
--recorte--

Mais tarde, você poderá ver o sistema de arquivos raiz sendo montado e o systemd inicializando,
enviando algumas mensagens próprias para o log do kernel:

EXT4-fs (sda1): sistema de arquivos montado com modo de dados ordenados. Opções: (nulo)
systemd[1]: systemd 237 rodando no modo de sistema. (+PAM +AUDIT +SELINUX +IMA +APPARMOR
+SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4
+SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN -PCRE2 default-hierarchy=hybrid)
systemd[1]: arquitetura detectada x86-64.
systemd[1]: Defina o nome do host como <duplex>.

Neste ponto, você definitivamente sabe que o espaço do usuário foi iniciado.

5.3 Parâmetros do Kernel


Quando o kernel do Linux é iniciado, ele recebe um conjunto de parâmetros de kernel baseados em texto
contendo alguns detalhes adicionais do sistema. Os parâmetros especificam muitos tipos diferentes de
comportamento, como a quantidade de saída de diagnóstico que o kernel deve produzir e as opções
específicas do driver de dispositivo.
Você pode visualizar os parâmetros passados para o kernel atualmente em execução do seu sistema
observando o arquivo /proc/ cmdline :

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.15.0-43-generic root=UUID=17f12d53-c3d7-4ab3-943e
-a0a72366c9fa ro quiet splash vt.handoff=1

Os parâmetros são sinalizadores simples de uma palavra, como ro e quiet, ou pares chave=valor ,
como vt.handoff=1. Muitos dos parâmetros não são importantes, como o sinalizador inicial para exibir uma
tela inicial, mas um que é crítico é o parâmetro raiz . Esta é a localização do sistema de arquivos raiz; sem
ele, o kernel não pode executar corretamente o início do espaço do usuário.

O sistema de arquivos raiz pode ser especificado como um arquivo de dispositivo, como neste exemplo:

root=/dev/sda1

Na maioria dos sistemas contemporâneos, existem duas alternativas que são


mais comum. Primeiro, você pode ver um volume lógico como este:

root=/dev/mapper/my-system-root

Você também pode ver um UUID (consulte a Seção 4.2.4):

root=UUID=17f12d53-c3d7-4ab3-943e-a0a72366c9fa

120 Capítulo 5
Machine Translated by Google

Ambos são preferíveis porque não dependem de um mapeamento de dispositivo de kernel


específico.
O parâmetro ro instrui o kernel a montar o sistema de arquivos raiz no modo somente
leitura ao iniciar o espaço do usuário. Isto é normal; o modo somente leitura garante que o fsck
possa verificar o sistema de arquivos raiz com segurança antes de tentar fazer algo sério. Após a
verificação, o processo de inicialização remonta o sistema de arquivos raiz no modo de leitura e
gravação.
Ao encontrar um parâmetro que não entende, o kernel do Linux salva esse parâmetro. O kernel
posteriormente passa o parâmetro para init ao executar a inicialização do espaço do usuário. Por
exemplo, se você adicionar -s aos parâmetros do kernel, o kernel passará o -s ao programa init para
indicar que ele deve iniciar no modo de usuário único.

Se você estiver interessado nos parâmetros básicos de inicialização, a página de manual


bootparam(7) fornece uma visão geral. Se você está procurando algo muito específico, você pode
conferir kernel-params.txt, um arquivo de referência que vem com o kernel Linux.

Com esses conceitos básicos cobertos, você deve se sentir à vontade para pular para o Capítulo 6
para aprender as especificidades do início do espaço do usuário, o disco RAM inicial e o programa
init que o kernel executa como seu primeiro processo. O restante deste capítulo detalha como o kernel
carrega na memória e inicia, incluindo como ele obtém seus parâmetros.

5.4 Carregadores de inicialização

No início do processo de inicialização, antes que o kernel e o init sejam iniciados, um carregador de inicialização
programa inicia o kernel. O trabalho do carregador de boot parece simples: ele carrega o kernel na
memória de algum lugar em um disco e então inicia o kernel com um conjunto de parâmetros do
kernel. No entanto, este trabalho é mais complicado do que parece. Para entender o porquê, considere
as perguntas que o carregador de inicialização
deve responder:

•Onde está o kernel?

•Quais parâmetros do kernel devem ser passados para o kernel quando ele é iniciado?

As respostas são (tipicamente) que o kernel e seus parâmetros geralmente estão em algum lugar
no sistema de arquivos raiz. Pode parecer que os parâmetros do kernel devem ser fáceis de encontrar,
mas lembre-se de que o próprio kernel ainda não está em execução, e é o kernel que geralmente
percorre um sistema de arquivos para encontrar os arquivos necessários. Pior ainda, os drivers de
dispositivo do kernel normalmente usados para acessar o disco também não estão disponíveis. Pense
nisso como um tipo de problema de “galinha ou ovo”. Pode ficar ainda mais complicado do que isso,
mas por enquanto, vamos ver como um carregador de inicialização supera os obstáculos dos drivers e
do sistema de arquivos.
Um carregador de inicialização precisa de um driver para acessar o disco, mas não é o mesmo
que o kernel usa. Em PCs, os carregadores de inicialização usam o tradicional Basic Input/
Output System (BIOS) ou o mais recente Unified Extensible Firmware Interface (UEFI) para acessar
discos. (Extensible Firmware Interface, ou EFI, e UEFI serão discutidos em mais detalhes na Seção
5.8.2.) O hardware de disco contemporâneo inclui

Como o kernel do Linux inicializa 121


Machine Translated by Google

firmware que permite que o BIOS ou UEFI acessem o hardware de armazenamento conectado via Logical
Block Addressing (LBA). O LBA é uma maneira universal e simples de acessar dados de qualquer disco,
mas seu desempenho é ruim. No entanto, isso não é um problema, porque os carregadores de inicialização
geralmente são os únicos programas que devem usar esse modo para acesso ao disco; após iniciar, o kernel
tem acesso aos seus próprios drivers de alto desempenho.

OBSERVAÇÃO Para determinar se seu sistema usa um BIOS ou UEFI, execute efibootmgr. Se você receber uma lista
de alvos de inicialização, seu sistema tem UEFI. Se, em vez disso, você for informado de que as variáveis
EFI não são suportadas, seu sistema usa um BIOS. Alternativamente, você pode verificar se / sys/
firmware/efi existe; em caso afirmativo, seu sistema usa UEFI.

Uma vez resolvido o acesso aos dados brutos do disco, o carregador de inicialização deve fazer o
trabalho de localizar os dados desejados no sistema de arquivos. Os carregadores de inicialização mais
comuns podem ler tabelas de partições e possuem suporte embutido para acesso somente leitura a
sistemas de arquivos. Assim, eles podem encontrar e ler os arquivos de que precisam para colocar o
kernel na memória. Esse recurso torna muito mais fácil configurar e aprimorar dinamicamente o carregador
de inicialização. Os carregadores de inicialização do Linux nem sempre tiveram esse recurso; sem ele,
configurar o carregador de inicialização era mais difícil.

Em geral, tem havido um padrão do kernel adicionando novos recursos (especialmente em


tecnologia de armazenamento), seguido por carregadores de inicialização adicionando taxas separadas,
versões simplificadas desses recursos para compensar.

5.4.1 Tarefas do carregador de inicialização

A funcionalidade principal de um carregador de inicialização do Linux inclui a capacidade de fazer o


seguinte:

•Selecione entre vários kernels.

•Alternar entre conjuntos de parâmetros do kernel.

•Permitir que o usuário substitua e edite manualmente nomes e parâmetros de imagem do kernel (por
exemplo, para entrar no modo de usuário único).

•Fornecer suporte para inicializar outros sistemas operacionais.

Os carregadores de inicialização tornaram-se consideravelmente mais avançados desde o


início do kernel Linux, com recursos como histórico de linha de comando e sistemas de menus, mas uma
necessidade básica sempre foi a flexibilidade na seleção de parâmetros e imagens do kernel. (Um
fenômeno surpreendente é que algumas necessidades realmente diminuíram. Por exemplo, como você
pode executar uma inicialização de emergência ou recuperação de um dispositivo de armazenamento
USB, raramente precisa se preocupar em inserir manualmente os parâmetros do kernel ou entrar no
modo de usuário único.) Current os carregadores de inicialização oferecem mais poder do que nunca, o
que pode ser particularmente útil se você estiver criando kernels personalizados ou apenas deseja ajustar
parâmetros.

122 Capítulo 5
Machine Translated by Google

5.4.2 Visão geral do carregador de inicialização

Aqui estão os principais carregadores de inicialização que você pode encontrar:

GRUB Um padrão quase universal em sistemas Linux, com versões BIOS/MBR e UEFI.

LILO Um dos primeiros carregadores de inicialização do Linux. ELILO é uma versão UEFI.

SYSLINUX Pode ser configurado para rodar a partir de muitos tipos diferentes de sistemas de
arquivos.
LOADLIN Inicializa um kernel do MS-DOS.

systemd-boot Um gerenciador de inicialização UEFI simples.

coreboot (anteriormente LinuxBIOS) Um substituto de alto desempenho para o BIOS do PC que


pode incluir um kernel.

Linux Kernel EFISTUB Um plug-in do kernel para carregar o kernel diretamente de uma
partição de sistema EFI/UEFI (ESP).
efilinux Um carregador de inicialização UEFI destinado a servir como modelo e referência
para outros carregadores de inicialização UEFI.

Este livro trata quase exclusivamente do GRUB. A lógica por trás do uso de outros carregadores
de inicialização é que eles são mais simples de configurar do que o GRUB, são mais rápidos ou
fornecem alguma outra funcionalidade para fins especiais.
Você pode aprender muito sobre um carregador de inicialização acessando um prompt de
inicialização onde você pode inserir um nome de kernel e parâmetros. Para fazer isso, você precisa saber
como chegar a um prompt ou menu de inicialização. Infelizmente, isso às vezes pode ser difícil de descobrir
porque as distribuições Linux personalizam fortemente o comportamento e a aparência do carregador de
inicialização. Geralmente é impossível dizer apenas observando o processo de inicialização qual carregador
de inicialização a distribuição usa.
As próximas seções informam como chegar a um prompt de inicialização para entrar
um nome de kernel e parâmetros. Quando estiver confortável com isso, você verá como configurar e
instalar um carregador de inicialização.

5.5 Introdução ao GRUB

GRUB significa Grand Unified Boot Loader. Abordaremos o GRUB 2, mas também há uma versão mais
antiga chamada GRUB Legacy que não está mais em uso ativo.
Um dos recursos mais importantes do GRUB é a navegação do sistema de arquivos que
permite uma fácil seleção de imagem e configuração do kernel. Uma das melhores maneiras de ver
isso em ação e aprender sobre o GRUB em geral é olhar seu menu. A interface é fácil de navegar, mas
há uma boa chance de que você nunca a tenha visto.

Para acessar o menu GRUB, pressione e segure SHIFT quando a tela de inicialização do
BIOS aparecer pela primeira vez ou ESC se o seu sistema tiver UEFI. Caso contrário, a configuração
do carregador de inicialização pode não pausar antes de carregar o kernel.
A Figura 5-1 mostra o menu GRUB.

Como o kernel Linux inicializa 123


Machine Translated by Google

Figura 5-1: menu GRUB

Tente o seguinte para explorar o carregador de inicialização:

1. Reinicialize ou ligue seu sistema Linux.

2. Mantenha pressionado SHIFT durante o autoteste do BIOS ou ESC no firmware


tela inicial para obter o menu GRUB. (Às vezes, essas telas não são visíveis, então você precisa
adivinhar quando pressionar o botão.)

3. Pressione e para visualizar os comandos de configuração do carregador de inicialização para a


opção de inicialização padrão. Você deverá ver algo como a Figura 5-2 (talvez seja necessário
rolar para baixo para ver todos os detalhes).

Figura 5-2: Editor de configuração do GRUB

124 Capítulo 5
Machine Translated by Google

Esta tela nos diz que para esta configuração, a raiz é definida com um UUID, a imagem do
kernel é /boot/ vmlinuz-4.15.0-45-generic e os parâmetros do kernel incluem ro, quiet e splash. O
sistema de arquivos RAM inicial é /boot/
initrd.img-4.15.0-45-generic. Mas se você nunca viu esse tipo de configuração antes, pode achar um pouco
confuso. Por que existem várias referências à raiz e por que elas são diferentes? Por que o insmod está
aqui? Se você já viu isso antes, deve se lembrar que é um recurso do kernel Linux normalmente executado
pelo udevd.

Os duplos são garantidos, porque o GRUB não usa o kernel Linux (lembre-se, seu trabalho é
iniciar o kernel). A configuração que você vê consiste inteiramente em recursos e comandos internos ao
GRUB, que existe em seu próprio mundo separado.

A confusão decorre em parte do fato de que o GRUB empresta terminologia de muitas fontes. O
GRUB possui seu próprio “kernel” e seu próprio comando insmod para carregar módulos GRUB
dinamicamente, completamente independente do kernel Linux. Muitos comandos do GRUB são
semelhantes aos comandos do shell do Unix; existe até um comando ls para listar arquivos.

NOTA Existe um módulo GRUB para LVM que é necessário para inicializar sistemas onde o kernel
reside em um volume lógico. Você pode ver isso em seu sistema.

De longe, a maior confusão resulta do uso da palavra raiz pelo GRUB.


Normalmente, você pensa em root como o sistema de arquivos raiz do seu sistema. Em uma configuração
do GRUB, este é um parâmetro do kernel, localizado em algum lugar após o nome da imagem do
comando linux .

Todas as outras referências à raiz na configuração são à raiz do GRUB, que existe apenas dentro
do GRUB. A “raiz” do GRUB é o sistema de arquivos onde o GRUB procura por arquivos de imagem do
kernel e do sistema de arquivos RAM.
Na Figura 5-2, a raiz do GRUB é definida primeiro para um dispositivo específico do GRUB
(hd0,msdos1), um valor padrão para esta configuração 1. No próximo comando, o GRUB procura um
UUID específico em uma partição 2. Se ele encontra esse UUID, ele define a raiz do GRUB para essa
partição.
Para finalizar, o primeiro argumento do comando linux (/boot/vmlinuz-. . .) é a localização do
arquivo de imagem do kernel Linux 3. O GRUB carrega este arquivo da raiz do GRUB. O comando initrd
é semelhante, especificando o arquivo para o sistema de arquivos RAM inicial abordado no Capítulo 6 4.

Você pode editar esta configuração dentro do GRUB; fazer isso geralmente é a maneira mais
fácil de corrigir temporariamente uma inicialização incorreta. Para corrigir permanentemente um problema
de inicialização, você precisará alterar a configuração (consulte a Seção 5.5.2), mas, por enquanto, vamos
um passo adiante e examinemos alguns componentes internos do GRUB com a interface de linha de
comando.

5.5.1 Explorando dispositivos e partições com a linha de comando do GRUB


Como você pode ver na Figura 5-2, o GRUB tem seu próprio esquema de endereçamento de dispositivo.
Por exemplo, o primeiro disco rígido encontrado é denominado hd0, seguido por hd1 e assim por diante.
As atribuições de nome de dispositivo estão sujeitas a alterações, mas felizmente o GRUB pode
pesquisar todas as partições por UUIDs para encontrar aquela onde o kernel reside, como você acabou
de ver na Figura 5-2 com o comando search .

Como o kernel Linux inicializa 125


Machine Translated by Google

Listando dispositivos

Para ter uma ideia de como o GRUB se refere aos dispositivos em seu sistema, acesse a
linha de comando do GRUB pressionando c no menu de inicialização ou no editor de
configuração. Você deve obter o prompt do GRUB:

grub>

Você pode inserir qualquer comando aqui que você vê em uma configuração, mas para
para começar, tente um comando de diagnóstico em vez disso: ls. Sem argumentos, a saída
é uma lista de dispositivos conhecidos pelo GRUB:

grub> ls
(hd0) (hd0,msdos1)

Neste caso, há um dispositivo de disco principal denotado por (hd0) e um único


partição (hd0,msdos1). Se houvesse uma partição swap no disco, ela também apareceria,
como (hd0,msdos5). O prefixo msdos nas partições informa que o disco contém uma tabela
de partição MBR; começaria com gpt
para GPT, encontrado em sistemas UEFI. (Existem combinações ainda mais profundas
com um terceiro identificador, onde um mapa de rótulo de disco BSD reside dentro de uma
partição, mas você normalmente não terá que se preocupar com isso, a menos que esteja
executando vários sistemas operacionais em uma máquina.)
Para obter informações mais detalhadas, use ls -l. Este comando pode ser par
particularmente útil porque exibe quaisquer UUIDs dos sistemas de arquivos de partição.
Por exemplo:

grub> ls -l
Dispositivo hd0: Nenhum sistema de arquivos conhecido detectado - Tamanho do setor 512B - Tamanho total
32009856KiB
Partição hd0,msdos1: Tipo de sistema de arquivos ext* – Hora da última modificação
2019-02-14 19:11:28 quinta-feira, UUID 8b92610e-1db7-4ba3-ac2f
30ee24b39ed0 - Partição iniciada em 1024Kib - Tamanho total 32008192KiB

Este disco em particular tem um sistema de arquivos Linux ext2/3/4 na primeira partição
MBR. Os sistemas que usam uma partição swap mostrarão outra partição, mas você não
poderá dizer seu tipo a partir da saída.

Navegação de arquivos

Agora vamos ver os recursos de navegação do sistema de arquivos do GRUB. Determine a


raiz do GRUB com o comando echo (lembre-se de que é aqui que o GRUB espera encontrar
o kernel):

grub> echo $root


hd0,msdos1

Para usar o comando ls do GRUB para listar os arquivos e diretórios nessa raiz,
você pode anexar uma barra ao final da partição:

grub> ls(hd0,msdos1)/

126 Capítulo 5
Machine Translated by Google

Como é inconveniente digitar a partição raiz real, você pode substituir a variável raiz
para economizar algum tempo:

grub> ls ($root)/

A saída é uma pequena lista de nomes de arquivos e diretórios na partição


sistema de arquivos, como etc/, bin/ e dev/. Esta é agora uma função completamente
diferente do comando GRUB ls . Antes, você estava listando dispositivos, tabelas de
partições e talvez algumas informações de cabeçalho do sistema de arquivos. Agora você
está realmente olhando para o conteúdo dos sistemas de arquivos.
Você pode dar uma olhada mais profunda nos arquivos e diretórios em uma partição de
maneira semelhante. Por exemplo, para inspecionar o diretório /boot , comece com o seguinte:

grub> ls ($root)/boot

OBSERVAÇÃO Use as teclas de seta para cima e para baixo para percorrer o histórico de comandos do GRUB e as setas
para a esquerda e para a direita para editar a linha de comando atual. As teclas de linha de leitura padrão
(CTRL-N, CTRL-P e assim por diante) também funcionam.

Você também pode visualizar todas as variáveis GRUB atualmente definidas com o conjunto
comando:

grub> definir
?=0
color_highlight=preto/branco
color_normal=branco/preto
--recorte--
prefix=(hd0,msdos1)/boot/grub
raiz=hd0,msdos1

Uma das mais importantes dessas variáveis é $prefix, o sistema de arquivos e diretório
onde o GRUB espera encontrar sua configuração e suporte auxiliar. Discutiremos a
configuração do GRUB a seguir.
Depois de terminar com a interface de linha de comando do GRUB, você pode
pressionar ESC para retornar ao menu do GRUB. Alternativamente, se você definiu todas as
configurações necessárias para a inicialização (incluindo o linux e possivelmente o initrd
variáveis), você pode inserir o comando boot para inicializar essa configuração. Em qualquer
caso, inicialize seu sistema. Vamos explorar a configuração do GRUB, e isso é feito melhor
quando você tem seu sistema completo disponível.

5.5.2 Configuração do GRUB


O diretório de configuração do GRUB geralmente é /boot/ grub ou /boot/ grub2. Ele contém
o arquivo de configuração central, grub.cfg, um diretório específico da arquitetura, como
i386-pc, contendo módulos carregáveis com um sufixo .mod e alguns outros itens, como
fontes e informações de localização. Não modificaremos o grub.cfg diretamente; em vez
disso, usaremos o comando grub-mkconfig (ou grub2-mkconfig no Fedora).

Como o kernel do Linux inicializa 127


Machine Translated by Google

Revendo grub.cfg

Primeiro, dê uma olhada rápida em grub.cfg para ver como o GRUB inicializa seu menu e opções de
kernel. Você verá que o arquivo consiste em comandos GRUB, que geralmente começam com várias
etapas de inicialização seguidas por uma série de entradas de menu para diferentes configurações de
kernel e inicialização. A inicialização não é complicada, mas há muitas condicionais no início que podem
levar você a acreditar no contrário. Esta primeira parte consiste apenas em várias definições de funções,
valores padrão e comandos de configuração de vídeo, como este:

if loadfont $font ; então


definir gfxmode=auto
carregar_vídeo
insmod gfxterm
--recorte--

NOTA Muitas variáveis como $font originam-se de uma chamada load_env perto do início do
grub.cfg.

Mais adiante no arquivo de configuração, você encontrará as configurações de inicialização


disponíveis, cada uma começando com o comando menuentry . Você deve ser capaz de ler e entender
este exemplo com base no que aprendeu na seção anterior:

menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-
simple-8b92610e-1db7-4ba3-ac2f-30ee24b39ed0' {
falha de registro

carregar_vídeo
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen]; então insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod ext2
definir root='hd0,msdos1'
search --no-floppy --fs-uuid --set=root 8b92610e-1db7-4ba3-ac2f-30ee24b39ed0
linux /boot/vmlinuz-4.15.0-45-generic root=UUID=8b92610e-1db7-4ba3-ac2f-30ee24b39ed0 ro quiet splash
$vt_handoff
initrd /boot/initrd.img-4.15.0-45-generic
}

Examine seu arquivo grub.cfg para comandos de submenu contendo vários comandos de
entrada de menu . Muitas distribuições usam o comando de submenu para versões mais antigas do kernel
para que não sobrecarreguem o menu do GRUB.

Gerando um novo arquivo de configuração

Se você quiser fazer alterações em sua configuração do GRUB, não edite seu arquivo grub.cfg
diretamente, porque ele é gerado automaticamente e o sistema ocasionalmente o sobrescreve. Você
configurará sua nova configuração em outro lugar e, em seguida, executará grub-mkconfig para gerar
a nova configuração.

128 Capítulo 5
Machine Translated by Google

Para ver como funciona a geração de configuração, veja o início


ndo de grub.cfg. Deve haver linhas de comentários como esta:

### COMEÇA /etc/grub.d/00_header ###

Após uma inspeção mais detalhada, você descobrirá que quase todos os arquivos em /etc/ grub.d
é um script de shell que produz uma parte do arquivo grub.cfg . O grub-mkconfig
O comando em si é um script de shell que executa tudo em /etc/ grub.d. Lembre-se de que o próprio
GRUB não executa esses scripts no momento da inicialização; executamos os scripts no espaço do
usuário para gerar o arquivo grub.cfg que o GRUB executa.
Tente você mesmo como root. Não se preocupe em sobrescrever sua configuração atual. Este
comando por si só simplesmente imprime a configuração na saída padrão.

# grub-mkconfig

E se você quiser adicionar entradas de menu e outros comandos à configuração do GRUB?


A resposta curta é que você deve colocar suas personalizações em um novo arquivo custom.cfg
no diretório de configuração do GRUB (geralmente /boot/ grub/ custom.cfg).

A resposta longa é um pouco mais complicada. A configuração do /etc/ grub.d


tion oferece duas opções: 40_custom e 41_custom. O primeiro, 40_custom, é um script que você
mesmo pode editar, mas é o menos estável; uma atualização de pacote provavelmente destruirá
quaisquer alterações que você fizer. O 41_custom
script é mais simples; é apenas uma série de comandos que carregam custom.cfg quando o
GRUB é iniciado. Se você escolher esta segunda opção, suas alterações não aparecerão quando
você gerar seu arquivo de configuração porque o GRUB faz todo o trabalho no momento da
inicialização.

NOTA Os números na frente dos nomes dos arquivos afetam a ordem de processamento; números mais baixos vêm
primeiro no arquivo de configuração.

As duas opções para arquivos de configuração personalizados não são particularmente


extensas e não há nada que impeça você de adicionar seus próprios scripts para gerar dados de
configuração. Você pode ver algumas adições específicas para sua distribuição particular no diretório /
etc/ grub.d . Por exemplo, o Ubuntu adiciona opções de inicialização do testador de memória (memtest86+)
à configuração.
Para gravar e instalar um arquivo de configuração GRUB recém-gerado, você pode gravar a
configuração em seu diretório GRUB com a opção -o para grub-mkconfig, assim:

# grub-mkconfig -o /boot/grub/grub.cfg

Como de costume, faça backup de sua configuração antiga e verifique se você está
instalando no diretório correto.
Agora vamos entrar em alguns dos detalhes mais técnicos do GRUB e dos carregadores
de inicialização. Se você está cansado de ouvir sobre gerenciadores de inicialização e kernel, pule
para o Capítulo 6.

Como o kernel do Linux inicializa 129


Machine Translated by Google

5.5.3 Instalação do GRUB


Instalar o GRUB é mais complicado do que configurá-lo. Felizmente, você normalmente não
terá que se preocupar com a instalação porque sua distribuição deve cuidar disso para você. No
entanto, se você estiver tentando duplicar ou restaurar um disco inicializável ou preparando sua
própria sequência de inicialização, talvez seja necessário instalá-lo por conta própria.

Antes de continuar, leia a Seção 5.4 para ter uma ideia de como os PCs inicializam e
determinar se você está usando a inicialização MBR ou UEFI. Em seguida, construa o conjunto de
software GRUB e determine onde seu diretório GRUB estará; o padrão é /boot/ grub. Você pode
não precisar compilar o GRUB se sua distribuição fizer isso por você, mas se precisar, consulte o
Capítulo 16 para saber como compilar software a partir do código-fonte. Certifique-se de criar o
destino correto: é diferente para inicialização MBR ou UEFI (e há até diferenças entre EFI de 32
bits e 64 bits).

Instalando o GRUB no seu sistema

A instalação do carregador de inicialização requer que você ou um programa instalador determine


o seguinte:

•O diretório GRUB de destino conforme visto pelo seu sistema em execução no momento.
Como acabamos de mencionar, geralmente é /boot/ grub, mas pode ser diferente se você
estiver instalando o GRUB em outro disco para uso em outro sistema.

•O dispositivo atual do disco de destino do GRUB.

•Para inicialização UEFI, o ponto de montagem atual da partição do sistema EFI


(geralmente /boot/ efi).

Lembre-se que o GRUB é um sistema modular, mas para carregar os módulos, ele deve ler
o sistema de arquivos que contém o diretório GRUB. Sua tarefa é construir uma versão do GRUB
capaz de ler esse sistema de arquivos para que ele possa carregar o restante de sua configuração
(grub.cfg) e quaisquer módulos necessários.
No Linux, isso geralmente significa construir uma versão do GRUB com seu ext2.mod
módulo (e possivelmente lvm.mod) pré- carregado. Depois de ter esta versão, tudo o que você
precisa fazer é colocá-la na parte inicializável do disco e colocar o restante dos arquivos necessários
em /boot/ grub.
Felizmente, o GRUB vem com um utilitário chamado grub-install (não deve ser confundido
com install-grub, que você pode encontrar em alguns sistemas mais antigos), que executa a maior
parte do trabalho de instalação dos arquivos GRUB e configuração para você. Por exemplo, se seu
disco atual estiver em /dev/ sda e você quiser instalar o GRUB no MBR desse disco com seu
diretório /boot/ grub atual , use este comando:

# grub-install /dev/sda

AVISO A instalação incorreta do GRUB pode quebrar a sequência de inicialização em seu sistema, portanto, não leve
este comando de ânimo leve. Se você estiver preocupado, pesquise como fazer backup de seu
MBR com dd, faça backup de qualquer outro diretório GRUB atualmente instalado e certifique-se
de ter um plano de inicialização de emergência.

130 Capítulo 5
Machine Translated by Google

Instalando o GRUB usando o MBR em um dispositivo de armazenamento externo

Para instalar o GRUB em um dispositivo de armazenamento fora do sistema atual, você deve
especificar manualmente o diretório GRUB nesse dispositivo como seu sistema atual o vê agora. Por
exemplo, digamos que você tenha um dispositivo de destino de /dev/ sdc e o sistema de arquivos raiz
desse dispositivo contendo /boot (por exemplo, /dev/ sdc1) está montado em /mnt do seu sistema atual.
Isso implica que quando você instalar o GRUB, seu sistema atual verá os arquivos GRUB em /mnt/ boot/
grub. Ao executar ning grub-install, informe onde esses arquivos devem ir da seguinte maneira:

# grub-install --boot-directory=/mnt/boot /dev/sdc

Na maioria dos sistemas MBR, /boot faz parte do sistema de arquivos raiz, mas algumas
instalações colocam /boot em seu próprio sistema de arquivos separado. Certifique-se de saber onde
seu destino /boot reside.

Instalando o GRUB com UEFI

A instalação do UEFI deve ser mais fácil, porque tudo o que você precisa fazer é copiar o carregador de
inicialização no lugar. Mas você também precisa “anunciar” o carregador de inicialização para o firmware
– ou seja, salvar a configuração do carregador na NVRAM –
com o comando efibootmgr . O comando grub-install executa isso se estiver disponível, então
normalmente você pode instalar o GRUB em um sistema UEFI como este:

# grub-install --efi-directory=efi_dir –-bootloader-id=name

Aqui, efi_dir é onde o diretório UEFI aparece em seu sistema atual (geralmente /boot/ efi/ EFI,
porque a partição UEFI é normalmente montada em /boot/ efi) e name é um identificador para o
carregador de inicialização.
Infelizmente, muitos problemas podem surgir quando você está instalando um carregador de
inicialização UEFI. Por exemplo, se você estiver instalando em um disco que eventualmente terminará
em outro sistema, você precisa descobrir como anunciar esse carregador de inicialização para o firmware
do novo sistema. E há diferenças no procedimento de instalação para mídia removível.

Mas um dos maiores problemas é a inicialização segura UEFI.

5.6 Problemas de inicialização segura UEFI


Um problema mais recente que afeta as instalações do Linux é lidar com a inicialização segura
recurso encontrado em PCs recentes. Quando ativo, esse mecanismo UEFI exige que qualquer
carregador de inicialização seja assinado digitalmente por uma autoridade confiável para ser executado.
A Microsoft exigiu que os fornecedores de hardware que enviam o Windows 8 e posterior com seus
sistemas usem a inicialização segura. O resultado é que, se você tentar instalar um carregador de
inicialização não assinado nesses sistemas, o firmware rejeitará o carregador e o sistema operacional
não será carregado.
As principais distribuições do Linux não têm problemas com a inicialização segura porque
incluem carregadores de inicialização assinados, geralmente baseados em uma versão UEFI do GRUB.
Muitas vezes há um pequeno shim assinado que vai entre UEFI e GRUB; O UEFI executa o shim, que
por sua vez executa o GRUB. Proteção contra inicialização

Como o kernel do Linux inicializa 131


Machine Translated by Google

software não autorizado é um recurso importante se sua máquina não estiver em um ambiente confiável ou
precisar atender a certos requisitos de segurança, portanto, algumas distribuições vão além e exigem que
toda a sequência de inicialização (incluindo o kernel) seja assinada.

Existem algumas desvantagens para proteger os sistemas de inicialização, especialmente para


quem está experimentando construir seus próprios carregadores de inicialização. Você pode contornar o
requisito de inicialização segura desabilitando-o nas configurações de UEFI.
No entanto, isso não funcionará de forma limpa para sistemas de inicialização dupla, pois o Windows não será
executado sem a inicialização segura habilitada.

5.7 Carregamento em cadeia de outros sistemas operacionais

O UEFI torna relativamente fácil suportar o carregamento de outros sistemas operacionais porque você
pode instalar vários carregadores de inicialização na partição EFI. No entanto, o estilo MBR mais antigo não
oferece suporte a essa funcionalidade e, mesmo se você tiver UEFI, ainda poderá ter uma partição individual
com um carregador de inicialização no estilo MBR que deseja usar. Em vez de configurar e executar um kernel
Linux, o GRUB pode carregar e executar um carregador de inicialização diferente em uma partição específica
do disco; isso é chamado de carregamento em cadeia.

Para fazer o chainload, crie uma nova entrada de menu na configuração do GRUB (usando um dos
métodos descritos na seção “Gerando um novo arquivo de configuração”). Aqui está um exemplo para
uma instalação do Windows na terceira partição de um disco:

menuentry "Windows" {
cadeia insmod
insmod ntfs
definir raiz=(hd0,3)
carregador de corrente +1

A opção +1 diz ao chainloader para carregar o que estiver no primeiro setor de uma partição. Você
também pode fazer com que ele carregue diretamente um arquivo, usando uma linha como esta para carregar
o carregador do MS-DOS io.sys :

menuentry "DOS" {
cadeia insmod
gordura insmod

definir raiz=(hd0,3)
carregador de corrente /io.sys
}

5.8 Detalhes do carregador de inicialização

Agora veremos rapidamente alguns componentes internos do carregador de inicialização. Para entender
como os carregadores de inicialização como o GRUB funcionam, primeiro examinaremos como um PC
inicializa quando você o liga. Porque eles devem abordar as muitas inadequações da

132 Capítulo 5
Machine Translated by Google

Mecanismos de inicialização do PC, esquemas de carregamento de inicialização têm várias


variações, mas existem duas principais: MBR e UEFI.

5.8.1 Inicialização MBR

Além das informações de partição descritas na Seção 4.1, o MBR inclui uma pequena área de
441 bytes que o BIOS do PC carrega e executa após o POST (Power-On Self-Test). Infelizmente,
esse espaço é inadequado para abrigar quase qualquer carregador de inicialização, portanto, é
necessário espaço adicional, resultando no que às vezes é chamado de carregador de inicialização
de vários estágios. Nesse caso, a parte inicial do código no MBR não faz nada além de carregar
o restante do código do carregador de inicialização. As partes restantes do carregador de
inicialização geralmente são colocadas no espaço entre o MBR e a primeira partição do disco.
Isso não é muito seguro porque qualquer coisa pode sobrescrever o código lá, mas a maioria dos
carregadores de inicialização faz isso, incluindo a maioria das instalações do GRUB.

Esse esquema de empurrar o código do carregador de inicialização após o MBR não


funciona com um disco particionado por GPT usando o BIOS para inicializar porque as
informações do GPT residem na área após o MBR. (O GPT deixa o MBR tradicional sozinho
para compatibilidade com versões anteriores.) A solução alternativa para o GPT é criar uma
pequena partição chamada partição de inicialização do BIOS com um UUID especial
(21686148-6449-6E6F-744E-656564454649) para fornecer ao código do carregador de
inicialização completo um lugar para residir. No entanto, essa não é uma configuração comum,
porque o GPT normalmente é usado com UEFI, não com o BIOS tradicional. Geralmente é
encontrado apenas em sistemas mais antigos que possuem discos muito grandes (superiores a 2
TB); estes são muito grandes para MBR.

5.8.2 Inicialização UEFI

Fabricantes de PCs e empresas de software perceberam que o BIOS de PC tradicional é


severamente limitado, então eles decidiram desenvolver um substituto chamado Extensible
Firmware Interface (EFI), que já discutimos um pouco em alguns lugares neste capítulo. O EFI
demorou um pouco para pegar a maioria dos PCs, mas hoje é o mais comum, especialmente
agora que a Microsoft exige inicialização segura para o Windows. O padrão atual é o Unified EFI
(UEFI), que inclui recursos como um shell integrado e a capacidade de ler tabelas de partição e
navegar em sistemas de arquivos. O esquema de particionamento GPT faz parte do padrão
UEFI.

A inicialização é radicalmente diferente nos sistemas UEFI em comparação com o MBR.


Na maioria das vezes, é muito mais fácil de entender. Em vez do código de inicialização
executável que reside fora de um sistema de arquivos, sempre há um sistema de arquivos VFAT
especial chamado EFI System Partition (ESP), que contém um diretório chamado EFI. O ESP
geralmente é montado em seu sistema Linux em /boot/ efi, então você provavelmente encontrará
a maior parte da estrutura de diretórios EFI começando em /boot/
efi/ EFI. Cada carregador de inicialização tem seu próprio identificador e um subdiretório
correspondente, como efi/ microsoft, efi/ apple, efi/ ubuntu ou efi/ grub. Um arquivo de carregador
de inicialização tem uma extensão .efi e reside em um desses subdiretórios, junto com outros
arquivos de suporte. Se você explorar, poderá encontrar arquivos como grubx64.efi (a versão
EFI do GRUB) e shimx64.efi.

Como o kernel do Linux inicializa 133


Machine Translated by Google

OBSERVAÇÃO O ESP difere de uma partição de inicialização do BIOS, descrita na Seção 5.8.1, e possui
um UUID diferente. Você não deve encontrar um sistema com ambos.

Há uma ruga, porém: você não pode simplesmente colocar o código antigo do carregador de
inicialização no ESP, porque o código antigo foi escrito para a interface do BIOS. Em vez disso, você
deve fornecer um carregador de inicialização escrito para UEFI. Por exemplo, ao usar o GRUB, você
deve instalar a versão UEFI do GRUB em vez da versão do BIOS. E, conforme explicado anteriormente
em “Instalando o GRUB com UEFI”, você deve anunciar novos carregadores de inicialização para o
firmware.

Finalmente, como observado na Seção 5.6, temos que lidar com o problema da “inicialização
segura”.

5.8.3 Como o GRUB funciona

Vamos encerrar nossa discussão sobre o GRUB observando como ele funciona:

1. O BIOS ou firmware do PC inicializa o hardware e procura sua inicialização


solicite dispositivos de armazenamento para código de inicialização.

2. Ao encontrar o código de inicialização, o BIOS/firmware carrega e executa.


É aqui que o GRUB começa.
3. O núcleo do GRUB é carregado.

4. O núcleo inicializa. Neste ponto, o GRUB agora pode acessar discos e


sistemas de arquivos.

5. O GRUB identifica sua partição de inicialização e carrega uma configuração nela.

6. O GRUB dá ao usuário a chance de alterar a configuração.

7. Após um tempo limite ou ação do usuário, o GRUB executa a configuração (o


seqüência de comandos no arquivo grub.cfg , conforme descrito na Seção 5.5.2).

8. Durante a execução da configuração, o GRUB pode carregar código adicional (módulos) na


partição de inicialização. Alguns desses módulos podem ser pré-carregados.

9. O GRUB executa um comando de inicialização para carregar e executar o kernel conforme especificado
pelo comando linux da configuração.

As etapas 3 e 4 desta sequência, onde o núcleo do GRUB é carregado, podem ser


complicadas devido às inadequações dos mecanismos tradicionais de inicialização do PC.
A maior questão é “Onde está o núcleo do GRUB?” Existem três possibilidades básicas:

• Parcialmente preenchido entre o MBR e o início do primeiro


partição

•Em uma partição regular

• Em uma partição de inicialização especial: uma partição de inicialização GPT, ESP ou outro lugar

Em todos os casos, exceto onde você tem um UEFI/ESP, o BIOS do PC carrega 512 bytes do
MBR e é aí que o GRUB começa. Este pequeno pedaço (derivado de boot.img no diretório GRUB)
ainda não é o núcleo, mas contém a localização inicial do núcleo e carrega o núcleo a partir deste
ponto.

134 Capítulo 5
Machine Translated by Google

No entanto, se você tiver um ESP, o núcleo do GRUB vai para lá como um arquivo. O firmware
pode navegar no ESP e executar diretamente todo o GRUB ou qualquer outro carregador de sistema
operacional localizado lá. (Você pode ter um calço no ESP que vai logo antes do GRUB para lidar com a
inicialização segura, mas a ideia é a mesma.)
Ainda assim, na maioria dos sistemas, esta não é a imagem completa. O carregador de inicialização
também pode ser necessário carregar uma imagem inicial do sistema de arquivos RAM na memória
antes de carregar e executar o kernel. Isso é o que o parâmetro de configuração initrd especifica, e o
abordaremos na Seção 6.7. Mas antes de aprender sobre o sistema de arquivos RAM inicial, você deve
aprender sobre o início do espaço do usuário - é aí que o próximo capítulo começa.

Como o kernel Linux inicializa 135


Machine Translated by Google
Machine Translated by Google

6
COMO COMEÇA O ESPAÇO DO USUÁRIO

O ponto em que o kernel inicia o init, seu primeiro


processo no espaço do usuário, é significativo—
não apenas porque a memória e a CPU estão
finalmente prontas para a operação normal do sistema,
mas porque é aí que você pode ver como o resto do sistema se
desenvolve como um todo. Antes deste ponto, o kernel segue
um caminho de execução bem controlado definido por um número
relativamente pequeno de desenvolvedores de software. O espaço
do usuário é muito mais modular e personalizável, e também é
muito fácil ver o que acontece na inicialização e operação do
espaço do usuário. Se você estiver se sentindo um pouco
aventureiro, pode usar isso como vantagem, porque entender e
alterar a inicialização do espaço do usuário não requer
programação de baixo nível.
Machine Translated by Google

O espaço do usuário começa aproximadamente nesta ordem:

1. calor

2. Serviços essenciais de baixo nível, como udevd e syslogd


3. Configuração de rede
4. Serviços de nível médio e alto (cron, impressão e assim por diante)
5. Prompts de login, GUIs e aplicativos de alto nível, como servidores da web

6.1 Introdução ao init


init é um programa de espaço do usuário como qualquer outro programa no sistema Linux, e
você o encontrará em /sbin junto com muitos outros binários do sistema. Seu principal objetivo
é iniciar e parar os processos de serviços essenciais no sistema.

Em todas as versões atuais das principais distribuições Linux, a implementação


padrão do init é systemd. Este capítulo se concentra em como o systemd funciona e como
interagir com ele.
Existem duas outras variedades de init que você pode encontrar em sistemas mais antigos.
O init do System V é um init sequenciado tradicional (Sys V, geralmente pronunciado “sys-five”,
com origens no Unix System V), encontrado no Red Hat Enterprise Linux (RHEL) anterior à
versão 7.0 e Debian 8. Upstart é o init no Distribuições do Ubuntu anteriores à versão 15.04.

Existem outras versões do init, especialmente em plataformas embarcadas. Por


exemplo, o Android tem seu próprio init, e uma versão chamada runit é popular em sistemas
leves. Os BSDs também têm sua própria versão do init, mas é improvável que você os veja
em uma máquina Linux contemporânea. (Algumas distribuições também modificaram a
configuração de inicialização do System V para se assemelhar ao estilo BSD.)

Diferentes implementações de init foram desenvolvidas para resolver várias deficiências


no init do System V. Para entender os problemas, considere o funcionamento interno de um
init tradicional. É basicamente uma série de scripts que são executados, em sequência, um de
cada vez. Cada script geralmente inicia um serviço ou configura uma parte individual do
sistema. Na maioria dos casos, é relativamente fácil resolver dependências, além de haver muita
flexibilidade para acomodar requisitos de inicialização incomuns por meio da modificação de
scripts.
No entanto, este esquema sofre de algumas limitações significativas. Esses
podem ser agrupados em “problemas de desempenho” e “dificuldades de gerenciamento do
sistema”. Os mais importantes deles são os seguintes:

• O desempenho é prejudicado porque duas partes da sequência de inicialização não podem


normalmente executado de uma só vez.

• Gerenciar um sistema em execução pode ser difícil. Espera-se que os scripts de inicialização
iniciem daemons de serviço. Para encontrar o PID de um daemon de serviço, você precisa
usar ps, algum outro mecanismo específico para o serviço, ou um sistema semipadronizado
de registro do PID, como /var/ run/ myservice.pid.

138 Capítulo 6
Machine Translated by Google

•Os scripts de inicialização tendem a incluir muito código padrão “boilerplate”, às vezes
dificultando a leitura e compreensão do que eles fazem.
•Há pouca noção de serviços e configuração sob demanda. A maioria dos serviços inicia no
momento da inicialização; a configuração do sistema também é amplamente definida nesse
momento. Ao mesmo tempo, o daemon inetd tradicional era capaz de lidar com serviços de
rede sob demanda, mas caiu em desuso.

Os sistemas init contemporâneos lidaram com esses problemas alterando como os serviços
são iniciados, como são supervisionados e como as dependências são configuradas. Em breve
você verá como isso funciona no systemd, mas primeiro você deve ter certeza de que está
executando.

6.2 Identificando sua inicialização


Determinar a versão do init do seu sistema geralmente não é difícil. A visualização da página de
manual do init(1) normalmente informa imediatamente, mas se você não tiver certeza, verifique
seu sistema da seguinte forma:

•Se o seu sistema tem os diretórios / usr/ lib/ systemd e /etc/ systemd , você tem
systemd.
•Se você tem um diretório /etc/ init que contém vários arquivos .conf , você provavelmente está
executando o Upstart (a menos que você esteja executando o Debian 7 ou mais antigo,
nesse caso você provavelmente tem o System V init). Não abordaremos o Upstart neste
livro porque ele foi amplamente suplantado pelo systemd.
•Se nenhuma das opções acima for verdadeira, mas você tiver um arquivo /etc/ inittab ,
provavelmente está executando o System V init. Vá para a Seção 6.5.

6.3 sistema
O systemd init é uma das mais recentes implementações de init no Linux. Além de lidar com
o processo de inicialização regular, o systemd visa incorporar a funcionalidade de vários serviços
Unix padrão, como cron e inetd. Leva alguma inspiração do lançado da Apple.

Onde o systemd realmente se destaca de seus antecessores são seus recursos


avançados de gerenciamento de serviços. Ao contrário de um init tradicional, o systemd pode
rastrear daemons de serviço individuais após o início e agrupar vários processos associados a
um serviço, fornecendo mais poder e percepção sobre exatamente o que está sendo executado
no sistema.
systemd é orientado a objetivos. No nível superior, você pode pensar em definir uma
meta, chamada de unidade, para alguma tarefa do sistema. Uma unidade pode conter instruções
para tarefas comuns de inicialização, como iniciar um daemon, e também possui dependências,
que são outras unidades. Ao iniciar (ou ativar) uma unidade, o systemd tenta ativar suas
dependências e, em seguida, passa para os detalhes da unidade.

Como o espaço do usuário é iniciado 139


Machine Translated by Google

Ao iniciar os serviços, o systemd não segue uma sequência rígida; em vez disso, ele
ativa unidades sempre que elas estiverem prontas. Após a inicialização, o systemd pode
reagir a eventos do sistema (como os uevents descritos no Capítulo 3) ativando unidades
adicionais.
Vamos começar examinando uma visão de nível superior das unidades, ativação e o
processo de inicialização inicial. Então você estará pronto para ver as especificidades da
configuração de unidade e as muitas variedades de dependências de unidade. Ao longo do
caminho, você entenderá como visualizar e controlar um sistema em execução.

6.3.1 Unidades e Tipos de Unidades

Uma maneira pela qual o systemd é mais ambicioso do que as versões anteriores do init é que
ele não opera apenas processos e serviços; ele também pode gerenciar montagens de sistema
de arquivos, monitorar solicitações de conexão de rede, cronômetros de execução e muito mais.
Cada recurso é chamado de tipo de unidade e cada função específica (como um serviço) é
chamada de unidade. Quando você liga uma unidade, você a ativa . Cada unidade possui seu
próprio arquivo de configuração; exploraremos esses arquivos na Seção 6.3.3.
Estes são os tipos de unidade mais significativos que executam o boot-time
tarefas em um sistema Linux típico:

Unidades de serviço Controle os daemons de serviço encontrados em um sistema Unix.


Unidades- alvo Controle outras unidades, geralmente agrupando-as.
Unidades de soquete Representam locais de solicitação de conexão de rede de
entrada.

Unidades de montagem Representam o anexo de sistemas de arquivos ao sistema.

OBSERVAÇÃO Você pode encontrar uma lista completa de tipos de unidade na página de manual do systemd(1).

Destas, as unidades de serviço e alvo são as mais comuns e as mais fáceis.


para entender. Vamos dar uma olhada em como eles se encaixam quando você inicializa um
sistema.

6.3.2 Gráficos de inicialização e dependência de unidade

Quando você inicializa um sistema, você está ativando uma unidade padrão, normalmente
uma unidade de destino chamada default.target que agrupa um número de unidades de
serviço e montagem como dependências. Como resultado, é um pouco fácil obter uma imagem
parcial do que vai acontecer quando você inicializar. Você pode esperar que as dependências de
unidade formem uma árvore – com uma unidade no topo, ramificando-se em várias unidades
abaixo para estágios posteriores do processo de inicialização – mas na verdade elas formam um
gráfico. Uma unidade que chega tarde no processo de inicialização pode depender de várias
unidades anteriores, fazendo com que as ramificações anteriores de uma árvore de dependência
se unam novamente. Você pode até criar um gráfico de dependência com o comando systemd-
analyze dot . O gráfico inteiro é bastante grande em um sistema típico (exigindo poder
computacional significativo para renderizar) e é difícil de ler, mas existem maneiras de filtrar
unidades e zerar partes individuais.

140 Capítulo 6
Machine Translated by Google

A Figura 6-1 mostra uma parte muito pequena do gráfico de dependência para a unidade
default.target encontrada em um sistema típico. Quando você ativa essa unidade, todas as unidades
abaixo dela também são ativadas.

OBSERVAÇÃO Na maioria dos sistemas, default.target é um link para alguma outra unidade de destino de alto nível,
como uma que representa uma inicialização da interface do usuário. No sistema mostrado na Figura
6-1, default.target agrupa as unidades necessárias para iniciar uma GUI.

default.target

mutli-user.target

alvo.básico cron.service dbus.service

sysinit.target

Figura 6-1: Gráfico de dependência de unidade

Esta figura é uma visão bastante simplificada. Em seu próprio sistema, você não
acha viável esboçar as dependências apenas olhando para o arquivo de configuração da unidade na
parte superior e trabalhando para baixo. Veremos mais detalhadamente como as dependências funcionam
na Seção 6.3.6.

6.3.3 Configuração do sistema


Os arquivos de configuração do systemd estão espalhados entre muitos diretórios no sistema, portanto,
talvez seja necessário pesquisar um pouco quando estiver procurando por um arquivo específico. Existem
dois diretórios principais para configuração do systemd: o diretório da unidade do sistema (configuração
global; geralmente /lib/ systemd/ system ou /usr/ lib/ systemd/ system) e o diretório de configuração do
sistema (definições locais; geralmente /etc/ systemd/ system) ).

Para evitar confusão, siga esta regra: evite fazer alterações no diretório da unidade do sistema,
pois sua distribuição o manterá para você.
Faça suas alterações locais no diretório de configuração do sistema. Esta regra geral também se
aplica a todo o sistema. Quando tiver a opção de modificar algo em /usr e /etc, sempre altere /etc.

Como o espaço do usuário é iniciado 141


Machine Translated by Google

Você pode verificar o caminho de pesquisa de configuração do systemd atual (incluindo


ing precedência) com este comando:

$ systemctl -p UnitPath show


UnitPath=/etc/systemd/system.control/run/systemd/system.control/run/systemd/
transitório /etc/systemd/system /run/systemd/system /run/systemd/generator /lib/
systemd/system/run/systemd/generator.late

Para ver a unidade do sistema e os diretórios de configuração em seu sistema, use os


seguintes comandos:

$ pkg-config systemd --variable=systemdsystemunitdir


/lib/systemd/system
$ pkg-config systemd --variable=systemdsystemconfdir
/etc/systemd/system

Arquivos de unidade

O formato dos arquivos de unidade é derivado da especificação XDG Desktop Entry (usada para
arquivos .desktop , que são muito semelhantes aos arquivos .ini em sistemas Microsoft), com
nomes de seção entre colchetes ([]) e atribuições de variáveis e valores ( opções) em cada seção.

Como exemplo, considere o arquivo de unidade dbus-daemon.service para o daemon de


barramento de desktop:

[Unidade]
Description=D-Bus Barramento de Mensagens do Sistema
Documentation=man:dbus-daemon(1)
Requer=dbus.socket
RefuseManualStart=sim

[Serviço]
ExecStart=/usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-
activation --syslog-only
ExecReload=/usr/bin/dbus-send --print-reply --system --type=method_call --dest=
org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig

Existem duas seções, [Unidade] e [Serviço]. A seção [Unit] fornece alguns detalhes sobre a
unidade e contém informações de descrição e dependência. Em particular, esta unidade requer a
unidade dbus.socket como uma dependência.
Em uma unidade de serviço como esta, você encontrará os detalhes sobre o serviço na seção
[Serviço] , incluindo como preparar, iniciar e recarregar o serviço. Você encontrará uma lista completa
nas páginas de manual systemd.service(5) e systemd.exec(5), bem como na discussão do rastreamento
de processos na Seção 6.3.5.
Muitos outros arquivos de configuração de unidade são igualmente simples. Por exemplo, o
arquivo de unidade de serviço sshd.service habilita logins remotos de shell seguros iniciando sshd.

142 Capítulo 6
Machine Translated by Google

OBSERVAÇÃO Os arquivos de unidade encontrados em seu sistema podem ser ligeiramente diferentes. Neste exemplo, você viu
que o Fedora usa o nome dbus-daemon.service, e o Ubuntu usa dbus.service.
Pode haver alterações nos arquivos reais também, mas geralmente são superficiais.

Variáveis

Muitas vezes você encontrará variáveis dentro de arquivos de unidade. Aqui está uma seção de um arquivo

de unidade diferente, este para o shell seguro que você aprenderá no Capítulo 10:

[Serviço]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY
ExecReload=/bin/kill -HUP $MAINPID

Tudo que começa com um cifrão ($) é uma variável. Embora essas variáveis tenham a mesma sintaxe,
suas origens são diferentes. As opções $OPTIONS e $CRYPTO_POLICY , que você pode passar para sshd
na ativação da unidade, são definidas no arquivo especificado pela configuração EnvironmentFile . Neste
caso em particular, você pode olhar em /etc/ sysconfig/ sshd para determinar se as variáveis estão configuradas
e, em caso afirmativo, quais são seus valores.

Em comparação, $MAINPID contém o ID do processo rastreado do serviço (consulte a Seção 6.3.5).


Após a ativação da unidade, o systemd registra e armazena esse PID para que você possa usá-lo para
manipular um processo específico do serviço posteriormente. O arquivo de unidade sshd.service usa
$MAINPID para enviar um sinal de desligamento (HUP) para sshd quando você deseja recarregar a
configuração (esta é uma técnica muito comum para lidar com recarregamentos e reiniciar daemons Unix).

Especificadores

Um especificador é um recurso semelhante a uma variável frequentemente encontrado em arquivos de


unidade. Os especificadores começam com um sinal de porcentagem (%). Por exemplo, o especificador
%n é o nome da unidade atual e o especificador %H é o nome do host atual.
Você também pode usar especificadores para criar várias cópias de uma unidade de um único
arquivo de unidade. Um exemplo é o conjunto de processos getty que controlam os prompts de login em
consoles virtuais, como tty1 e tty2. Para usar esse recurso, adicione um símbolo @ ao final do nome da
unidade, antes do ponto no nome do arquivo da unidade.

Por exemplo, o nome do arquivo da unidade getty é getty@.service na maioria das distribuições,
permitindo a criação dinâmica de unidades, como getty@tty1 e getty@tty2. Qualquer coisa após o @ é
chamada de instância. Ao examinar um desses arquivos de unidade, você também poderá ver um
especificador %I ou %i . Ao ativar um serviço de um arquivo de unidade com instâncias, o systemd substitui
o especificador %I ou %i pela instância para criar o novo nome de serviço.

Como o espaço do usuário é iniciado 143


Machine Translated by Google

6.3.4 Operação do sistema


Você interagirá com o systemd principalmente por meio do comando systemctl , que
permite ativar e desativar serviços, listar status, recarregar a configuração e muito mais.

Os comandos mais essenciais ajudam você a obter informações da unidade. Por


exemplo, para visualizar uma lista de unidades ativas em seu sistema, emita um comando
list-units . (Este é o comando padrão para systemctl, portanto, tecnicamente, você não
precisa do argumento list-units .)

$ systemctl lista-unidades

O formato de saída é típico de um comando de listagem de informações do Unix.


Por exemplo, o cabeçalho e a linha para -.mount (o sistema de arquivos raiz) são assim:

UNIT LOAD ACTIVE SUB DESCRIÇÃO

-.mount carregado ativo montado Root Mount

Por padrão, systemctl list-units produz muita saída, porque um sistema típico tem
várias unidades ativas, mas ainda é uma forma abreviada porque systemctl trunca qualquer
nome de unidade muito grande. Para ver os nomes completos das unidades, use a opção --
full , e para ver todas as unidades (não apenas as que estão ativas), use a opção --all .

Uma operação systemctl particularmente útil é obter o status de uma unidade


específica. Por exemplo, aqui está um comando de status típico e algumas de suas
saídas:

$ systemctl status sshd.service


· sshd.service - servidor OpenBSD Secure Shell
Carregado: carregado (/usr/lib/systemd/system/sshd.service; ativado; predefinição do
fornecedor: ativado)
Ativo: ativo (em execução) desde sex 2021-04-16 08:15:41 EDT; 1 meses 1 dias atrás

PID principal: 1110 (sshd)


Tarefas: 1 (limite: 4915)
CGroup: /system.slice/sshd.service
ÿ1110 /usr/sbin/sshd -D

Várias mensagens de log também podem seguir essa saída. Se você está acostumado
um sistema init tradicional, você pode se surpreender com a quantidade de informações
úteis disponíveis neste único comando. Você obtém não apenas o estado da unidade,
mas também os processos associados ao serviço, quando a unidade foi iniciada e várias
mensagens de log, se disponíveis.
A saída para outros tipos de unidade inclui informações úteis semelhantes; por exemplo,
a saída das unidades de montagem inclui quando a montagem aconteceu, a linha de
comando exata usada para ela e seu status de saída.
Uma parte interessante da saída é o nome do grupo de controle (cgroup).
No exemplo anterior, o grupo de controle é /system.slice/sshd.service, e os processos
no cgroup são mostrados abaixo dele. No entanto, você também pode

144 Capítulo 6
Machine Translated by Google

veja grupos de controle nomeados começando com systemd:/system se os processos de uma unidade
(por exemplo, uma unidade de montagem) já tiverem terminado. Você pode visualizar cgroups
relacionados ao systemd sem o restante do status da unidade com o comando systemd cgls . Você
aprenderá mais sobre como o systemd usa cgroups na Seção 6.3.5, e como os cgroups funcionam na
Seção 8.6.
O comando status também exibe apenas o log de diagnóstico mais recente
mensagens para a unidade. Você pode ver todas as mensagens de uma unidade como esta:

$ journalctl --unit=unit_name

Você aprenderá muito mais sobre journalctl no Capítulo 7.

OBSERVAÇÃO Dependendo do sistema e da configuração do usuário, você pode precisar de privilégios de


superusuário para executar journalctl.

Como os trabalhos se relacionam com as unidades de partida, parada e recarga

Para ativar, desativar e reiniciar unidades, use os comandos systemctl start, systemctl stop e systemctl
restart. No entanto, se você alterou um arquivo de configuração de unidade, você pode dizer ao systemd
para recarregar o arquivo de duas maneiras:

systemctl reload unit Recarrega apenas a configuração da unidade.


systemctl daemon-reload Recarrega todas as configurações da unidade.

Solicitações para ativar, reativar e reiniciar unidades são chamadas de jobs em systemd,
e são essencialmente mudanças de estado unitário. Você pode verificar os trabalhos atuais em um
sistema com:

$ systemctl list-jobs

Se um sistema estiver ativo por algum tempo, você pode esperar que não haja trabalhos ativos
porque todas as ativações necessárias para iniciar o sistema devem ser concluídas. No entanto, no
momento da inicialização, às vezes você pode efetuar login rápido o suficiente para ver os trabalhos de
unidades que iniciam muito lentamente. Por exemplo:

JOB UNIT TIPO ESTADO

1 graphical.target 2 início esperando


multi-user.target start 71 espera
systemd-...nlevel.service start 75 sm- espera
client.service start 76 sendmail.service start espera
corrida
120 systemd-...ead-done.timer start espera

Nesse caso, a tarefa 76, a inicialização da unidade sendmail.service , está demorando muito.
Os outros trabalhos listados estão em estado de espera, provavelmente porque todos estão aguardando
o trabalho 76. Quando sendmail.service terminar de iniciar e estiver totalmente ativo, o trabalho 76 será
concluído, o restante dos trabalhos também será concluído e o trabalho lista estará vazia.

Como o espaço do usuário é iniciado 145


Machine Translated by Google

OBSERVAÇÃO O termo trabalho pode ser confuso, especialmente porque alguns outros sistemas init o utilizam para se
referir a recursos que são mais parecidos com unidades systemd. Esses trabalhos também não têm nada a
ver com o controle de trabalho do shell.

Consulte a Seção 6.6 para saber como desligar e reinicializar o sistema.

Adicionando unidades ao systemd

Adicionar unidades ao systemd é principalmente uma questão de criar, ativar e possivelmente habilitar
arquivos de unidade. Você normalmente deve colocar seus próprios arquivos de unidade no diretório de
configuração do sistema (/ etc/ systemd/ system) para que você não os confunda com nada que veio com sua
distribuição e para que a distribuição não os sobrescreva quando você atualizar.

Como é fácil criar unidades de destino que na verdade não fazem nada ou interferem no seu sistema,
experimente. Para criar dois destinos, um com dependência do outro, siga estas etapas:

1. Crie um arquivo de unidade chamado test1.target em /etc/ systemd/ system:

[Unidade]
Descrição=teste 1

2. Crie um arquivo test2.target com uma dependência em test1.target:

[Unidade]
Descrição=teste 2
Quer=teste1.destino

A palavra-chave Wants aqui define uma dependência que faz com que test1.target seja ativado quando
você ativa test2.target. Ative a unidade test2.target para vê-la em ação:

# systemctl start test2.target

3. Verifique se ambas as unidades estão ativas:

# systemctl status test1.target test2.target


· teste1.destino - teste 1
Carregado: carregado (/etc/systemd/system/test1.target; estático; predefinição do
fornecedor: ativado)
Ativo: ativo desde ter 2019-05-28 14:45:00 EDT; 16s atrás

28 de maio 14:45:00 duplex systemd[1]: Alcançou o teste de destino 1.

· test2.target - teste 2
Carregado: carregado (/etc/systemd/system/test2.target; estático; predefinição do
fornecedor: ativado)
Ativo: ativo desde ter 2019-05-28 14:45:00 EDT; 17s atrás

146 Capítulo 6
Machine Translated by Google

4. Se o seu arquivo de unidade tiver uma seção [Instalar] , você precisa “habilitar” a unidade antes de
ativá-la:

# systemctl habilita unidade

A seção [Install] é outra maneira de criar uma dependência. Nós vamos olhar
nele (e dependências como um todo) com mais detalhes na Seção 6.3.6.

Removendo unidades do systemd

Para remover uma unidade, siga estas etapas:

1. Desative a unidade, se necessário:

# systemctl unidade de parada

2. Se a unidade tiver uma seção [Install] , desative a unidade para remover quaisquer links simbólicos
criados pelo sistema de dependência:

# systemctl desabilita unidade

Você pode remover o arquivo de unidade, se desejar.

OBSERVAÇÃO A desativação de uma unidade que está habilitada implicitamente (ou seja, não tem uma seção [Install] )
não tem efeito.

6.3.5 Rastreamento e Sincronização de Processos do sistema

O systemd quer uma quantidade razoável de informações e controle sobre cada processo que inicia.
Isso tem sido difícil historicamente. Um serviço pode ser iniciado de diferentes maneiras; ele poderia
bifurcar novas instâncias de si mesmo ou até mesmo daemonizar e separar-se do processo original.
Também não há como dizer quantos subprocessos o servidor pode gerar.

Para gerenciar unidades ativadas facilmente, o systemd usa os cgroups mencionados


anteriormente, um recurso do kernel Linux que permite um rastreamento mais preciso de uma hierarquia
de processos. O uso de cgroups também ajuda a minimizar o trabalho que um desenvolvedor ou
administrador de pacotes precisa fazer para criar um arquivo de unidade de trabalho. No systemd, você
não precisa se preocupar em contabilizar todos os possíveis comportamentos de inicialização; tudo o que
você precisa saber é se um processo de inicialização de serviço se bifurca. Use a opção Tipo em seu
arquivo de unidade de serviço para indicar o comportamento de inicialização. Existem dois estilos básicos
de inicialização:

Type=simples O processo de serviço não bifurca e termina; continua a ser o principal processo de
serviço.

Type=forking O serviço bifurca e o systemd espera que o processo de serviço original termine.
Após esse término, o systemd assume que o serviço está pronto.

Como o espaço do usuário é iniciado 147


Machine Translated by Google

A opção Type=simple não leva em conta o fato de que um serviço pode levar algum tempo
para iniciar e, como resultado, o systemd não sabe quando iniciar quaisquer unidades dependentes
que exigem absolutamente que tal serviço esteja pronto. Uma maneira de lidar com isso é usar a
inicialização atrasada (consulte a Seção 6.3.7). No entanto, alguns estilos de inicialização do tipo
podem indicar que o próprio serviço notificará o systemd quando estiver pronto:

Type=notify Quando estiver pronto, o serviço envia uma notificação específica ao


systemd com uma chamada de função especial.
Type=dbus Quando pronto, o serviço se registra no D-Bus (Desktop Bus).

Outro estilo de inicialização de serviço é especificado com Type=oneshot; aqui, o processo


de serviço termina completamente sem nenhum processo filho após o início. É como Type=simple,
exceto que o systemd não considera o serviço a ser iniciado até que o processo do serviço termine.
Quaisquer dependências estritas (que você verá em breve) não serão iniciadas até o término. Um
serviço usando Type=oneshot também obtém uma diretiva padrão RemainAfterExit=yes para que
o systemd considere um serviço como ativo mesmo após o término de seus processos.

Uma opção final é Type=idle. Isso funciona como o estilo simples , mas instrui
systemd para não iniciar o serviço até que todos os trabalhos ativos terminem. A ideia aqui é
apenas atrasar o início de um serviço até que outros serviços comecem a impedir que os serviços
interfiram na saída uns dos outros. Lembre-se de que, uma vez iniciado um serviço, o trabalho do
systemd que o iniciou é encerrado, portanto, aguardar o término de todos os outros trabalhos
garante que nada mais seja iniciado.
Se você estiver interessado em como os cgroups funcionam, vamos explorá-los com
mais detalhes na Seção 8.6.

6.3.6 Dependências do sistema


Um sistema flexível para dependências operacionais e de tempo de inicialização requer
algum grau de complexidade, porque regras excessivamente rígidas podem causar baixo
desempenho e instabilidade do sistema. Por exemplo, digamos que você queira exibir um
prompt de login após iniciar um servidor de banco de dados, para definir uma dependência
estrita do prompt de login para o servidor de banco de dados. Isso significa que se o servidor de
banco de dados falhar, o prompt de login também falhará e você nem poderá fazer login em sua
máquina para corrigir o problema!
As tarefas de inicialização do Unix são bastante tolerantes a falhas e muitas vezes podem
falhar sem causar problemas sérios para serviços padrão. Por exemplo, se você removeu o disco
de dados de um sistema, mas deixou sua entrada /etc/ fstab (ou unidade de montagem em
systemd), a montagem do sistema de arquivos em tempo de inicialização falharia. Embora essa
falha possa afetar os servidores de aplicativos (como servidores da Web), ela normalmente não
afetaria a operação padrão do sistema.
Para acomodar a necessidade de flexibilidade e tolerância a falhas, o systemd oferece
vários tipos e estilos de dependência. Vejamos primeiro os tipos básicos, rotulados por sua sintaxe
de palavra-chave:

Requer dependências estritas. Ao ativar uma unidade com Requer


unidade de dependência, o systemd tenta ativar a unidade de dependência. Se a unidade
de dependência falhar, o systemd também desativa a unidade dependente.

148 Capítulo 6
Machine Translated by Google

Quer Dependências apenas para ativação. Ao ativar uma unidade, o systemd ativa
as dependências Wants da unidade , mas não se importa se essas dependências falharem.

Unidades necessárias que já devem estar ativas. Antes de ativar uma unidade com
uma dependência Requisite , o systemd primeiro verifica o status da dependência. Se a
dependência não foi ativada, o systemd falha na ativação da unidade com a dependência.

Conflicts Dependências negativas. Ao ativar uma unidade com um


Dependência de conflito , o systemd desativa automaticamente a dependência oposta se
estiver ativa. A ativação simultânea de unidades conflitantes falha.

O tipo de dependência Wants é especialmente significativo porque não


propagar falhas para outras unidades. A página de manual systemd.service(5) afirma que é
assim que você deve especificar as dependências, se possível, e é fácil ver o porquê. Esse
comportamento produz um sistema muito mais robusto, oferecendo o benefício de um init
tradicional, em que a falha de um componente de inicialização anterior não necessariamente
proíbe a inicialização de componentes posteriores.
Você pode visualizar as dependências de uma unidade com o comando systemctl , desde que
conforme você especifica um tipo de dependência, como Deseja ou Requer:

# systemctl show -p tipo unidade

Encomenda

Até agora, a sintaxe de dependência que você viu não especificou explicitamente a ordem.
Por exemplo, ativar a maioria das unidades de serviço com dependências Requires ou Wants faz
com que essas unidades sejam iniciadas ao mesmo tempo. Isso é ideal, porque você deseja iniciar
o maior número possível de serviços o mais rápido possível para reduzir o tempo de inicialização.
No entanto, existem situações em que uma unidade deve iniciar após a outra. Por exemplo, no
sistema no qual a Figura 6-1 é baseada, a unidade default.target é definida para iniciar após multi-
user.target (essa distinção de ordem não é mostrada na figura).
Para ativar unidades em uma ordem específica, use os seguintes modificadores de
dependência:

Antes A unidade atual será ativada antes da(s) unidade(s) listada(s). Por exemplo, se
Before=bar.target aparecer em foo.target, o systemd ativa foo.target antes de bar.target.

Após A unidade atual é ativada após a(s) unidade(s) listada(s).

Quando você usa o pedido, o systemd espera até que uma unidade tenha um status ativo
antes de ativar suas unidades dependentes.

Dependências padrão e implícitas

Conforme você explora dependências (especialmente com systemd-analyze), você pode


começar a perceber que algumas unidades adquirem dependências que não são explicitamente
declaradas em arquivos de unidade ou outros mecanismos visíveis. É mais provável que você
encontre isso em unidades de destino com dependências de desejos - você descobrirá que

Como o Espaço do Usuário é Iniciado 149


Machine Translated by Google

O systemd adiciona um modificador After ao lado de qualquer unidade listada como uma dependência
Wants . Essas dependências adicionais são internas ao systemd, calculadas no momento da
inicialização e não armazenadas em arquivos de configuração.
O modificador After adicionado é chamado de dependência padrão, uma adição automática à
configuração da unidade destinada a evitar erros comuns e manter os arquivos da unidade pequenos.
Essas dependências variam de acordo com o tipo de unidade. Por exemplo, o systemd não adiciona
as mesmas dependências padrão para unidades de destino como para unidades de serviço. Essas
diferenças estão listadas nas seções DEFAULT DEPENDENCES das páginas do manual de
configuração da unidade, como systemd.service(5) e systemd.target(5).

Você pode desabilitar uma dependência padrão em uma unidade adicionando


DefaultDependencies=no ao seu arquivo de configuração.

Dependências Condicionais

Você pode usar vários parâmetros de dependência condicional para testar vários estados do sistema
operacional em vez de unidades systemd. Por exemplo:

ConditionPathExists=p Verdadeiro se o caminho (do arquivo) p existir no sistema.

ConditionPathIsDirectory=p Verdadeiro se p for um diretório.

ConditionFileNotEmpty=p Verdadeiro se p for um arquivo e não tiver comprimento zero.

Se uma dependência condicional em uma unidade for falsa quando o systemd tentar ativar a
unidade, a unidade não será ativada, embora isso se aplique apenas à unidade na qual ela aparece.
Ou seja, se você ativar uma unidade que tenha uma dependência condicional e algumas dependências
de unidade, o systemd tentará ativar essas dependências de unidade independentemente de a condição
ser verdadeira ou falsa.
Outras dependências são principalmente variações das anteriores.
Por exemplo, a dependência RequiresOverridable é como Requires quando executada normalmente,
mas age como uma dependência Wants se uma unidade for ativada manualmente. Para obter uma
lista completa, consulte a página de manual do systemd.unit(5).

A Seção [Instalar] e Unidades de Habilitação

Até agora, vimos como definir dependências no arquivo de configuração de uma unidade dependente.
Também é possível fazer isso “ao contrário” — ou seja, especificando a unidade dependente no arquivo
de unidade de uma dependência. Você pode fazer isso adicionando um parâmetro WantedBy ou
RequiredBy na seção [Install] . Este mecanismo permite que você altere quando uma unidade deve iniciar
sem modificar arquivos de configuração adicionais (por exemplo, quando você prefere não editar um
arquivo de unidade do sistema).
Para ver como isso funciona, considere as unidades de exemplo na Seção 6.3.4.
Tínhamos duas unidades, test1.target e test2.target, com test2.target tendo um Wants
dependência de test1.target. Podemos alterá-los para que test1.target fique assim:

[Unidade]
Descrição=teste 1

[Instalar]
WantedBy=test2.target

150 Capítulo 6
Machine Translated by Google

E test2.target é o seguinte:

[Unidade]
Descrição=teste 2

Como agora você tem uma unidade com uma seção [Install] , você precisa habilitar a
unidade com systemctl antes de poder iniciá-la. Veja como isso funciona com test1.target:

# systemctl habilita test1.target


Link simbólico criado /etc/systemd/system/test2.target.wants/test1.target ÿ /etc/
systemd/system/test1.target.

Observe a saída aqui—o efeito de habilitar uma unidade é criar um link simbólico em
um subdiretório .wants correspondente à unidade dependente (test2.target neste caso). Agora
você pode iniciar ambas as unidades ao mesmo tempo com systemctl start test2.target porque a
dependência está em vigor.

NOTA A ativação de uma unidade não a ativa.

Para desabilitar a unidade (e remover o link simbólico), use systemctl da seguinte


forma:

# systemctl desabilita test1.target


Removido /etc/systemd/system/test2.target.wants/test1.target.

As duas unidades neste exemplo também lhe dão a chance de experimentar


com diferentes cenários de inicialização. Por exemplo, veja o que acontece quando você
tenta iniciar apenas test1.target ou quando tenta iniciar test2.target sem habilitar test1.target.
Ou tente alterar WantedBy para RequiredBy. (Lembre-se, você pode verificar o status de uma
unidade com o status systemctl.)
Durante a operação normal, o systemd ignora a seção [Install] em um
unidade, mas observa sua presença e, por padrão, considera a unidade desabilitada. A
ativação de uma unidade sobrevive a reinicializações.
A seção [Install] geralmente é responsável pelos .wants e .requires
diretórios no diretório de configuração do sistema (/ etc/ systemd/ system).
No entanto, o diretório de configuração da unidade ([/ usr]/ lib/ systemd/ system) também contém
diretórios .wants , e você também pode adicionar links que não correspondem às seções [Install]
nos arquivos da unidade. Essas adições manuais são uma maneira simples de adicionar uma
dependência sem modificar um arquivo de unidade que pode ser sobrescrito no futuro (por uma
atualização de software, por exemplo), mas não são particularmente incentivadas porque uma
adição manual é difícil de rastrear.

6.3.7 Inicialização sob demanda e paralelizada de recursos do sistema


Um dos recursos do systemd é a capacidade de atrasar a inicialização de uma unidade até que ela seja
absolutamente necessária. A configuração normalmente funciona assim:

1. Você cria uma unidade do sistema (chame-a de Unidade A) para o serviço do sistema que
deseja fornecer.

Como o espaço do usuário é iniciado 151


Machine Translated by Google

2. Você identifica um recurso do sistema, como uma porta/soquete de rede, arquivo ou dispositivo,
que a Unidade A usa para oferecer seus serviços.

3. Você cria outra unidade systemd, Unidade R, para representar esse recurso.
Essas unidades são classificadas em tipos, como unidades de soquete, unidades de caminho e
unidades de dispositivo.

4. Você define o relacionamento entre a Unidade A e a Unidade R. Normalmente, isso é implícito com
base nos nomes das unidades, mas também pode ser explícito, como veremos em breve.

Uma vez no lugar, a operação prossegue da seguinte forma:

1. Após a ativação da Unidade R, o systemd monitora o recurso.

2. Quando qualquer coisa tenta acessar o recurso, o systemd bloqueia o recurso e a entrada
para o recurso é armazenada em buffer.

3. systemd ativa a Unidade A.

4. Quando estiver pronto, o serviço da Unidade A assume o controle do recurso,


lê a entrada em buffer e executa normalmente.

Existem algumas preocupações aqui:

•Você deve certificar-se de que sua unidade de recursos cobre todos os recursos que o serviço fornece.
Isso normalmente não é um problema, porque a maioria dos serviços tem apenas um ponto de
acesso.

•Você precisa garantir que sua unidade de recurso esteja vinculada à unidade de serviço que ela
representa. Isso pode ser implícito ou explícito e, em alguns casos, muitas opções representam
maneiras diferentes de o systemd realizar a transferência para a unidade de serviço.

• Nem todos os servidores sabem como interagir com as unidades de recursos do sistema
pode fornecer.

Se você já sabe o que os utilitários tradicionais como inetd, xinetd e automount fazem, verá
muitas semelhanças. De fato, o conceito não é nada novo; systemd ainda inclui suporte para unidades
de montagem automática.

Um exemplo de unidade de soquete e

serviço Vejamos um exemplo, um serviço de eco de rede simples. Este é um material um tanto
avançado, e você pode não entendê-lo completamente até ler a discussão sobre TCP, portas e escuta
no Capítulo 9 e soquetes no Capítulo 10, mas você deve ser capaz de obter a idéia básica.

A ideia de um serviço de eco é repetir tudo o que um cliente de rede envia após a conexão; o
nosso escutará na porta TCP 22222. Começaremos a construí-lo com uma unidade de soquete para
representar a porta, conforme mostrado no seguinte echo.socket
arquivo da unidade:

[Unidade]
Descrição=soquete de eco

152 Capítulo 6
Machine Translated by Google

[Soquete]
ListenStream=22222
Aceitar=verdadeiro

Observe que não há menção à unidade de serviço que esse soquete suporta dentro do
arquivo de unidade. Então, qual é o arquivo de unidade de serviço correspondente?
Seu nome é echo@.service. O link é estabelecido por convenção de nomenclatura;
se um arquivo de unidade de serviço tiver o mesmo prefixo de um arquivo .socket (neste caso,
echo), o systemd saberá ativar essa unidade de serviço quando houver atividade na unidade de
soquete. Nesse caso, o systemd cria uma instância de echo@.service quando há atividade em
echo.socket. Aqui está o arquivo de unidade echo@.service :

[Unidade]
Descrição=serviço de eco

[Serviço]
ExecStart=/bin/cat
StandardInput=soquete

OBSERVAÇÃO Se você não gostar da ativação implícita de unidades com base nos prefixos ou precisar
vincular unidades com prefixos diferentes, poderá usar uma opção explícita na unidade que define
seu recurso. Por exemplo, use Socket=bar.socket dentro de foo.service para que bar.socket passe
seu soquete para foo.service.

Para executar esta unidade de exemplo, você precisa iniciar a unidade echo.socket :

# systemctl inicia echo.socket

Agora você pode testar o serviço conectando-se à sua porta TCP local 22222
com um utilitário como o telnet. O serviço repete o que você digita; aqui está um exemplo de
interação:

$ telnet localhost 22222


Tentando 127.0.0.1...
Conectado ao localhost.
O caractere de escape é '^]'.
Olá.
Olá.

Quando você estiver entediado com isso e quiser voltar ao seu shell, pressione CTRL-] em
uma linha por si só e, em seguida, pressione CTRL-D. Para interromper o serviço, pare a unidade
de soquete da seguinte forma:

# systemctl stop echo.socket

NOTA O telnet pode não ser instalado por padrão em sua distribuição.

Como o espaço do usuário é iniciado 153


Machine Translated by Google

Instâncias e transferência

Como a unidade echo@.service suporta várias instâncias simultâneas, há um @ no nome (lembre-


se de que o especificador @ significa parametrização). Por que você quer várias instâncias? Digamos
que você tenha mais de um cliente de rede se conectando ao serviço ao mesmo tempo e queira que
cada conexão tenha sua própria instância. Nesse caso, a unidade de serviço deve oferecer suporte a
várias instâncias porque incluímos o Accept=true

opção em echo.socket. Essa opção instrui o systemd não apenas a escutar na porta, mas também
a aceitar conexões de entrada em nome da unidade de serviço e passá-las para eles, criando uma
instância separada para cada conexão.
Cada instância lê os dados da conexão como entrada padrão, mas não necessariamente precisa
saber que os dados vêm de uma conexão de rede.

OBSERVAÇÃO A maioria das conexões de rede requer mais flexibilidade do que apenas um gateway simples para
entrada e saída padrão, portanto, não espere poder criar serviços de rede complexos com um arquivo
de unidade de serviço como o arquivo de unidade echo@.service mostrado aqui.

Se uma unidade de serviço puder fazer o trabalho de aceitar uma conexão, não coloque um @
em seu nome de arquivo de unidade e não coloque Accept=true na unidade de soquete. Nesse caso, a
unidade de serviço assume o controle completo do soquete do systemd, que por sua vez não tenta
escutar a porta de rede novamente até que a unidade de serviço termine.

Os muitos recursos e opções diferentes de transferência para unidades de serviço tornam difícil
fornecer um resumo categórico. Não só isso, mas a documentação das opções está espalhada por
várias páginas de manual.
Para as unidades orientadas a recursos, verifique systemd.socket(5), systemd.path(5) e
systemd.device(5). Um documento muitas vezes esquecido para unidades de serviço é o
systemd.exec(5), que contém informações sobre como a unidade de serviço pode esperar receber um
recurso na ativação.

Otimização de inicialização com unidades auxiliares

Um objetivo geral do systemd é simplificar a ordem de dependência e acelerar o tempo de inicialização.


Unidades de recursos, como unidades de soquete, fornecem uma maneira de fazer isso semelhante à
inicialização sob demanda. Ainda teremos uma unidade de serviço e uma unidade auxiliar representando
o recurso oferecido pela unidade de serviço, exceto que, neste caso, o systemd inicia a unidade de
serviço assim que ativa a unidade auxiliar, em vez de aguardar uma solicitação.

A razão para este esquema é que as unidades essenciais de serviço de inicialização, como
como systemd-journald.service leva algum tempo para iniciar, e muitas outras unidades dependem
deles. No entanto, o systemd pode oferecer o recurso essencial de uma unidade (como uma unidade
de soquete) muito rapidamente e, em seguida, pode ativar imediatamente não apenas a unidade
essencial, mas também qualquer unidade que dependa dela. Uma vez que a unidade essencial
esteja pronta, ela assume o controle do recurso.
A Figura 6-2 mostra como isso pode funcionar em um sistema sequencial tradicional.
Nesta linha do tempo de inicialização, o Serviço E fornece um Recurso R essencial. Os Serviços A, B
e C dependem desse recurso (mas não um do outro) e devem

154 Capítulo 6
Machine Translated by Google

aguarde até que o Serviço E tenha iniciado. Como o sistema não iniciará um novo serviço até
que termine de iniciar o anterior, leva muito tempo para iniciar o Serviço C.

Serviço E

Iniciando Iniciado; Recurso R pronto

Serviço A

Iniciando Iniciado

Serviço B

Iniciando Iniciado

Serviço C

Iniciando

Figura 6-2: Linha do tempo de inicialização sequencial com uma dependência de recursos

A Figura 6-3 mostra uma possível configuração de inicialização do systemd equivalente.


Os serviços são representados pelas Unidades A, B, C e E, com uma nova Unidade R
representando o recurso que a Unidade E fornece. Como o systemd pode fornecer uma interface
para a Unidade R enquanto a Unidade E inicia, as Unidades A, B, C e E podem ser iniciadas ao
mesmo tempo. Quando estiver pronto, a Unidade E assume o lugar da Unidade R.
Um ponto interessante aqui é que a Unidade A, B ou C pode não precisar acessar o recurso que a
Unidade R fornece antes de terminar a inicialização. O que estamos fazendo é oferecer a eles a
opção de começar a acessar o recurso o mais rápido possível.

Unidade R

Disponível

Unidade E

Iniciando Iniciado; assume a Unidade R

Unidade A

Iniciando Iniciado

Unidade B

Iniciando Iniciado

Unidade C

Iniciando Iniciado

Figura 6-3: linha do tempo de inicialização do systemd com uma unidade de recurso

Como o espaço do usuário é iniciado 155


Machine Translated by Google

OBSERVAÇÃO Quando você paraleliza a inicialização assim, há uma chance de seu sistema ficar lento
para baixo temporariamente devido a um grande número de unidades começando ao mesmo tempo.

A conclusão é que, embora você não esteja criando uma inicialização de unidade sob
demanda neste caso, você está usando os mesmos recursos que possibilitam a inicialização sob
demanda. Para exemplos comuns do mundo real, consulte as unidades de configuração journald
e D-Bus em uma máquina executando systemd; é muito provável que sejam paralelizados dessa
maneira.

6.3.8 Componentes Auxiliares do sistema


À medida que o systemd cresceu em popularidade, ele cresceu para incluir suporte para algumas tarefas
não relacionadas à inicialização e gerenciamento de serviços, tanto diretamente quanto por meio de
camadas de compatibilidade auxiliares. Você pode notar os vários programas em /lib/ systemd; estes são
os executáveis relacionados a essas funções.
Aqui estão alguns serviços específicos do sistema:

udevd Você aprendeu sobre isso no Capítulo 3; faz parte do systemd.

journald Um serviço de registro que lida com alguns mecanismos de registro diferentes, incluindo o
serviço syslog tradicional do Unix . Você lerá mais sobre isso no Capítulo 7.

resolvido Um daemon de armazenamento em cache do serviço de nomes para DNS; você aprenderá
sobre isso no Capítulo 9.

Todos os executáveis para esses serviços são prefixados com systemd-. Por
Por exemplo, o udevd integrado ao systemd é chamado systemd-udevd.
Se você se aprofundar, verá que alguns desses programas são relativamente
invólucros simples. Sua função é executar utilitários padrão do sistema e notificar o systemd sobre
os resultados. Um exemplo é systemd-fsck.
Se você vir um programa em /lib/ systemd que não consegue identificar, verifique se há uma
página de manual. Há uma boa chance de que ele descreva não apenas a utilidade, mas também o tipo de
unidade que pretende aumentar.

6.4 Níveis de execução do System V

Agora que você aprendeu sobre o systemd e como ele funciona, vamos mudar de marcha e ver alguns
aspectos do init tradicional do System V. A qualquer momento em um sistema Linux, um determinado
conjunto básico de processos (como crond e udevd) está em execução. No init do System V, esse estado
da máquina é chamado de nível de execução, que é denotado por um número de 0 a 6. Um sistema
passa a maior parte do tempo em um único nível de execução, mas quando você desliga a máquina, o
init alterna para um runlevel diferente para encerrar os serviços do sistema de forma ordenada e dizer ao
kernel para parar.

Você pode verificar o nível de execução do seu sistema com o comando who -r assim:

$ quem -r
nível de execução 5 27-01-2019 16:43

156 Capítulo 6
Machine Translated by Google

Esta saída nos diz que o nível de execução atual é 5, assim como a data e
hora em que o nível de execução foi estabelecido.
Os níveis de execução servem a vários propósitos, mas o mais comum é distinguir entre
os estados de inicialização do sistema, desligamento, modo de usuário único e modo de console.
Por exemplo, a maioria dos sistemas tradicionalmente usava os níveis de execução de 2 a 4 para
o console de texto; um nível de execução de 5 significa que o sistema inicia um login da GUI.

Mas os níveis de execução estão se tornando uma coisa do passado. Embora o systemd os
suporte, ele considera os níveis de execução obsoletos como estados finais para o sistema,
preferindo unidades de destino. Para o systemd, os níveis de execução existem principalmente para
iniciar serviços que suportam apenas os scripts de inicialização do System V.

6.5 Inicialização do Sistema V

A implementação do init do System V está entre as mais antigas usadas no Linux; sua ideia central
é dar suporte a uma inicialização ordenada para diferentes níveis de execução com uma sequência
de inicialização cuidadosamente construída. A inicialização do System V agora é incomum na
maioria das instalações de servidores e desktops, mas você pode encontrá-la em versões do RHEL
anteriores à versão 7.0, bem como em ambientes Linux incorporados, como roteadores e telefones.
Além disso, alguns pacotes mais antigos podem fornecer apenas scripts de inicialização projetados
para init do System V; O systemd pode lidar com aqueles com um modo de compatibilidade que
discutiremos na Seção 6.5.5. Veremos o básico aqui, mas lembre-se de que você pode não encontrar
nada abordado nesta seção.

Uma instalação init típica do System V tem dois componentes: um arquivo de configuração
central e um grande conjunto de scripts de inicialização aumentados por um farm de links simbólicos.
O arquivo de configuração /etc/ inittab é onde tudo começa. Se você tiver init do System V, procure
uma linha como a seguinte em seu arquivo inittab :

id:5:initpadrão:

Isso indica que o nível de execução padrão é 5.


Todas as linhas no inittab têm o seguinte formato, com quatro campos separados por dois
pontos nesta ordem:

1. Um identificador exclusivo (uma string curta, como id no exemplo anterior).

2. Os números de nível de execução aplicáveis.

3. A ação que o init deve tomar (nível de execução padrão para 5 no anterior
exemplo).

4. Um comando a ser executado (opcional).

Para ver como os comandos funcionam em um arquivo inittab , considere esta linha:

l5:5:wait:/etc/rc.d/rc 5

Essa linha específica é importante porque aciona a maior parte da configuração e dos serviços
do sistema. Aqui, a ação wait determina quando e como o System V init executa o comando: execute /
etc/rc.d/rc 5 uma vez ao entrar

Como o Espaço do Usuário é Iniciado 157


Machine Translated by Google

runlevel 5 e espere que este comando termine antes de fazer qualquer outra coisa. O comando
rc 5 executa qualquer coisa em /etc/ rc5.d que comece com um número (em ordem numérica).
Abordaremos isso com mais detalhes em breve.
A seguir estão algumas das ações inittab mais comuns , além de initdefault e wait:

reaparecimento

A ação de respawn diz ao init para executar o comando a seguir e, se o comando terminar
de ser executado, executá-lo novamente. É provável que você veja algo assim em um
arquivo inittab :

1:2345:respawn:/sbin/mingetty tty1

Os programas getty fornecem prompts de login. A linha anterior é usada para o primeiro
console virtual (/ dev/ tty1), que é o que você vê quando pressiona ALT-F1 ou CTRL-ALT-F1
(consulte a Seção 3.4.7). O ressurgimento
A ação traz o prompt de login de volta após você sair.

ctrlaltdel

A ação ctrlaltdel controla o que o sistema faz quando você pressiona CTRL-ALT-DEL
em um console virtual. Na maioria dos sistemas, este é algum tipo de comando de
reinicialização usando o comando shutdown (discutido na Seção 6.6).

sysinit
A ação sysinit é a primeira coisa que o init deve executar ao iniciar, antes de entrar em
qualquer nível de execução.

OBSERVAÇÃO Para mais ações disponíveis, consulte a página de manual do inittab(5).

6.5.1 Inicialização do System V: Sequência de Comandos de Inicialização

Agora vamos ver como o init do System V inicia os serviços do sistema, pouco antes de permitir
que você faça login. Lembre-se desta linha inittab anterior:

l5:5:wait:/etc/rc.d/rc 5

Esta linha curta aciona muitos outros programas. Na verdade, rc significa executar
comandos, que muitas pessoas chamam de scripts, programas ou serviços. Mas onde estão
esses comandos?
O 5 nesta linha nos diz que estamos falando do nível de execução 5. O com
mandos provavelmente estão em /etc/ rc.d/ rc5.d ou /etc/ rc5.d. (O nível de execução 1 usa
rc1.d, o nível de execução 2 usa rc2.d e assim por diante.) Por exemplo, você pode encontrar
os seguintes itens no diretório rc5.d :

S10sysklogd S20ppp S99gpm


Fogo do núcleo S12 S25netstd_nfs S99httpd
S15netstd_init S30netstd_misc S99rmnologin

158 Capítulo 6
Machine Translated by Google

S18netbase S45 pcmcia S99sshd


S20acct S89atd
S20logoutd S89cron

O comando rc 5 inicia programas no diretório rc5.d executando os seguintes comandos


nesta sequência:

Iniciar S10sysklogd
S12 início do kernel
S15netstd_init start
início S18netbase
--recorte--
S99sshd iniciar

Observe o argumento start em cada comando. O S maiúsculo em um nome de comando


significa que o comando deve ser executado no modo de início , e o número (00 a 99) determina
onde na sequência rc inicia o comando. Os comandos rc*.d geralmente são scripts de shell que
iniciam programas em /sbin ou /usr/ sbin.

Normalmente, você pode descobrir o que um determinado comando faz visualizando o script
com menos ou outro programa de paginação.

OBSERVAÇÃO Alguns diretórios rc*.d contêm comandos que começam com K (para “kill” ou modo de parada).
Neste caso, rc executa o comando com o argumento stop em vez de start. Você provavelmente
encontrará comandos K em níveis de execução que desligam o sistema.

Você pode executar esses comandos manualmente; entretanto, normalmente você desejará
fazê-lo através do diretório init.d em vez dos diretórios rc*.d , que veremos a seguir.

6.5.2 O System V init Link Farm


O conteúdo dos diretórios rc*.d são, na verdade, links simbólicos para arquivos em outro diretório,
init.d. Se seu objetivo é interagir, adicionar, excluir ou modificar serviços nos diretórios rc*.d , você
precisa entender esses links simbólicos. Uma longa listagem de um diretório como rc5.d revela uma
estrutura como esta:

lrwxrwxrwx . . . S10sysklogd -> ../init.d/sysklogd


lrwxrwxrwx . . . S12kerneld -> ../init.d/kerneld
lrwxrwxrwx . . . S15netstd_init -> ../init.d/netstd_init
lrwxrwxrwx -- . . . S18netbase -> ../init.d/netbase
snip--
lrwxrwxrwx -- . . . S99httpd -> ../init.d/httpd
snip--

Um grande número de links simbólicos em vários subdiretórios como este é chamado de


farm de links. As distribuições do Linux contêm esses links para que possam usar os mesmos
scripts de inicialização para todos os níveis de execução. Esta é uma convenção, não uma
exigência, mas simplifica a organização.

Como o Espaço do Usuário é Iniciado 159


Machine Translated by Google

Iniciando e Parando Serviços

Para iniciar e parar serviços manualmente, use o script no diretório init.d. Por exemplo, uma maneira
de iniciar o programa do servidor web httpd manualmente é executar init.d/httpd start. Da mesma
forma, para matar um serviço em execução, você pode usar o stop
argumento (parada httpd, por exemplo).

Modificando a sequência de inicialização

A alteração da sequência de inicialização no System V init normalmente é feita modificando o


farm de links. A alteração mais comum é impedir que um dos comandos no diretório init.d seja
executado em um nível de execução específico. Você tem que ter cuidado sobre como você faz
isso, no entanto. Por exemplo, você pode considerar a remoção do link simbólico no diretório rc*.d
apropriado . Mas se você precisar colocar o link de volta, poderá ter problemas para lembrar seu
nome exato. Uma das melhores abordagens é adicionar um sublinhado (_) no início do nome do
link, assim:

#mv S99httpd _S99httpd

Esta mudança faz com que rc ignore _S99httpd porque o nome do arquivo não é lon
ger começa com S ou K, mas o nome original ainda indica sua finalidade.
Para adicionar um serviço, crie um script como os do diretório init.d e, em seguida, crie um
link simbólico no diretório rc*.d correto . A maneira mais fácil de fazer isso é copiar e modificar
um dos scripts que você já conhece no init.d (consulte o Capítulo 11 para obter mais informações
sobre scripts de shell).
Ao adicionar um serviço, escolha um local apropriado na sequência de inicialização
para iniciá-lo. Se o serviço for iniciado muito cedo, pode não funcionar devido à dependência de
algum outro serviço. Para serviços não essenciais, a maioria dos administradores de sistemas
prefere números nos anos 90, o que coloca os serviços depois da maioria dos serviços que
acompanham o sistema.

6.5.3 peças de execução

O mecanismo que o System V init usa para executar os scripts init.d encontrou seu caminho em
muitos sistemas Linux, independentemente de eles usarem o System V init. É um utilitário
chamado run-parts, e a única coisa que ele faz é executar vários programas executáveis em um
determinado diretório, em algum tipo de ordem previsível. Você pode pensar em run-parts quase
como uma pessoa que digita o comando ls em algum diretório e depois executa quaisquer
programas listados na saída.

O comportamento padrão é executar todos os programas em um diretório, mas você geralmente


tem a opção de selecionar determinados programas e ignorar outros. Em algumas distribuições,
você não precisa de muito controle sobre os programas executados. Por exemplo, o Fedora vem
com um utilitário run-parts muito simples.
Outras distribuições, como Debian e Ubuntu, têm um programa de partes de execução mais
complicado . Seus recursos incluem a capacidade de executar programas com base em uma
expressão regular (por exemplo, usando a expressão S [0-9]{2}

160 Capítulo 6
Machine Translated by Google

para executar todos os scripts “start” em um diretório de nível de execução /etc/ init.d ) e para passar
argumentos para os programas. Esses recursos permitem iniciar e interromper os níveis de execução do
System V com um único comando.
Você realmente não precisa entender os detalhes de como usar run-parts;
na verdade, a maioria das pessoas nem sabe que ele existe. As principais coisas a serem lembradas
são que ele aparece em scripts de tempos em tempos e que existe apenas para executar os programas
em um determinado diretório.

6.5.4 Controle de inicialização do System V

Ocasionalmente, você precisará dar um pequeno chute no init para dizer a ele para alternar os níveis de
execução, reler sua configuração ou desligar o sistema. Para controlar a inicialização do System V, você
usa o telinit. Por exemplo, para alternar para o nível de execução 3, digite:

#telinit 3

Ao alternar os níveis de execução, o init tenta eliminar todos os processos que não estão no
inittab para o novo nível de execução, portanto, tenha cuidado ao alterar os níveis de execução.
Quando você precisa adicionar ou remover trabalhos, ou fazer qualquer outra alteração no
inittab , você deve informar ao init sobre a mudança e fazer com que ele recarregue o arquivo.
O comando telinit para isso é:

#telini q

Você também pode usar telinit s para alternar para o modo de usuário único.

6.5.5 Compatibilidade do System V Systemd

Um recurso que diferencia o systemd de outros sistemas de inicialização de geração mais recente é
que ele tenta fazer um trabalho mais completo de rastreamento de serviços iniciados por scripts de
inicialização compatíveis com System V. Funciona assim:

1. Primeiro, o systemd ativa o runlevel<N>.target, onde N é o runlevel.

2. Para cada link simbólico em /etc/ rc<N>.d, o systemd identifica o script em


/ etc/ init.d.

3. O systemd associa o nome do script a uma unidade de serviço (por exemplo, /etc/ init.d/ foo seria
foo.service).

4. systemd ativa a unidade de serviço e executa o script com uma inicialização


ou argumento stop , baseado em seu nome em rc<N>.d.

5. systemd tenta associar quaisquer processos do script com o


unidade de serviço.

Como o systemd faz a associação com um nome de unidade de serviço, você pode usar
systemctl para reiniciar o serviço ou visualizar seu status. Mas não espere milagres do modo de
compatibilidade do System V; ele ainda deve executar os scripts de inicialização em série, por
exemplo.

Como o espaço do usuário é iniciado 161


Machine Translated by Google

6.6 Desligando seu sistema


init controla como o sistema é desligado e reinicializado. Os comandos para desligar o sistema são os
mesmos, independentemente da versão do init que você executa. A maneira correta de desligar uma
máquina Linux é usar o comando shutdown
comando.

Existem duas maneiras básicas de usar o desligamento. Se você parar o sistema, ele desliga a
máquina e a mantém desligada. Para fazer a máquina parar imediatamente, execute isto:

# desligar -h agora

Na maioria das máquinas e versões do Linux, uma parada corta a energia da máquina. Você
também pode reiniciar a máquina. Para uma reinicialização, use -r em vez de -h.
O processo de desligamento leva vários segundos. Você deve evitar redefinir ou desligar uma máquina
durante um desligamento.
No exemplo anterior, agora é a hora de desligar. Incluir um argumento de tempo é obrigatório,
mas há muitas maneiras de especificá-lo. Por exemplo, se você quiser que a máquina desligue em
algum momento no futuro, você pode usar +n, onde n é o número de minutos que o desligamento deve
esperar antes de continuar. Consulte a página de manual shutdown(8) para outras opções.

Para fazer a reinicialização do sistema em 10 minutos, digite:

# desligar -r +10

No Linux, o desligamento notifica qualquer pessoa conectada que a máquina está indo
para baixo, mas faz pouco trabalho real. Se você especificar um horário diferente de agora, o comando
shutdown cria um arquivo chamado /etc/ nologin. Quando este arquivo está presente, o sistema proíbe
logins de qualquer pessoa, exceto o superusuário.
Quando o tempo de desligamento do sistema finalmente chega, o desligamento informa ao init para
iniciar o processo de desligamento. No systemd, isso significa ativar as unidades de desligamento e no
System V init, significa alterar o nível de execução para 0 (parar) ou 6 (reinicializar).
Independentemente da implementação ou configuração do init, o procedimento geralmente é assim:

1. O init solicita que todos os processos sejam encerrados de forma limpa.

2. Se um processo não responde depois de um tempo, o init o mata, primeiro tentando um sinal
TERM.

3. Se o sinal TERM não funcionar, o init usa o sinal KILL em qualquer


retardatários.

4. O sistema bloqueia os arquivos do sistema e faz outros preparativos para o desligamento.

5. O sistema desmonta todos os sistemas de arquivos, exceto o root.

6. O sistema remonta o sistema de arquivos raiz somente leitura.

7. O sistema grava todos os dados armazenados em buffer no sistema de arquivos com a sincronização
programa.

162 Capítulo 6
Machine Translated by Google

8. O passo final é dizer ao kernel para reinicializar ou parar com a reinicialização(2)


chamada do sistema. Isso pode ser feito por init ou por um programa auxiliar, como reboot, halt ou
poweroff.

Os programas de reinicialização e parada se comportam de maneira diferente dependendo


de como são chamados, o que pode causar confusão. Por padrão, esses programas chamam o
desligamento com as opções -r ou -h . No entanto, se o sistema já estiver parado ou reiniciar o
nível de execução, os programas dizem ao kernel para desligar-se imediatamente. Se você
realmente deseja desligar sua máquina com pressa, independentemente de qualquer dano potencial
de um desligamento desordenado, use a opção -f (forçar).

6.7 O sistema de arquivos RAM inicial


O processo de inicialização do Linux é, na maioria das vezes, bastante simples. No entanto, um
componente sempre foi um pouco confuso: initramfs, ou o sistema de arquivos RAM inicial. Pense
nisso como uma pequena cunha de espaço do usuário que fica na frente do início do modo de
usuário normal. Mas primeiro, vamos falar sobre por que ela existe.
O problema decorre da disponibilidade de muitos tipos diferentes de armazenamento
hardware de idade. Lembre-se, o kernel do Linux não se comunica com a interface do BIOS do
PC ou EFI para obter dados dos discos, portanto, para montar seu sistema de arquivos raiz, ele
precisa de suporte de driver para o mecanismo de armazenamento subjacente. Por exemplo, se
a raiz estiver em uma matriz RAID conectada a um controlador de terceiros, o kernel precisa
primeiro do driver para esse controlador. Infelizmente, há tantos drivers de controlador de
armazenamento que as distribuições não podem incluir todos eles em seus kernels, então muitos
drivers são enviados como módulos carregáveis.
Mas os módulos carregáveis são arquivos, e se seu kernel não tiver um sistema de arquivos
montado em primeiro lugar, ele não poderá carregar os módulos de driver de que precisa.
A solução é reunir uma pequena coleção de módulos de driver do kernel junto com alguns
outros utilitários em um arquivo. O carregador de inicialização carrega esse arquivo na memória
antes de executar o kernel. Ao iniciar, o kernel lê o conteúdo do arquivo em um sistema de arquivos
RAM temporário (o init ramfs), monta-o em / e executa a transferência do modo de usuário para o
init no initramfs. Então, os utilitários incluídos no initramfs permitem que o kernel carregue os
módulos de driver necessários para o sistema de arquivos raiz real. Finalmente, os utilitários
montam o sistema de arquivos raiz real e iniciam o verdadeiro init.

As implementações variam e estão em constante evolução. Em algumas distribuições, o


init no initramfs é um shell script bastante simples que inicia um udevd para carregar drivers e,
em seguida, monta a raiz real e executa o init lá. Em distribuições que usam systemd, você
normalmente verá uma instalação completa do systemd sem arquivos de configuração de unidade
e apenas alguns arquivos de configuração udevd.

Uma característica básica do sistema de arquivos RAM inicial que tem (até agora)
permaneceu inalterado desde o seu início é a capacidade de ignorá-lo se você não precisar
dele. Ou seja, se o seu kernel tiver todos os drivers necessários para montar seu sistema de
arquivos raiz, você pode omitir o sistema de arquivos RAM inicial na configuração do carregador
de inicialização. Quando bem-sucedido, a eliminação do sistema de arquivos RAM inicial reduz
um pouco o tempo de inicialização. Experimente você mesmo no momento da inicialização usando o

Como o espaço do usuário é iniciado 163


Machine Translated by Google

Editor de menu GRUB para remover a linha initrd . (É melhor não experimentar alterando o arquivo
de configuração do GRUB, pois você pode cometer um erro que será difícil de reparar.)
Gradualmente, tornou-se um pouco mais difícil ignorar o sistema de arquivos RAM inicial porque
recursos como mount-by-UUID pode não estar disponível com kernels de distribuição genéricos.

Você pode verificar o conteúdo do seu sistema de arquivos RAM inicial, mas precisará fazer
um pouco de trabalho de detetive. A maioria dos sistemas agora usa arquivos criados por mkinitramfs
que você pode descompactar com unmkinitramfs. Outros podem ser arquivos cpio compactados mais
antigos (consulte a página de manual cpio(1)).
Uma parte de interesse particular é o “pivot” próximo ao final do processo de inicialização
no sistema de arquivos RAM inicial. Esta parte é responsável por remover o conteúdo do sistema
de arquivos temporário (para economizar memória) e mudar permanentemente para a raiz real.

Você normalmente não criará seu próprio sistema de arquivos RAM inicial, pois é um
processo meticuloso. Existem vários utilitários para criar imagens iniciais do sistema de arquivos
RAM, e sua distribuição provavelmente vem com um. Dois dos mais comuns são mkinitramfs e dracut.

NOTA O termo sistema de arquivos RAM inicial (initramfs) refere-se à implementação que usa
o arquivo cpio como a fonte do sistema de arquivos temporário. Existe uma versão mais antiga
chamada de disco RAM inicial, ou initrd, que usa uma imagem de disco como base do sistema de
arquivos temporário. Isso caiu em desuso porque é muito mais fácil manter um cpio
arquivo. No entanto, você verá frequentemente o termo initrd usado para se referir a um sistema de arquivos RAM
inicial baseado em cpio. Muitas vezes, os nomes dos arquivos e os arquivos de configuração ainda contêm initrd.

6.8 Inicialização de Emergência e Modo de Usuário Único


Quando algo dá errado com o sistema, seu primeiro recurso geralmente é inicializar o sistema com
uma imagem “ao vivo” de uma distribuição ou com uma imagem de recuperação dedicada, como
SystemRescueCD, que você pode colocar em mídia removível. Uma imagem ao vivo é simplesmente
um sistema Linux que pode ser inicializado e executado sem um processo de instalação; as imagens
de instalação da maioria das distribuições funcionam como imagens ao vivo. Tarefas comuns para
consertar um sistema incluem o seguinte:

•Verificando sistemas de arquivos após uma falha do sistema.

•Redefinindo uma senha esquecida.

•Corrigindo problemas em arquivos críticos, como /etc/ fstab e /etc/ passwd.

•Restauração de backups após uma falha do sistema.

Outra opção para inicializar rapidamente para um estado utilizável é o modo de usuário único.
A ideia é que o sistema inicialize rapidamente em um shell de root em vez de passar por toda a
confusão de serviços. No init do System V, o modo de usuário único geralmente é o nível de
execução 1. No systemd, é representado por rescue.target. Normalmente, você entra no modo com
o parâmetro -s para o carregador de inicialização. Você pode precisar digitar a senha de root para
entrar no modo de usuário único.

164 Capítulo 6
Machine Translated by Google

O maior problema com o modo de usuário único é que ele não oferece muitos
Facilidades. A rede quase certamente não estará disponível (e se estiver, será difícil
de usar), você não terá uma GUI e seu terminal pode nem funcionar corretamente. Por
esta razão, as imagens ao vivo são quase sempre consideradas preferíveis.

6.9 Olhando para o futuro


Você já viu as fases de inicialização do kernel e do espaço do usuário de um sistema Linux
e como o systemd rastreia os serviços depois de iniciados. Em seguida, iremos um pouco
mais fundo no espaço do usuário. Há duas áreas a serem exploradas, começando com
vários arquivos de configuração do sistema que todos os programas Linux usam ao interagir
com certos elementos do espaço do usuário. Então veremos os serviços essenciais que o
systemd inicia.

Como o espaço do usuário é iniciado 165


Machine Translated by Google
Machine Translated by Google

CONFIGURAÇÃO DO SISTEMA :
7
EXPLORAÇÃO MADEIREIRA , SYSTEMTIME , LOTE
TRABALHOS E USUÁRIOS

Quando você olha pela primeira vez no diretório /etc


para explorar a configuração do seu sistema, você
pode se sentir um pouco sobrecarregado. A boa
notícia é que, embora a maioria dos arquivos que você
vê afetem as operações de um sistema até certo ponto, apenas
alguns são fundamentais.
Este capítulo abrange as partes do sistema que tornam a infraestrutura discutida no Capítulo
4 disponível para o software de espaço do usuário com o qual normalmente interagimos, como as
ferramentas abordadas no Capítulo 2. Em particular, veremos o seguinte:

• Registro do sistema
• Arquivos de configuração que as bibliotecas do sistema acessam para obter informações
do servidor e do usuário
Machine Translated by Google

• Alguns programas de servidor selecionados (às vezes chamados daemons) que são executados
quando o sistema inicializa

•Utilitários de configuração que podem ser usados para ajustar os programas do servidor
e arquivos de configuração

• Configuração de horário

• Agendamento de tarefas periódicas

O uso generalizado do systemd reduziu o número de daemons básicos e independentes


encontrados em um sistema Linux típico. Um exemplo é o daemon de log do sistema (syslogd), cuja
funcionalidade agora é amplamente fornecida por um daemon embutido no systemd (journald). Ainda
assim, alguns daemons tradicionais permanecem, como crond e atd.

Como nos capítulos anteriores, este capítulo não inclui praticamente nenhum material de rede
porque a rede é um bloco de construção separado do sistema. No Capítulo 9, você verá onde a rede
se encaixa.

7.1 Registro do Sistema


A maioria dos programas do sistema grava sua saída de diagnóstico como mensagens no syslog
serviço. O daemon syslogd tradicional realiza esse serviço aguardando mensagens e, ao receber
uma, enviando-a para um canal apropriado, como um arquivo ou um banco de dados. Na maioria
dos sistemas contemporâneos, journald (que vem com systemd) faz a maior parte do trabalho.
Embora nos concentremos no journald neste livro, também abordaremos muitos aspectos do syslog
tradicional.

O registrador do sistema é uma das partes mais importantes do sistema.


Quando algo dá errado e você não sabe por onde começar, é sempre bom verificar o log. Se você
tiver journald, fará isso com o journalctl
comando, que abordaremos na Seção 7.1.2. Em sistemas mais antigos, você precisará verificar os
próprios arquivos. Em ambos os casos, as mensagens de log são assim:

19 de agosto 17:59:48 duplex sshd[484]: Servidor escutando na porta 0.0.0.0 22.

Uma mensagem de log geralmente contém informações importantes, como nome do processo,
ID do processo e carimbo de data/hora. Também pode haver dois outros campos: a facilidade (uma
categoria geral) e a gravidade (quão urgente é a mensagem).
Discutiremos isso com mais detalhes posteriormente.
Compreender o registro em um sistema Linux pode ser um pouco desafiador devido às
combinações variadas de componentes de software mais antigos e mais novos. Algumas
distribuições, como o Fedora, mudaram para um padrão somente journald, enquanto outras executam
uma versão do syslogd mais antigo (como rsyslogd) junto com journald. Distribuições mais antigas e
alguns sistemas especializados podem não usar o systemd e ter apenas uma das versões do syslogd.
Além disso, alguns sistemas de software ignoram completamente o registro padronizado e escrevem
seus próprios.

168 Capítulo 7
Machine Translated by Google

7.1.1 Verificando sua configuração de log

Você deve inspecionar seu próprio sistema para ver que tipo de registro está instalado.
Veja como:

1. Verifique o journald, que você quase certamente tem se estiver executando o systemd.
Embora você possa procurar journald em uma lista de processos, a maneira mais fácil é
simplesmente executar journalctl. Se journald estiver ativo em seu sistema, você receberá
uma lista paginada de mensagens de log.

2. Verifique se há rsyslogd. Procure rsyslogd em uma lista de processos e procure por /etc/
rsyslog.conf.

3. Se você não tiver o rsyslogd, verifique o syslog-ng (outra versão do syslogd) procurando por um
diretório chamado /etc/ syslog-ng.

Continue seu tour procurando em /var/ log por arquivos de log. Se você tem um ver
ção do syslogd, este diretório deve conter muitos arquivos, a maioria criados pelo seu daemon
syslog. No entanto, haverá alguns arquivos aqui que são mantidos por outros serviços; dois
exemplos são wtmp e lastlog, os arquivos de log que utilitários como last e lastlog acessam para
obter registros de login.
Além disso, pode haver outros subdiretórios em /var/ log contendo logs. Estes quase sempre
vêm de outros serviços. Um deles, /var/ log/
journal, é onde journald armazena seus arquivos de log (binários).

7.1.2 Pesquisando e Monitorando Logs

A menos que você tenha um sistema sem journald ou esteja pesquisando um arquivo de log
mantido por algum outro utilitário, você examinará o journal. Sem argumentos, a ferramenta de
acesso journalctl é como uma mangueira de incêndio, dando a você todas as mensagens do
diário, começando pelas mais antigas (assim como elas apareceriam em um arquivo de log).
Felizmente , journalctl usa como padrão um pager como less para exibir mensagens para que
seu terminal não seja inundado. Você pode pesquisar mensagens com o pager e inverter a ordem
de tempo das mensagens com journalctl -r, mas existem maneiras muito melhores de encontrar logs.

OBSERVAÇÃO Para obter acesso total às mensagens do diário, você precisa executar journalctl como root ou
como um usuário pertencente aos grupos adm ou systemd-journal. O usuário padrão na maioria
das distribuições tem acesso.

Em geral, você pode pesquisar campos individuais de periódicos apenas adicionando-os à


linha de comando; por exemplo, execute journalctl _PID=8792 para pesquisar mensagens do ID
de processo 8792. No entanto, os recursos de filtragem mais poderosos são de natureza mais
geral. Você pode especificar um ou mais se precisar de vários critérios.

Filtrando por Tempo

A opção -S (desde) está entre as mais úteis para restringir um horário específico. Aqui está um
exemplo de uma das maneiras mais fáceis e eficazes de usá-lo:

$ journalctl -S -4h

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 169


Machine Translated by Google

A parte -4h deste comando pode parecer uma opção, mas na realidade é
uma especificação de tempo dizendo ao journalctl para procurar mensagens das últimas quatro horas
em seu fuso horário atual. Você também pode usar uma combinação de um dia e/ou hora específicos:

$ journalctl -S 06:00:00
$ journalctl -S 2020-01-14
$ journalctl -S '2020-01-14 14:30:00'

A opção -U (until) funciona da mesma maneira, especificando um tempo até o qual


journalctl deve recuperar mensagens. No entanto, muitas vezes não é tão útil porque você
normalmente vai paginar ou pesquisar mensagens até encontrar o que você precisa, então simplesmente
saia.

Filtrando por Unidade

Outra maneira rápida e eficaz de obter logs relevantes é filtrar por unidade do systemd. Você pode fazer
isso com a opção -u , assim:

$ journalctl -u cron.service

Normalmente, você pode omitir o tipo de unidade (.service neste caso) ao filtrar por unidade.

Se você não souber o nome de uma unidade específica, tente este comando para listar todas
as unidades no diário:

$ journalctl -F _SYSTEMD_UNIT

A opção -F mostra todos os valores no diário para um campo específico.

Encontrando campos

Às vezes, você só precisa saber em qual campo pesquisar. Você pode listar todos os campos disponíveis
da seguinte forma:

$ journalctl -N

Qualquer campo que comece com um sublinhado (como _SYSTEMD_UNIT do exemplo anterior) é
um campo confiável; o cliente que envia uma mensagem não pode alterar esses campos.

Filtrando por Texto

Um método clássico de pesquisar arquivos de log é executar o grep em todos eles, esperando encontrar
uma linha ou ponto relevante em um arquivo onde possa haver mais informações. Da mesma forma, você
pode pesquisar mensagens de diário por expressão regular com a opção -g , como neste exemplo, que
retornará mensagens contendo kernel seguido de algum lugar por memória:

$ journalctl -g 'kernel.*memory'

170 Capítulo 7
Machine Translated by Google

Infelizmente, quando você pesquisa o diário dessa maneira, obtém apenas as mensagens que
correspondem à expressão. Muitas vezes, informações importantes podem estar próximas em termos de tempo.
Tente escolher o carimbo de data/hora de uma correspondência e, em seguida, execute journalctl -S com um
horário imediatamente anterior para ver quais mensagens chegaram ao mesmo tempo.

NOTA A opção -g requer uma compilação de journalctl com uma biblioteca específica. Algumas distribuições não incluem uma
versão que suporte -g.

Filtrando por inicialização

Frequentemente, você se verá procurando nos logs por mensagens na época em que uma máquina inicializou
ou pouco antes de ser desligada (e reinicializada). É muito fácil obter as mensagens de apenas uma
inicialização, desde quando a máquina foi iniciada até que ela parou. Por exemplo, se você estiver procurando
pelo início da inicialização atual, basta usar a opção -b :

$ diárioctl -b

Você também pode adicionar um deslocamento; por exemplo, para iniciar na inicialização anterior, use
um deslocamento de -1.

$ diárioctl -b -1

NOTA Você pode verificar rapidamente se a máquina desligou corretamente no último ciclo
combinando as opções -b e -r (reverse). Tente; se a saída se parecer com o exemplo aqui, o desligamento foi
limpo:

$ journalctl -r -b -1
-- Os registros começam na quarta-feira 03/04/2019 12:29:31 EDT, terminando na sexta-feira 02/08/2019
19:10:14 EDT. --
18 de julho 12:19:52 mymachine systemd-journald[602]: Diário parado
18 de julho 12:19:52 mymachine systemd-shutdown[1]: Enviando SIGTERM para os
processos restantes...
18 de julho 12:19:51 mymachine systemd-shutdown[1]: Sincronizando sistemas de arquivos e dispositivos
de bloco.

Em vez de um deslocamento como -1, você também pode visualizar as inicializações por IDs. Execute o fol
lowing para obter os IDs de inicialização:

$ journalctl --list-boots
-1 e598bd09e5c046838012ba61075dccbb Sex 2019-03-22 17:20:01 EDT—Sex 2019-04-12
08:13:52 EDT
0 5696e69b1c0b42d58b9c57c31d8c89cc Sex 2019-04-12 08:15:39 EDT—Sex 2019-08-02
19:17:01 EDT

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 171


Machine Translated by Google

Finalmente, você pode exibir mensagens do kernel (com ou sem selecionar um


inicialização específica) com journalctl -k.

Filtrando por Gravidade/Prioridade

Alguns programas produzem um grande número de mensagens de diagnóstico que podem obscurecer logs
importantes. Você pode filtrar pelo nível de gravidade especificando um valor entre 0 (mais importante) e 7
(menos importante) ao lado do -p
opção. Por exemplo, para obter os logs dos níveis 0 a 3, execute:

$ journalctl -p 3

Se você quiser apenas os logs de um conjunto específico de níveis de gravidade, use o ..


sintaxe de intervalo:

$ journalctl -p 2..3

Filtrar por gravidade pode economizar muito tempo, mas você pode não encontrar muita utilidade para
isso. A maioria dos aplicativos não gera grandes quantidades de dados informativos por padrão, embora alguns
incluam opções de configuração para habilitar um log mais detalhado.

Monitoramento de Log Simples

Uma maneira tradicional de monitorar logs é usar tail -f ou o modo less follow (menos +F) em um arquivo de log
para ver as mensagens que chegam do registrador do sistema.
Esta não é uma prática de monitoramento regular do sistema muito eficaz (é muito fácil perder alguma coisa),
mas é útil para examinar um serviço quando você está tentando encontrar um problema ou obter uma visão mais
detalhada da inicialização e operação em tempo real.
Usar tail -f não funciona com journald porque não usa texto simples
arquivos; em vez disso, você pode usar a opção -f para journalctl para produzir o mesmo efeito de imprimir os
logs conforme eles chegam:

$ diárioctl -f

Essa simples invocação é boa o suficiente para a maioria das necessidades. No entanto, você pode
querer adicionar algumas das opções de filtragem anteriores se o seu sistema tiver um fluxo bastante constante
de mensagens de log não relacionadas ao que você está procurando.

7.1.3 Rotação do Arquivo de Log

Quando você está usando um daemon syslog, qualquer mensagem de log que seu sistema registra vai
para um arquivo de log em algum lugar, o que significa que você precisa excluir mensagens antigas
ocasionalmente para que elas não consumam todo o seu espaço de armazenamento. Diferentes distribuições
fazem isso de maneiras diferentes, mas a maioria usa o utilitário logrotate .

O mecanismo é chamado de rotação de log. Como um arquivo de log de texto tradicional contém as
mensagens mais antigas no início e as mais recentes no final, é muito difícil remover apenas as mensagens mais
antigas de um arquivo para liberar espaço. Em vez disso, um log mantido por logrotate é dividido em vários
pedaços.

172 Capítulo 7
Machine Translated by Google

Digamos que você tenha um arquivo de log chamado auth.log em /var/ log contendo as
mensagens de log mais recentes. Depois, há um auth.log.1, auth.log.2 e auth.log.3, cada um
com dados progressivamente mais antigos. Quando o logrotate decide que é hora de excluir
alguns dados antigos, ele “rota” os arquivos assim:

1. Remove o arquivo mais antigo, auth.log.3.


2. Renomeia auth.log.2 para auth.log.3.
3. Renomeia auth.log.1 para auth.log.2.
4. Renomeia auth.log para auth.log.1.

Os nomes e alguns detalhes variam entre as distribuições. Por exemplo, a configuração


do Ubuntu especifica que logrotate deve compactar o arquivo que é movido da posição “1” para
a posição “2”, portanto, no exemplo anterior, você teria auth.log.2.gz e auth.log.3 .gz. Em outras
distribuições, logrotate renomeia os arquivos de log com um sufixo de data, como -20200529.

Uma vantagem desse esquema é que é mais fácil encontrar um arquivo de log de um horário
específico.
Você pode estar se perguntando o que acontece se logrotate executa uma rotação ao
mesmo tempo que outro utilitário (como rsyslogd) deseja adicionar ao arquivo de log. Por
exemplo, digamos que o programa de log abre o arquivo de log para gravação, mas não o fecha
antes que logrotate execute a renomeação. Nesse cenário um tanto incomum, a mensagem de
log seria gravada com sucesso, porque no Linux, uma vez que um arquivo é aberto, o sistema de
E/S não tem como saber que foi renomeado. Mas observe que o arquivo em que a mensagem
aparece será o arquivo com o novo nome, como auth.log.1.

Se logrotate já tiver renomeado o arquivo antes que o programa de log tente abri-lo, a
chamada de sistema open() cria um novo arquivo de log (como auth.log), exatamente como
faria se logrotate não estivesse em execução.

7.1.4 Manutenção do Diário

Os diários armazenados em /var/ log/ journal não precisam de rotação, pois o próprio diário
pode identificar e remover mensagens antigas. Ao contrário do gerenciamento de logs
tradicional, journald normalmente decide excluir mensagens com base em quanto espaço resta
no sistema de arquivos do diário, quanto espaço o diário deve ocupar como porcentagem do
sistema de arquivos e qual o tamanho máximo do diário definido. Existem outras opções para
gerenciamento de log, como a idade máxima permitida de uma mensagem de log. Você
encontrará uma descrição dos padrões, bem como outras configurações na página de manual
journald.conf(5).

7.1.5 Uma análise mais detalhada do registro do sistema

Agora que você viu alguns dos detalhes operacionais do syslog e do diário, é hora de retroceder
um pouco e examinar as razões pelas quais e como o registro funciona da maneira que funciona.
Esta discussão é mais teórica do que prática; você pode pular para o próximo tópico do livro sem
problemas.
Na década de 1980, uma lacuna estava começando a surgir: os servidores Unix precisavam
de uma maneira de registrar informações de diagnóstico, mas não havia um padrão para isso.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 173


Machine Translated by Google

Quando o syslog apareceu com o servidor de e-mail sendmail, fez bastante sentido que os
desenvolvedores de outros serviços o adotassem prontamente. RFC 3164 descreve a evolução
do syslog.
O mecanismo é bastante simples. Um syslogd tradicional escuta e espera por mensagens no
soquete de domínio Unix /dev/ log. Um recurso poderoso adicional do syslogd é a capacidade de
escutar em um soquete de rede além de /dev/ log, permitindo que máquinas clientes enviem mensagens
através de uma rede.
Isso torna possível consolidar todas as mensagens syslog de um
rede em um servidor de registro e, por esse motivo, o syslog se tornou muito popular entre os
administradores de rede. Muitos dispositivos de rede, como roteadores e dispositivos incorporados,
podem atuar como clientes syslog, enviando suas mensagens de diagnóstico para um servidor.

O Syslog possui uma arquitetura cliente-servidor clássica, incluindo seu próprio protocolo
(atualmente definido na RFC 5424). No entanto, o protocolo nem sempre era padrão e as versões
anteriores não acomodavam muita estrutura além de alguns conceitos básicos. Esperava-se que os
programadores usando syslog criassem um formato de mensagem de log descritivo, mas claro e
breve, para seus próprios aplicativos. Com o tempo, o protocolo adicionou novos recursos enquanto
ainda tentava manter o máximo possível de compatibilidade com versões anteriores.

Instalação, gravidade e outros campos

Como o syslog envia mensagens de vários tipos de diferentes serviços para diferentes destinos,
ele precisa de uma maneira de classificar cada mensagem. O método tradicional é usar valores
codificados de facilidade e gravidade que normalmente (mas nem sempre) são incluídos em uma
mensagem. Além da saída de arquivo, mesmo versões muito antigas do syslogd eram capazes de
enviar mensagens importantes para consoles e diretamente para usuários logados específicos com
base na facilidade e gravidade das mensagens - uma ferramenta inicial para monitoramento do
sistema.
A facilidade é uma categoria geral de serviço, identificando o que enviou a mensagem. As
instalações incluem serviços e componentes do sistema, como kernel, sistema de correio e
impressora.
A gravidade é a urgência da mensagem de log. Existem oito níveis, numerados de 0 a 7.
Eles geralmente são chamados pelo nome, embora os nomes não sejam muito consistentes e
variem entre as implementações:

0: emergir 4: aviso
1: alerta 5: aviso
2: crítico 6: informações

3: erro 7: depurar

A facilidade e a gravidade juntas formam a prioridade, empacotada como um número no


protocolo syslog. Você pode ler tudo sobre esses campos na RFC 5424, aprender como especificá-
los em aplicativos na página de manual do syslog(3) e aprender como combiná-los na página de
manual do rsyslog.conf(5).

174 Capítulo 7
Machine Translated by Google

No entanto, você pode se deparar com alguma confusão ao traduzi-los para o mundo
journald, onde a gravidade é chamada de prioridade (por exemplo, quando você executa
journalctl -o json para obter uma saída de log legível por máquina).
Infelizmente, quando você começar a examinar os detalhes da parte prioritária do
protocolo, descobrirá que ele não acompanhou as mudanças e os requisitos do restante
do sistema operacional. A definição de gravidade ainda se mantém bem, mas os recursos
disponíveis são conectados e incluem serviços raramente usados, como UUCP, sem
nenhuma maneira de definir novos (apenas alguns slots genéricos de local0 a local7).

Já falamos sobre alguns dos outros campos nos dados de log, mas a RFC 5424
também inclui uma provisão para dados estruturados, conjuntos de pares de valores-chave
arbitrários que os programadores de aplicativos podem usar para definir seus próprios campos.
Embora eles possam ser usados com journald com algum trabalho extra, é muito mais
comum enviá-los para outros tipos de bancos de dados.

A relação entre Syslog e journald

O fato de journald ter deslocado completamente o syslog em alguns sistemas pode fazer
com que você pergunte por que o syslog permanece em outros. Existem dois principais
razões:

• O Syslog tem um meio bem definido de agregar logs em muitos


máquinas. É muito mais fácil monitorar os logs quando eles estão em apenas uma
máquina.

•Versões de syslog, como rsyslogd, são modulares e capazes de produzir vários formatos e
bancos de dados diferentes (incluindo o formato de diário).
Isso torna mais fácil conectá-los a ferramentas de análise e monitoramento.

Por outro lado, journald enfatiza a coleta e a organização do log out de uma única
máquina em um único formato.
Quando você deseja fazer algo mais complicado, a capacidade do journald de alimentar
seus logs em um registrador diferente oferece um alto grau de versatilidade.
Isso é especialmente verdadeiro quando você considera que o systemd pode coletar a saída
das unidades do servidor e enviá-las para journald, dando acesso a ainda mais dados de log
do que os aplicativos enviam ao syslog.

Notas finais sobre registro

O registro em sistemas Linux mudou significativamente durante sua história, e é quase


certo que continuará a evoluir. No momento, o processo de coleta, armazenamento e
recuperação de logs em uma única máquina está bem definido, mas há outros aspectos do
log que não são padronizados.

Primeiro, há uma variedade estonteante de opções disponíveis quando você deseja


agregar e armazenar logs em uma rede de máquinas. Em vez de um servidor de log
centralizado simplesmente armazenando logs em arquivos de texto, os logs agora podem ir
para bancos de dados e, muitas vezes, o próprio servidor centralizado é substituído por um
serviço de internet.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 175


Machine Translated by Google

Em seguida, a natureza de como os logs são consumidos mudou. De uma vez,


logs não foram considerados dados “reais”; seu objetivo principal era um recurso que o
administrador (humano) pudesse ler quando algo desse errado. No entanto, à medida que
os aplicativos se tornaram mais complexos, as necessidades de registro aumentaram. Esses
novos requisitos incluem a capacidade de pesquisar, extrair, exibir e analisar os dados dentro
dos logs. Embora tenhamos muitas maneiras de armazenar logs em bancos de dados, as
ferramentas para usar os logs em aplicativos ainda estão em sua infância.

Finalmente, há a questão de garantir que os logs sejam confiáveis. o


o syslog original não tinha autenticação; você simplesmente confiou que qualquer aplicativo
e/ou máquina que enviasse o log estava dizendo a verdade.
Além disso, os logs não eram criptografados, tornando-os vulneráveis à espionagem na rede.
Esse era um risco sério em redes que exigiam alta segurança. Os servidores syslog
contemporâneos têm métodos padrão de criptografar uma mensagem de log e autenticar a
máquina de onde ela se origina. No entanto, quando você se concentra em aplicativos
individuais, a imagem fica menos clara. Por exemplo, como você pode ter certeza de que a
coisa que se chama seu servidor web é realmente o servidor web?

Exploraremos alguns tópicos de autenticação um pouco avançados mais adiante neste


capítulo. Mas, por enquanto, vamos para o básico de como os arquivos de configuração
são organizados no sistema.

7.2 A Estrutura do /etc


A maioria dos arquivos de configuração do sistema em um sistema Linux são encontrados em /
etc. Historicamente, cada programa ou serviço de sistema tinha um ou mais arquivos de
configuração lá, e devido ao grande número de componentes em um sistema Unix, /etc
acumulava arquivos rapidamente.
Havia dois problemas com essa abordagem: era difícil encontrar arquivos de
configuração específicos em um sistema em execução e era difícil manter um sistema
configurado dessa maneira. Por exemplo, se você quisesse alterar a configuração do sudo ,
teria que editar /etc/ sudoers. Mas após sua alteração, uma atualização para sua distribuição
pode eliminar suas personalizações porque substituiria tudo em /etc.

A tendência por muitos anos tem sido colocar os arquivos de configuração do sistema
em subdiretórios em /etc, como você já viu para systemd, que usa /etc/ systemd. Ainda
existem alguns arquivos de configuração individuais em /etc, mas se você executar ls -F /
etc, verá que a maioria dos itens agora são subdiretórios.

Para resolver o problema de sobrescrever arquivos de configuração, agora você pode


colocar as personalizações em arquivos separados nos subdiretórios de configuração, como
aqueles em /etc/ grub.d.
Que tipo de arquivos de configuração são encontrados em /etc? A linha de
orientação básica é que as configurações personalizáveis para uma única máquina, como
informações do usuário (/ etc/ passwd) e detalhes da rede (/ etc/ network), vão para /etc.
No entanto, detalhes gerais do aplicativo, como os padrões de uma distribuição para um

176 Capítulo 7
Machine Translated by Google

interface do usuário, não pertença a /etc. Os arquivos de configuração padrão do sistema que não
devem ser personalizados também são geralmente encontrados em outros lugares, como os arquivos
de unidade systemd pré-empacotados em /usr/ lib/ systemd.
Você já viu alguns dos arquivos de configuração que pertencem ao boot
ing. Vamos continuar analisando como os usuários são configurados em um sistema.

7.3 Arquivos de gerenciamento de usuários

Os sistemas Unix permitem vários usuários independentes. No nível do kernel, os usuários são
simplesmente números (IDs de usuário), mas como é muito mais fácil lembrar um nome do que um
número, você normalmente trabalhará com nomes de usuário (ou nomes de login) ao gerenciar o Linux.
Os nomes de usuário existem apenas no espaço do usuário, portanto, qualquer programa que trabalhe
com um nome de usuário precisa encontrar seu ID de usuário correspondente ao se comunicar com o
kernel.

7.3.1 O arquivo /etc/passwd


O arquivo de texto simples /etc/ passwd mapeia nomes de usuários para IDs de usuários. Parece
a Listagem 7-1.

root:x:0:0:Superusuário:/root:/bin/sh
daemon : * : 1 : 1 : daemon : /usr/sbin: /bin/sh
bin:*:2:2:bin:/bin:/bin/sh
sys:*:3:3:sys:/dev:/bin/sh
ninguém:*:65534:65534:ninguém:/home:/bin/false
juser:x:3119:1000:J. Usuário aleatório:/home/juser:/bin/bash
beazley:x:143:1000:David Beazley:/home/beazley:/bin/bash

Listagem 7-1: Uma lista de usuários em /etc/passwd

Cada linha representa um usuário e possui sete campos separados por dois pontos.
O primeiro é o nome de usuário.
A seguir vem a senha criptografada do usuário, ou pelo menos o que já foi o campo para a
senha. Na maioria dos sistemas Linux, a senha não é mais armazenada no arquivo passwd , mas sim
no arquivo shadow (consulte a Seção 7.3.3). O formato do arquivo shadow é semelhante ao do
passwd, mas usuários normais não têm permissão de leitura para shadow. O segundo campo em
passwd ou shadow é a senha criptografada, e parece um monte de lixo ilegível, como d1CVEWiB/oppc.
As senhas Unix nunca são armazenadas como texto não criptografado; na verdade, o campo não é a
senha em si, mas uma derivação dela. Na maioria dos casos, é excepcionalmente difícil obter a senha
original desse campo (assumindo que a senha não seja fácil de adivinhar).

Um x no campo do segundo arquivo passwd indica que a senha criptografada está armazenada
no arquivo shadow (que deve ser configurado em seu sistema). Um asterisco (*) indica que o usuário
não pode fazer login.
Se este campo de senha estiver em branco (ou seja, você vê dois dois-pontos em uma linha,
como ::), nenhuma senha é necessária para efetuar login. Cuidado com senhas em branco como esta.
Você nunca deve ter um usuário capaz de fazer login sem uma senha.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 177


Machine Translated by Google

Os campos passwd restantes são os seguintes:

•O ID do usuário (UID), que é a representação do usuário no kernel. Você pode ter duas entradas com
o mesmo ID de usuário, mas isso o confundirá—
e possivelmente seu software também — portanto, mantenha o ID do usuário exclusivo.

•O ID do grupo (GID), que deve ser uma das entradas numeradas no arquivo /etc/ group . Os grupos
determinam as permissões de arquivo e pouco mais.
Esse grupo também é chamado de grupo primário do usuário.

•O nome real do usuário (geralmente chamado de campo GECOS ). Às vezes, você


encontrará vírgulas neste campo, denotando números de quarto e telefone.
• O diretório inicial do usuário.

•O shell do usuário (o programa que é executado quando o usuário executa um terminal


sessão).

A Figura 7-1 identifica os vários campos em uma das entradas da Listagem 7-1.

Nome de acesso
Senha
ID do usuário

ID do grupo Nome real (GECOS)


Diretório inicial
Casca

juser:x:3119:1000:J. Usuário aleatório:/home/juser:/bin/bash


Figura 7-1: Uma entrada no arquivo de senha

A sintaxe do arquivo /etc/ passwd é bastante rígida, não permitindo comentários ou


linhas em branco.

NOTA Um usuário em / etc/passwd e um diretório inicial correspondente são conhecidos coletivamente como uma
conta. No entanto, lembre-se de que esta é uma convenção de espaço do usuário. Uma entrada no
arquivo passwd geralmente é suficiente para qualificar; o diretório inicial não precisa existir para que a
maioria dos programas reconheça uma conta. Além disso, existem maneiras de adicionar usuários em um
sistema sem incluí-los explicitamente no arquivo passwd ; por exemplo, adicionar usuários de um servidor
de rede usando algo como NIS (Network Information Service) ou LDAP (Lightweight Directory Access
Protocol) já foi comum.

7.3.2 Usuários Especiais


Você encontrará alguns usuários especiais em /etc/ passwd. O superusuário (root) sempre tem UID
0 e GID 0, como na Listagem 7-1. Alguns usuários, como o daemon, não têm privilégios de login. O
usuário none é um usuário sem privilégios; alguns processos são executados como none porque não
podem (normalmente) gravar em nada no sistema.

178 Capítulo 7
Machine Translated by Google

Os usuários que não podem fazer login são chamados de pseudo-usuários. Embora eles não
possam efetuar login, o sistema pode iniciar processos com seus IDs de usuário. Pseudo-usuários,
como ninguém, geralmente são criados por motivos de segurança.
Novamente, essas são todas as convenções do espaço do usuário. Esses usuários não têm
nenhum significado especial para o kernel; o único ID de usuário que significa algo especial para o
kernel é o do superusuário, 0. É possível dar ao usuário none acesso a tudo no sistema da mesma
forma que você faria com qualquer outro usuário.

7.3.3 O arquivo /etc/shadow


O arquivo de senha shadow (/ etc/ shadow) em um sistema Linux normalmente contém informações
de autenticação do usuário, incluindo as senhas criptografadas e informações de expiração de senha
que correspondem aos usuários em /etc/ passwd.
O arquivo shadow foi introduzido para fornecer uma maneira mais flexível (e talvez mais
segura) de armazenar senhas. Ele incluía um conjunto de bibliotecas e utilitários, muitos dos quais
logo foram substituídos por partes do PAM (Pluggable Authentication Modules; abordaremos esse
tópico avançado na Seção 7.10). Em vez de introduzir um conjunto inteiramente novo de arquivos
para Linux, o PAM usa /etc/ shadow, mas não certos arquivos de configuração correspondentes,
como /etc/ login.defs.

7.3.4 Manipulando Usuários e Senhas


Usuários comuns interagem com /etc/ passwd usando o comando passwd e algumas outras
ferramentas. Use passwd para alterar sua senha. Você pode usar chfn e chsh
para alterar o nome real e o shell, respectivamente (o shell deve estar listado em /etc/ shells). Estes
são todos executáveis suid-root, porque somente o superusuário pode alterar o arquivo /etc/ passwd .

Alterando /etc/passwd como o superusuário

Como /etc/ passwd é apenas um arquivo de texto simples normal, o superusuário tem permissão
técnica para usar qualquer editor de texto para fazer alterações. Para adicionar um usuário, é
possível simplesmente adicionar uma linha apropriada e criar um diretório home para o usuário; para
excluir, você pode fazer o oposto.
No entanto, editar diretamente o passwd assim é uma má ideia. Não só é muito fácil
cometer um erro, mas você também pode ser pego com um problema de simultaneidade se outra
coisa estiver fazendo alterações de senha ao mesmo tempo . É muito mais fácil (e seguro) fazer
alterações nos usuários usando comandos separados disponíveis no terminal ou por meio da GUI. Por
exemplo, para definir a senha de um usuário, execute passwd user como superusuário. Use adduser
e userdel para adicionar e remover usuários, respectivamente.

No entanto, se você realmente precisar editar o arquivo diretamente (por exemplo, se estiver
corrompido de alguma forma), use o programa vipw , que faz backup e bloqueia /etc/ passwd
enquanto você o está editando como precaução adicional. Para editar /etc/ shadow em vez de /etc/
passwd, use vipw -s. (Espero que você nunca precise fazer nenhum desses.)

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 179


Machine Translated by Google

7.3.5 Trabalhando com Grupos


Grupos no Unix oferecem uma maneira de compartilhar arquivos entre determinados usuários. A
ideia é que você possa definir bits de permissão de leitura ou gravação para um grupo específico,
excluindo todos os outros. Esse recurso já foi importante porque muitos usuários compartilhavam uma
máquina ou rede, mas tornou-se menos significativo nos últimos anos, pois as estações de trabalho são
compartilhadas com menos frequência.
O arquivo /etc/ group define os IDs do grupo (como os encontrados no arquivo /etc/ passwd ). A
Listagem 7-2 é um exemplo.

raiz:*:0:juser
daemon:*:1:
bin:*:2:
sistema:*:3:
adm:*:4:
disco:*:6:juser,beazley
nogrupo:*:65534:
usuário:*:1000:

Listagem 7-2: Um arquivo /etc/group de amostra

Assim como no arquivo /etc/ passwd , cada linha em /etc/ group é um conjunto de campos
separados por dois pontos. Os campos em cada entrada são os seguintes, da esquerda para a direita:

O nome do grupo Isso aparece quando você executa um comando como ls -l.

A senha do grupo As senhas do grupo Unix raramente são usadas, nem você deve usá-las (uma
boa alternativa na maioria dos casos é o sudo). Use * qualquer outro valor padrão. Um x aqui ou
significa que há uma entrada correspondente em /etc/ gshadow, e isso também é quase sempre
uma senha desabilitada, denotada com um
* ou !.

O ID do grupo (um número) O GID deve ser exclusivo no arquivo do grupo .


Esse número vai para o campo de grupo de um usuário na entrada /etc/ passwd desse usuário .

Uma lista opcional de usuários que pertencem ao grupo Além dos usuários listados aqui,
usuários com o ID de grupo correspondente em sua senha
entradas de arquivo também pertencem ao grupo.

A Figura 7-2 identifica os campos em uma entrada de arquivo de grupo .

Nome do grupo
Senha

ID do grupo
Membros adicionais

disco:*:6:juser,beazley
Figura 7-2: Uma entrada no arquivo de grupo

Para ver os grupos aos quais você pertence, execute grupos.

NOTA As distribuições Linux geralmente criam um novo grupo para cada novo usuário adicionado, com o mesmo
nome do usuário.

180 Capítulo 7
Machine Translated by Google

7.4 getty e login


O programa getty se conecta aos terminais e exibe um prompt de login. Na maioria dos sistemas
Linux, getty não é complicado porque o sistema o utiliza apenas para logins em terminais virtuais. Em
uma lista de processos, geralmente se parece com isso (por exemplo, ao executar em /dev/ tty1):

$ ps ao args | grep getty


/sbin/agetty -o -p -- \u --noclear tty1 linux

Em muitos sistemas, você pode nem ver um processo getty até acessar um terminal virtual com
algo como CTRL-ALT-F1. Este exemplo mostra agetty, a versão que muitas distribuições Linux incluem
por padrão.
Depois de inserir seu nome de login, getty se substitui pelo programa de login , que solicita sua
senha. Se você digitar a senha correta, faça o login
substitui a si mesmo (usando exec()) pelo seu shell. Caso contrário, você receberá uma mensagem
“Login incorreto”. Grande parte do trabalho real de autenticação do programa de login é feito pelo PAM
(consulte a Seção 7.10).

OBSERVAÇÃO Ao investigar o getty, você pode encontrar uma referência a uma taxa de transmissão como
“38400”. Essa configuração é praticamente obsoleta. Os terminais virtuais ignoram a taxa de
transmissão; está lá apenas para conectar-se a linhas seriais reais.

Agora você sabe o que getty e login fazem, mas provavelmente nunca precisará configurá-los ou
alterá-los. Na verdade, você raramente os usará, porque a maioria dos usuários agora faz login por
meio de uma interface gráfica como gdm ou remotamente com SSH, nenhum dos quais usa getty ou
login.

7.5 Configurando o Horário


Máquinas Unix dependem de cronometragem precisa. O kernel mantém o relógio do sistema, que é o
relógio consultado quando você executa comandos como data.
Você também pode definir o relógio do sistema usando o comando date , mas geralmente é uma má
ideia fazer isso porque você nunca terá a hora exata. O relógio do seu sistema deve estar o mais
próximo possível da hora correta.
O hardware do PC tem um relógio em tempo real (RTC) com bateria. O RTC não é o melhor
relógio do mundo, mas é melhor que nada. O kernel geralmente define sua hora com base no RTC no
momento da inicialização, e você pode redefinir o relógio do sistema para a hora atual do hardware
com hwclock. Mantenha o relógio do seu hardware em UTC (Universal Coordinated Time) para evitar
problemas com as correções de fuso horário ou horário de verão. Você pode definir o RTC para o
relógio UTC do seu kernel usando este comando:

# hwclock --systohc --utc

Infelizmente, o kernel é ainda pior em manter o tempo do que o RTC, e porque as máquinas Unix
geralmente permanecem por meses ou anos em um único

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 181


Machine Translated by Google

boot, eles tendem a desenvolver desvio de tempo. O desvio de tempo é a diferença atual entre o
tempo do kernel e o tempo real (conforme definido por um relógio atômico ou outro relógio muito preciso).

Você não deve tentar corrigir o desvio de tempo com hwclock porque eventos de sistema baseados
em tempo podem ser perdidos ou danificados. Você pode executar um utilitário como o adjtimex para
atualizar o relógio sem problemas com base no RTC, mas geralmente é melhor manter a hora do
sistema correta com um daemon de hora da rede (consulte a Seção 7.5.2).

7.5.1 Representação do Horário do Kernel e Fusos Horários


O relógio do sistema do kernel representa a hora atual como o número de segundos desde 12:00 da meia-
noite de 1º de janeiro de 1970, UTC. Para ver esse número no momento, execute:

$ data +%s

Para converter esse número em algo que os humanos possam ler, os programas espaciais do
usuário o alteram para a hora local e compensam o horário de verão e quaisquer outras circunstâncias
estranhas (como morar em Indiana). O fuso horário local é controlado pelo arquivo /etc/ localtime. (Não
se preocupe em tentar olhar para ele; é um arquivo binário.)

Os arquivos de fuso horário em seu sistema estão em /usr/ share/ zoneinfo. Você descobrirá que
esse diretório contém muitos fusos horários e aliases para fusos horários.
Para definir o fuso horário do seu sistema manualmente, copie um dos arquivos em /usr/ share/
zoneinfo para /etc/ localtime (ou faça um link simbólico) ou altere-o com a ferramenta de fuso horário da sua
distribuição. O programa de linha de comando tzselect
pode ajudá-lo a identificar um arquivo de fuso horário.
Para usar um fuso horário diferente do padrão do sistema para apenas um shell ses
sion, defina a variável de ambiente TZ para o nome de um arquivo em /usr/ share/
zoneinfo e teste a mudança, assim:

$ export TZ=EUA/Central
$ data

Tal como acontece com outras variáveis de ambiente, você também pode definir o fuso horário para
a duração de um único comando como este:

$ TZ=EUA/Data central

7.5.2 Tempo de Rede

Se sua máquina estiver permanentemente conectada à Internet, você poderá executar um daemon
NTP (Network Time Protocol) para manter a hora usando um servidor remoto. Isso já foi tratado pelo
daemon ntpd, mas como em muitos outros serviços, o systemd substituiu isso por seu próprio pacote,
chamado timesyncd. A maioria das distribuições Linux inclui timesyncd, e é

182 Capítulo 7
Machine Translated by Google

habilitado por padrão. Você não deve precisar configurá-lo, mas se estiver interessado em
como fazê-lo, a página de manual timesyncd.conf(5) pode ajudá-lo.
A substituição mais comum é alterar o(s) servidor(es) de tempo remoto(s).
Se você quiser executar o ntpd, precisará desabilitar o timesyncd se o tiver instalado.
Acesse https:// www.ntppool.org/ para ver as instruções. Este site também pode ser útil se você
ainda quiser usar o timesyncd com servidores diferentes.

Se sua máquina não tiver uma conexão permanente com a Internet, você poderá usar um
daemon como o chronyd para manter o tempo durante as desconexões.
Você também pode definir o relógio do hardware com base no horário da rede para
ajudar o sistema a manter a coerência do horário quando for reinicializado. Muitas distribuições
fazem isso automaticamente, mas para fazer isso manualmente, certifique-se de que a hora do
seu sistema esteja configurada na rede e execute este comando:

# hwclock --systohc –-utc

7.6 Agendando Tarefas Recorrentes com cron e Timer Units


Existem duas maneiras de executar programas em uma programação repetida: cron e
unidades de timer systemd. Essa capacidade é vital para automatizar as tarefas de manutenção
do sistema. Um exemplo são os utilitários de rotação de arquivos de log para garantir que seu
disco rígido não fique cheio de arquivos de log antigos (como discutido anteriormente neste capítulo).
O serviço cron tem sido o padrão de fato para fazer isso, e vamos cobri-lo em detalhes. No
entanto, as unidades de timer do systemd são uma alternativa ao cron com vantagens em certos
casos, então veremos como usá-las também.
Você pode executar qualquer programa com o cron em qualquer horário que lhe convier. O
programa executado pelo cron é chamado de cron job. Para instalar um cron job, você criará uma
linha de entrada em seu arquivo crontab, geralmente executando o comando crontab . Por
exemplo, a seguinte entrada de arquivo crontab agenda o /home/
comando juser/bin/spmake diariamente às 9h15 (no fuso horário local):

15 09 * * * /home/juser/bin/spmake

Os cinco campos no início desta linha, delimitados por espaços em branco, especificam
o horário agendado (veja também a Figura 7-3). Os campos são os seguintes, em ordem:

• Minuto (0 a 59). Este cron job está definido para o minuto 15.
•Hora (0 a 23). Este trabalho está definido para a nona hora.
•Dia do mês (1 a 31). •Mês (1 a 12). •Dia
da semana (0 a 7). Os números 0 e 7 são
domingo.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 183


Machine Translated by Google

Minuto
Hora
Dia do mês
Mês
Dia da semana
Comando

15 09 * * * /home/juser/bin/spmake
Figura 7-3: Uma entrada no arquivo crontab

Uma estrela (*) em qualquer campo significa corresponder a todos os valores. O exame anterior
ple executa spmake diariamente porque os campos de dia do mês, mês e dia da semana
são todos preenchidos com estrelas, que o cron lê como “execute este trabalho todos os dias,
de todos os meses, de todos os dias da semana”.
Para executar spmake apenas no dia 14 de cada mês, você usaria este
linha crontab:

15 09 14 * * /home/juser/bin/spmake

Você pode selecionar mais de uma vez para cada campo. Por exemplo, para executar
o programa nos dias 5 e 14 de cada mês, você pode inserir 5,14 no terceiro campo:

15 09 5,14 * * /home/juser/bin/spmake

OBSERVAÇÃO Se a tarefa cron gerar uma saída padrão ou um erro ou sair de forma anormal, o cron deve
enviar essas informações por e-mail para o proprietário da tarefa cron (assumindo que o e-mail
funcione em seu sistema). Redirecione a saída para / dev/null ou algum outro arquivo de log se
achar o e-mail irritante.

A página de manual do crontab(5) fornece informações completas sobre o formato


do crontab.

7.6.1 Instalando Arquivos Crontab


Cada usuário pode ter seu próprio arquivo crontab, o que significa que cada sistema
pode ter vários crontabs, geralmente encontrados em /var/ spool/ cron/ crontabs.
Usuários normais não podem escrever neste diretório; o comando crontab instala, lista,
edita e remove o crontab de um usuário.
A maneira mais fácil de instalar um crontab é colocar suas entradas do crontab em um
arquivo e, em seguida, usar o arquivo crontab para instalar o arquivo como seu crontab atual.
O comando crontab verifica o formato do arquivo para certificar-se de que você não cometeu
nenhum erro. Para listar seus cron jobs, execute crontab -l. Para remover o crontab,
use crontab -r.
Depois de criar seu crontab inicial, pode ser um pouco confuso usar arquivos
temporários para fazer edições adicionais. Em vez disso, você pode editar e instalar seu

184 Capítulo 7
Machine Translated by Google

crontab em uma etapa com o comando crontab -e . Se você cometer um erro, o crontab deve informar
onde está o erro e perguntar se você deseja tentar editar novamente.

7.6.2 Arquivos Crontab do Sistema

Muitas tarefas comuns do sistema ativadas pelo cron são executadas como superusuário.
No entanto, em vez de editar e manter o crontab de um superusuário para agendá-los, as distribuições
Linux normalmente têm um arquivo /etc/ crontab para todo o sistema. Você não usará o crontab para
editar este arquivo e, em qualquer caso, é um pouco diferente no formato: antes do comando a ser
executado, há um campo adicional especificando o usuário que deve executar o trabalho. (Isso lhe dá a
oportunidade de agrupar as tarefas do sistema, mesmo que não sejam todas executadas pelo mesmo
usuário.) Por exemplo, esta tarefa cron definida em /etc/ crontab é executada às 6h42 como o superusuário
(raiz 1) :

42 6 * * * root1 /usr/local/bin/cleansystem > /dev/null 2>&1

NOTA Algumas distribuições armazenam arquivos crontab de sistema adicionais no diretório /etc/cron.d .
Esses arquivos podem ter qualquer nome, mas têm o mesmo formato que / etc/crontab.
Também pode haver alguns diretórios como / etc/cron.daily, mas os arquivos aqui são geralmente scripts
executados por um cron job específico em / etc/crontab ou / etc/cron.d. Às vezes, pode ser confuso rastrear
onde os trabalhos estão e quando são executados.

7.6.3 Unidades de Temporização

Uma alternativa para criar um cron job para uma tarefa periódica é construir uma unidade de timer systemd.
Para uma tarefa totalmente nova, você deve criar duas unidades: uma unidade de timer e uma unidade de
serviço. A razão para duas unidades é que uma unidade de cronômetro não contém nenhuma especificação

sobre a tarefa a ser executada; é apenas um mecanismo de ativação para executar uma unidade de serviço
(ou conceitualmente, outro tipo de unidade, mas o uso mais comum é para unidades de serviço).

Vejamos um par típico de unidade de timer/serviço, começando com a unidade de timer. Vamos
chamar isso de loggertest.timer; como acontece com outros arquivos de unidade personalizados, vamos
colocá-lo em /etc/ systemd/ system (consulte a Listagem 7-3).

[Unidade]
Description=Exemplo de unidade de temporizador

[Cronômetro]

OnCalendar=*-*-* *:00,20,40
Unit=loggertest.service

[Instalar]
WantedBy=timers.target

Listagem 7-3: loggertest.timer

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 185


Machine Translated by Google

Este temporizador é executado a cada 20 minutos, com a opção OnCalendar semelhante


a sintaxe do cron. Neste exemplo, está no início de cada hora, bem como 20 e 40 minutos após
cada hora.
O formato de hora OnCalendar é ano-mês-dia hora:minuto:segundo. O campo representa uma
*
por segundos é opcional. Assim como no cron, uma espécie de curinga e
vírgula permite vários valores. O periódico / sintaxe também é válido; no exemplo anterior, você pode
alterar *:00,20,40 para *:00/20 (a cada 20 minutos) para obter o mesmo efeito.

OBSERVAÇÃO A sintaxe para horários no campo OnCalendar possui muitos atalhos e variações. Consulte a
seção Eventos do Calendário da página de manual do systemd.time(7) para obter a lista completa.

A unidade de serviço associada é denominada loggertest.service (consulte a Listagem 7-4).


Nós o nomeamos explicitamente no timer com a opção Unit , mas isso não é estritamente necessário
porque o systemd procura um arquivo .service com o mesmo nome base do arquivo de unidade do
timer. Esta unidade de serviço também vai em /etc/ systemd/ system, e se parece bastante com as
unidades de serviço que você viu no Capítulo 6.

[Unidade]
Description=Exemplo de serviço de teste

[Serviço]
Tipo = oneshot
ExecStart=/usr/bin/logger -p local3.debug Sou um registrador

Listagem 7-4: loggertest.service

A carne disso é a linha ExecStart , que é o comando que o serviço executa quando ativado.
Este exemplo específico envia uma mensagem para o log do sistema.

Observe o uso de oneshot como o tipo de serviço, indicando que o serviço


espera-se que seja executado e encerrado, e esse systemd não considerará o serviço iniciado
até que o comando especificado pelo ExecStart seja concluído. Isso tem algumas vantagens para os
temporizadores:

•Você pode especificar vários comandos ExecStart no arquivo de unidade. Os outros estilos de
unidade de serviço que vimos no Capítulo 6 não permitem isso.

•É mais fácil controlar a ordem de dependência estrita ao ativar outras unidades usando as
diretivas de dependência Wants e Before .
• Você tem melhores registros de horários de início e término da unidade no
Diário.

NOTA Neste exemplo de unidade, estamos usando o logger para enviar uma entrada ao syslog e ao journal.
Você leu na Seção 7.1.2 que pode visualizar as mensagens de log por unidade. No entanto, a
unidade pode terminar antes que journald tenha a chance de receber a mensagem. Esta é uma
condição de corrida e, caso a unidade seja concluída muito rapidamente, journald não poderá
procurar a unidade associada à mensagem syslog (isso é feito pelo ID do processo).

186 Capítulo 7
Machine Translated by Google

Consequentemente, a mensagem que é escrita no diário pode não incluir um campo de unidade,
renderizando um comando de filtragem como journalctl -f -u loggertest.service
incapaz de mostrar a mensagem syslog. Isso normalmente não é um problema em serviços de
execução mais longa.

7.6.4 cron vs. unidades de temporizador

O utilitário cron é um dos componentes mais antigos de um sistema Linux; ele existe há décadas
(antes do próprio Linux), e seu formato de configuração não mudou muito por muitos anos. Quando
algo fica tão velho, torna-se forragem para substituição.

As unidades de timer systemd que você acabou de ver podem parecer uma substituição
lógica e, de fato, muitas distribuições agora mudaram as tarefas de manutenção periódica no nível
do sistema para unidades de timer. Mas acontece que o cron tem algumas vantagens:

• Configuração mais simples

•Compatibilidade com muitos serviços de terceiros


• Mais fácil para os usuários instalarem suas próprias tarefas

As unidades de temporizador oferecem estas vantagens:

• Acompanhamento superior de processos associados a tarefas/unidades com cgroups

• Excelente rastreamento de informações de diagnóstico na revista

• Opções adicionais para tempos e frequências de ativação

• Capacidade de usar dependências do systemd e mecanismos de ativação

Talvez algum dia haja uma camada de compatibilidade para tarefas cron da mesma
maneira que unidades de montagem e /etc/ fstab. No entanto, a configuração por si só é uma razão
pela qual é improvável que o formato cron desapareça tão cedo. Como você verá na próxima seção,
um utilitário chamado systemd-run permite criar unidades de timer e serviços associados sem criar
arquivos de unidade, mas o gerenciamento e a implementação diferem o suficiente para que muitos
usuários provavelmente prefiram o cron. Você verá um pouco disso em breve quando dis

xingar .

7.7 Agendando Tarefas Únicas com pelo


Para executar um trabalho uma vez no futuro sem usar o cron, use o serviço at . Por exemplo, para
executar myjob às 22h30, digite este comando:

$ às 22h30

em> meu trabalho

Finalize a entrada com CTRL-D. (O utilitário at lê os comandos da entrada padrão.)

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 187


Machine Translated by Google

Para verificar se o trabalho foi agendado, use atq. Para removê-lo, use atrm. Você também
pode agendar dias de trabalho para o futuro adicionando a data no formato DD.MM.AA — por
exemplo, às 22h30 de 30.09.15.
Não há muito mais para o comando . Embora não seja usado isso
muitas vezes, pode ser inestimável quando surge a necessidade.

7.7.1 Equivalentes da Unidade do Temporizador

Você pode usar unidades de timer systemd como um substituto para at. Elas são muito mais fáceis
de criar do que as unidades de timer periódicas que você viu anteriormente e podem ser executadas
na linha de comando assim:

# systemd-run --on-calendar='2022-08-14 18:00' /bin/echo este é um teste


Temporizador em execução como unidade: run-rbd000cc6ee6f45b69cb87ca0839c12de.timer
Executará o serviço como unidade: run-rbd000cc6ee6f45b69cb87ca0839c12de.service

O comando systemd-run cria uma unidade de temporizador transitória que você pode visualizar
com o comando usual systemctl list-timers . Se você não se importa com um horário específico, você
pode especificar um deslocamento de tempo com --on-active (por exemplo, --on-active=30m para 30
minutos no futuro).

OBSERVAÇÃO Ao usar --on-calendar, é importante incluir uma data (futura) do calendário, bem como a hora. Caso
contrário, as unidades de cronômetro e serviço permanecerão, com o cronômetro executando o serviço
todos os dias no horário especificado, da mesma forma que faria se você criasse uma unidade de
cronômetro normal conforme descrito anteriormente. A sintaxe para esta opção é a mesma da opção
OnCalendar em unidades de temporizador.

7.8 Unidades de temporizador funcionando como usuários regulares

Todas as unidades de timer systemd que vimos até agora foram executadas como root. Também é
possível criar uma unidade de timer como um usuário comum. Para fazer isso, adicione a opção --
user ao systemd-run.
No entanto, se você efetuar logout antes da unidade ser executada, a unidade não iniciará; e
se você efetuar logout antes que a unidade seja concluída, a unidade será encerrada. Isso acontece
porque o systemd possui um gerenciador de usuários associado a um usuário logado, e isso é
necessário para executar unidades de timer. Você pode dizer ao systemd para manter o gerenciador
de usuários depois de sair com este comando:

$ loginctl enable-linger

Como root, você também pode habilitar um gerenciador para outro usuário:

# loginctl enable-linger user

188 Capítulo 7
Machine Translated by Google

7.9 Tópicos de Acesso do Usuário

O restante deste capítulo abrange vários tópicos sobre como os usuários obtêm a permissão para efetuar
login, alternar para outros usuários e realizar outras tarefas relacionadas. Este é um material um tanto
avançado, e você pode pular para o próximo capítulo se estiver pronto para sujar as mãos com alguns
processos internos.

7.9.1 IDs de usuário e troca de usuário


Discutimos como programas setuid, como sudo e su , permitem que você altere temporariamente os
usuários, e abordamos componentes do sistema, como login , que controlam o acesso do usuário. Talvez
você esteja se perguntando como essas peças funcionam e qual o papel do kernel na troca de usuários.

Quando você alterna temporariamente para outro usuário, tudo o que você está fazendo é alterar
sua ID de usuário. Existem duas maneiras de fazer isso, e o kernel lida com ambas. A primeira é com
um executável setuid, que foi abordado na Seção 2.17. A segunda é através da família setuid() de
chamadas de sistema.
Existem algumas versões diferentes dessa chamada de sistema para acomodar os vários IDs de usuário
associados a um processo, como você aprenderá na Seção 7.9.2.
O kernel tem regras básicas sobre o que um processo pode ou não fazer, mas aqui estão os
três fundamentos que cobrem os executáveis setuid e setuid():

•Um processo pode executar um executável setuid desde que tenha permissões de arquivo adequadas.

• Um processo rodando como root (ID de usuário 0) pode usar setuid() para se tornar qualquer
outro usuário.

•Um processo que não está rodando como root tem severas restrições sobre como ele pode usar setuid();
na maioria dos casos, não pode.

Como consequência dessas regras, se você quiser alternar os IDs de um usuário comum para
outro, geralmente precisará de uma combinação dos métodos.
Por exemplo, o executável sudo é setuid root e, uma vez executado, pode chamar setuid() para se
tornar outro usuário.

NOTA Em sua essência, a troca de usuário não tem nada a ver com senhas ou nomes de usuário. Esses são conceitos
estritamente de espaço do usuário, como você viu pela primeira vez no arquivo /etc/passwd na Seção 7.3.1.
Você aprenderá mais detalhes sobre como isso funciona na Seção 7.9.4.

7.9.2 Propriedade do processo, UID efetivo, UID real e UID salvo


Nossa discussão sobre IDs de usuário até agora foi simplificada. Na realidade, cada processo tem mais
de um ID de usuário. Até agora, você está familiarizado com o ID de usuário efetivo (UID efetivo ou euid),
que define os direitos de acesso para um processo (mais significativamente, permissões de arquivo). Um
segundo ID de usuário, o ID de usuário real (UID real ou ruid), indica quem iniciou um processo.
Normalmente, esses IDs são idênticos, mas quando você executa um programa setuid, o Linux define o euid
para o proprietário do programa durante a execução, mas mantém seu ID de usuário original no ruid.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 189


Machine Translated by Google

A diferença entre os UIDs efetivos e reais é confusa, tanto que muita documentação
sobre a propriedade do processo é
incorreta.
Pense no euid como o ator e no ruid como o dono. O ruid define o usuário que pode

interagir com o processo em execução – mais significativamente, qual usuário pode matar e enviar
sinais para um processo. Por exemplo, se o usuário A inicia um novo processo que é executado
como usuário B (com base nas permissões setuid), o usuário A ainda possui o processo e pode
eliminá-lo.
Vimos que a maioria dos processos tem o mesmo euid e ruid. Como resultado, a saída
padrão para ps e outros programas de diagnóstico do sistema mostram apenas o euid. Para visualizar
os dois IDs de usuário em seu sistema, tente isto, mas não se surpreenda se você descobrir que as
duas colunas de ID de usuário são idênticas para todos os processos em seu sistema:

$ ps -eo pid,usuário,ruser,comm

Para criar uma exceção apenas para que você possa ver valores diferentes no
colunas, tente experimentar criando uma cópia setuid do comando sleep , executando a cópia
por alguns segundos e, em seguida, executando o comando ps anterior em outra janela antes que a
cópia termine.
Para aumentar a confusão, além dos IDs de usuário reais e efetivos, há também um ID de
usuário salvo (que geralmente não é abreviado). Um processo pode mudar seu euid para o ruid ou ID
de usuário salvo durante a execução. (Para tornar as coisas ainda mais complicadas, o Linux tem
ainda outro ID de usuário: o ID de usuário do sistema de arquivos, ou fsuid, que define o usuário que
acessa o sistema de arquivos, mas raramente é usado.)

Comportamento Típico do Programa Setuid

A ideia do ruid pode contradizer sua experiência anterior. Por que você não precisa lidar com os
outros IDs de usuário com muita frequência? Por exemplo, depois de iniciar um processo com sudo,
se você quiser eliminá-lo, você ainda usa sudo; você não pode matá-lo como seu próprio usuário
regular. Seu usuário regular não deveria ser o ruid neste caso, dando a você as permissões corretas?

A causa desse comportamento é que o sudo e muitos outros programas setuid


altere explicitamente o euid e o ruid com uma das chamadas de sistema setuid() .
Esses programas fazem isso porque geralmente há efeitos colaterais indesejados e problemas de
acesso quando todos os IDs de usuário não correspondem.

OBSERVAÇÃO Se você estiver interessado nos detalhes e regras sobre troca de ID de usuário, leia a página
de manual do setuid(2) e verifique as outras páginas de manual listadas na seção CONSULTE
TAMBÉM. Existem muitas chamadas de sistema diferentes para diversas situações.

Alguns programas não gostam de ter um ruid de root. Para evitar que o sudo altere o ruid,
adicione esta linha ao seu arquivo /etc/ sudoers (e cuidado com os efeitos colaterais em outros
programas que você deseja executar como root!):

Padrões stay_setuid

190 Capítulo 7
Machine Translated by Google

Implicações de segurança

Como o kernel do Linux lida com todas as opções de usuário (e, como resultado, permissões
de acesso a arquivos) por meio de programas setuid e chamadas de sistema subsequentes, os
desenvolvedores e administradores de sistemas devem ser extremamente cuidadosos com duas
coisas:

• O número e a qualidade dos programas que possuem permissões setuid


•O que esses programas fazem

Se você fizer uma cópia do shell bash que é setuid root, qualquer usuário local poderá
executá-lo e ter a execução completa do sistema. É realmente tão simples.
Além disso, mesmo um programa de propósito especial que é setuid root pode representar um
perigo se tiver bugs. Explorar os pontos fracos em programas executados como root é um método
primário de invasão de sistemas, e há muitos desses exploits para contar.

Como há tantas maneiras de invadir um sistema, impedir a intrusão é um assunto


multifacetado. Uma das maneiras mais essenciais de manter atividades indesejadas fora do
seu sistema é impor a autenticação do usuário com nomes de usuário e boas senhas.

7.9.3 Identificação, autenticação e autorização do usuário


Um sistema multiusuário deve fornecer suporte básico para segurança do usuário em três
áreas: identificação, autenticação e autorização. A identificação
parte da segurança responde à questão de quem são os usuários. A autenticação
peça pede aos usuários que provem que são quem dizem ser. Finalmente, a autorização é usada
para definir e limitar o que os usuários têm permissão para fazer.
Quando se trata de identificação do usuário, o kernel do Linux conhece apenas os IDs
numéricos do usuário para propriedade de processo e arquivo. O kernel conhece as regras de
autorização de como executar os executáveis setuid e como os IDs de usuário podem executar
a família setuid() de chamadas de sistema para mudar de um usuário para outro.
No entanto, o kernel não sabe nada sobre autenticação: nomes de usuário, senhas e assim
por diante. Praticamente tudo relacionado à autenticação acontece no espaço do usuário.

Discutimos o mapeamento entre IDs de usuário e senhas na Seção 7.3.1; agora


abordaremos como os processos do usuário acessam esse mapeamento. Começaremos com um
caso simplificado, no qual um processo de usuário deseja saber seu nome de usuário (o nome
correspondente ao euid). Em um sistema Unix tradicional, um processo poderia fazer algo assim
para obter seu nome de usuário:

1. O processo pede ao kernel seu euid com a chamada de sistema geteuid() .


2. O processo abre o arquivo /etc/ passwd e inicia a leitura no início.

3. O processo lê uma linha do arquivo /etc/ passwd . Se não há mais nada para
read, o processo falhou em encontrar o nome de usuário.
4. O processo analisa a linha em campos (dividindo tudo
entre os dois pontos). O terceiro campo é o ID do usuário para a linha atual.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 191


Machine Translated by Google

5. O processo compara o ID da etapa 4 com o ID da etapa 1. Se


eles são idênticos, o primeiro campo na etapa 4 é o nome de usuário desejado e o
processo pode parar de pesquisar e usar esse nome.
6. O processo segue para a próxima linha em /etc/ passwd e volta para a etapa 3.

Este é um procedimento longo, e uma implementação no mundo real geralmente é


ainda mais complicada.

7.9.4 Usando Bibliotecas para Informações do Usuário


Se todo desenvolvedor que precisasse saber o nome de usuário atual tivesse que escrever
todo o código que você acabou de ver, o sistema seria uma bagunça horrivelmente
desarticulada, cheia de bugs, inchada e insustentável. Felizmente, muitas vezes existem
bibliotecas padrão que podemos usar para realizar tarefas repetitivas como esta; neste
caso, tudo o que você normalmente precisa fazer para obter um nome de usuário é chamar
uma função como getpwuid() na biblioteca padrão depois de obter a resposta de geteuid().
(Consulte as páginas de manual dessas chamadas para saber mais sobre como elas funcionam.)
A biblioteca padrão é compartilhada entre os executáveis em seu sistema, para que
você possa fazer alterações significativas na implementação da autenticação sem alterar
nenhum programa. Por exemplo, você pode deixar de usar /etc/ passwd para seus usuários e
usar um serviço de rede, como LDAP, alterando apenas a configuração do sistema.

Essa abordagem funcionou bem para identificar nomes de usuário associados a IDs
de usuário, mas as senhas se mostraram mais problemáticas. A Seção 7.3.1 descreve
como, tradicionalmente, a senha criptografada fazia parte de /etc/ passwd, então se você
quisesse verificar uma senha que um usuário digitou, você criptografaria o que o usuário
digitou e compararia com o conteúdo da arquivo /etc/ passwd .
Essa implementação tradicional tem muitas limitações, incluindo:

• Não permite que você defina um padrão de todo o sistema para a criptografia
protocolo.
•Assume-se que você tem acesso à senha criptografada.
•Assume-se que você deseja solicitar uma senha ao usuário toda vez que o usuário quiser
acessar algo que exija autenticação (o que é irritante).

•Assume-se que você deseja usar senhas. Se você quiser usar tokens de uso único, cartões
inteligentes, biometria ou alguma outra forma de autenticação de usuário, você mesmo
deve adicionar esse suporte.

Algumas dessas limitações contribuíram para o desenvolvimento da sombra


password discutido na Seção 7.3.3, que deu o primeiro passo para permitir a configuração
de senha em todo o sistema. Mas a solução para a maior parte dos problemas veio com o
projeto e a implementação do PAM.

7.10 Módulos de autenticação plugáveis


Para acomodar a flexibilidade na autenticação do usuário, em 1995 a Sun Microsystems
propôs um novo padrão chamado Pluggable Authentication Modules (PAM), um sistema

192 Capítulo 7
Machine Translated by Google

de bibliotecas compartilhadas para autenticação (Open Software Foundation RFC 86.0,


outubro de 1995). Para autenticar um usuário, um aplicativo entrega o usuário ao PAM para
determinar se o usuário pode se identificar com êxito. Dessa forma, é relativamente fácil
adicionar suporte para técnicas de autenticação adicionais, como chaves físicas e de dois
fatores. Além do suporte ao mecanismo de autenticação, o PAM também fornece uma
quantidade limitada de controle de autorização para serviços (por exemplo, se você quiser negar
um serviço como o cron para determinados usuários).
Como há muitos tipos de cenários de autenticação, o PAM emprega vários módulos de
autenticação carregáveis dinamicamente. Cada módulo executa uma tarefa específica e é um
objeto compartilhado que os processos podem carregar dinamicamente e executar em seu
espaço executável. Por exemplo, pam_unix.so é um módulo que pode verificar a senha de um
usuário.
Este é um negócio complicado, para dizer o mínimo. A interface de programação não
é fácil e não está claro se o PAM realmente resolve todos os problemas existentes. No entanto,
o PAM é suportado em quase todos os programas que exigem autenticação em um sistema
Linux, e a maioria das distribuições usa o PAM. E como funciona em cima da API de autenticação
Unix existente, a integração do suporte em um cliente requer pouco ou nenhum trabalho extra.

7.10.1 Configuração do PAM


Exploraremos o básico de como o PAM funciona examinando sua configuração.
Você normalmente encontrará os arquivos de configuração do aplicativo do PAM em /etc/ pam.d
diretório (sistemas mais antigos podem usar um único arquivo /etc/ pam.conf ). A maioria das
instalações inclui muitos arquivos, então você pode não saber por onde começar. Alguns nomes
de arquivos, como cron e passwd, correspondem a partes do sistema que você já conhece.
Como a configuração específica nesses arquivos varia significativamente entre as
distribuições, pode ser difícil encontrar um exemplo comumente aplicável. Veremos uma
linha de configuração de exemplo que você pode encontrar para chsh (o programa de shell
de mudança):

autenticação
requisito pam_shells.so

Esta linha diz que o shell do usuário deve estar listado em /etc/ shells para que
que o usuário se autentique com sucesso com o programa chsh . Vamos ver como.
Cada linha de configuração possui três campos: um tipo de função, um argumento de controle e
um módulo, nessa ordem. Veja o que eles significam para este exemplo:

Tipo de função A função que um aplicativo de usuário solicita que o PAM execute. Aqui,
é auth, a tarefa de autenticar o usuário.
Argumento de controle Esta configuração controla o que o PAM faz após o sucesso ou
falha de sua ação para a linha atual (requisito neste exemplo).
Chegaremos a isso em breve.
Módulo O módulo de autenticação que é executado para esta linha, determinando o que
a linha realmente faz. Aqui, o módulo pam_shells.so verifica se o shell atual do usuário
está listado em /etc/ shells.

A configuração do PAM é detalhada na página de manual do pam.conf(5). Vejamos


alguns dos fundamentos.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 193


Machine Translated by Google

Tipos de função

Um aplicativo de usuário pode solicitar ao PAM que execute uma das quatro funções a
seguir:

auth Autenticar um usuário (ver se o usuário é quem diz ser).


conta Verifique o status da conta do usuário (se o usuário está autorizado a fazer algo, por
exemplo). sessão Execute algo apenas para a sessão atual do usuário (como exibir uma

mensagem do dia).

senha Altere a senha de um usuário ou outras credenciais.

Para qualquer linha de configuração, o módulo e a função juntos determinam a ação do


PAM. Um módulo pode ter mais de um tipo de função, portanto, ao determinar a finalidade de
uma linha de configuração, lembre-se sempre de considerar a função e o módulo como um par. Por
exemplo, o pam_unix.so
O módulo verifica uma senha ao executar a função de autenticação , mas define uma senha ao
executar a função de senha .

Argumentos de controle e regras empilhadas

Um recurso importante do PAM é que as regras especificadas por suas linhas de configuração
são empilhadas, o que significa que você pode aplicar muitas regras ao executar uma função. É por
isso que o argumento de controle é importante: o sucesso ou fracasso de uma ação em uma linha
pode afetar as linhas subsequentes ou fazer com que toda a função seja bem-sucedida ou falhe.

Existem dois tipos de argumentos de controle: a sintaxe simples e uma sintaxe mais
avançada. Aqui estão os três principais argumentos de controle de sintaxe simples que você
encontrará em uma regra:

suficiente Se essa regra for bem-sucedida, a autenticação será bem-sucedida e o PAM não
precisará examinar mais nenhuma regra. Se a regra falhar, o PAM prossegue para regras
adicionais.

requisito Se esta regra for bem-sucedida, o PAM prossegue para regras adicionais. Se a
regra falhar, a autenticação não terá êxito e o PAM não precisará examinar mais nenhuma regra.

obrigatório Se esta regra for bem-sucedida, o PAM prossegue para regras adicionais. Se
a regra falhar, o PAM prossegue para regras adicionais, mas sempre retornará uma
autenticação malsucedida, independentemente do resultado final das regras adicionais.

Continuando com o exemplo anterior, aqui está uma pilha de exemplo para
a função de autenticação chsh :

autenticação suficiente pam_rootok.so


autenticação
requisito pam_shells.so
autenticação suficiente pam_unix.so
autenticação
necessário pam_deny.so

194 Capítulo 7
Machine Translated by Google

Com essa configuração, quando o comando chsh solicita que o PAM execute a
função de autenticação, o PAM faz o seguinte (consulte a Figura 7-4 para obter um
fluxograma):

1. O módulo pam_rootok.so verifica se root é o usuário que está tentando autenticar.


Em caso afirmativo, ele é imediatamente bem-sucedido e não tenta mais
autenticação. Isso funciona porque o argumento de controle está definido como
suficiente, significando que o sucesso desta ação é bom o suficiente para o PAM
relatar imediatamente o sucesso de volta ao chsh. Caso contrário, segue para o passo 2.

Início do PAM: solicitação para autenticação

pam_rootok.so: Sim
O root está tentando autenticar?

Não

Não pam_shells.so:
O shell está em /etc/shells?

Sim

pam_unix.so: Sim
O usuário digitou a senha correta?

Não

pam_deny.so:
Sempre falha

Falha na autenticação Autenticação bem-sucedida

Figura 7-4: fluxo de execução da regra PAM

2. O módulo pam_shells.so verifica se o shell do usuário está listado em


/ etc/ shell. Se não estiver lá, o módulo retorna falha e o requisito

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 195


Machine Translated by Google

O argumento de controle indica que o PAM deve relatar imediatamente essa falha de
volta ao chsh e não tentar nenhuma autenticação adicional. Caso contrário, o módulo
retorna sucesso e cumpre o flag de controle de requisito; prossiga para o passo 3.
3. O módulo pam_unix.so solicita a senha do usuário e a verifica. O argumento de
controle é definido como suficiente, então o sucesso deste módulo (uma senha
correta) é suficiente para o PAM relatar o sucesso ao chsh.
Se a senha estiver incorreta, o PAM continua na etapa 4.
4. O módulo pam_deny.so sempre falha e, como o argumento de controle está definido
como obrigatório, o PAM relata a falha de volta ao chsh. Este é um padrão para quando
não há mais nada para tentar. (Observe que um argumento de controle obrigatório não
faz com que o PAM falhe em sua função imediatamente - ele executará todas as linhas
restantes em sua pilha - mas o PAM sempre relatará a falha de volta ao aplicativo.)

NOTA Não confunda os termos função e ação ao trabalhar com o PAM. A função
ção é o objetivo de alto nível: o que o aplicativo do usuário deseja que o PAM faça
(autenticar um usuário, por exemplo). Uma ação é uma etapa específica que o PAM realiza
para atingir esse objetivo. Apenas lembre-se de que o aplicativo do usuário invoca a função
primeiro e que o PAM cuida dos detalhes com ações.

A sintaxe do argumento de controle avançado, indicada entre colchetes ([]), permite


controlar manualmente uma reação com base no valor de retorno específico do módulo
(não apenas sucesso ou falha). Para detalhes, veja a página de manual do pam.conf(5);
quando você entender a sintaxe simples, não terá problemas com a sintaxe avançada.

Argumentos do módulo

Os módulos PAM podem receber argumentos após o nome do módulo. Você


encontrará frequentemente este exemplo com o módulo pam_unix.so :

autenticação
suficiente pam_unix.so nullok

O argumento nullok aqui diz que o usuário não pode ter senha (o padrão seria falha
se o usuário não tiver senha).

7.10.2 Dicas sobre a sintaxe de configuração do PAM

Devido à sua capacidade de fluxo de controle e sintaxe de argumento do módulo, a


sintaxe de configuração do PAM possui muitos recursos de uma linguagem de
programação e um certo grau de poder. Nós apenas arranhamos a superfície até agora,
mas aqui estão mais algumas dicas sobre o PAM:

•Para descobrir quais módulos PAM estão presentes em seu sistema, tente
man -k pam_ (observe o sublinhado). Pode ser difícil rastrear a localização dos
módulos. Experimente o comando locate pam_unix.so e veja onde isso o leva.

196 Capítulo 7
Machine Translated by Google

•As páginas do manual contêm as funções e argumentos para cada


módulo.

•Muitas distribuições geram automaticamente certos arquivos de configuração do PAM,


portanto, pode não ser aconselhável alterá-los diretamente em /etc/ pam.d. Leia os
comentários em seus arquivos /etc/ pam.d antes de editá-los; se forem arquivos
gerados, os comentários lhe dirão de onde vieram. •O arquivo de configuração /etc/
pam.d/ other define a configuração padrão para qualquer aplicativo que não tenha seu
próprio arquivo de configuração. O padrão é muitas vezes negar tudo.

•Existem diferentes maneiras de incluir arquivos de configuração adicionais em um


arquivo de configuração PAM. A sintaxe @include carrega um arquivo de
configuração inteiro, mas você também pode usar um argumento de controle
para carregar apenas a configuração de uma função específica. O uso varia entre
as distribuições.

•A configuração do PAM não termina com os argumentos do módulo. Alguns módulos


podem acessar arquivos adicionais em /etc/ security, geralmente para configurar
restrições por usuário.

7.10.3 PAM e Senhas


Devido à evolução da verificação de senha do Linux ao longo dos anos, há vários artefatos
de configuração de senha que às vezes podem causar confusão. O primeiro a conhecer é
o arquivo /etc/ login.defs. Este é o arquivo de configuração para o conjunto de senhas
shadow original. Ele contém informações sobre o algoritmo de criptografia usado para o
arquivo de senha /etc/ shadow , mas raramente é usado em um sistema com PAM instalado,
porque a configuração do PAM contém essas informações. Dito isso, o algoritmo de
criptografia em /etc/ login.defs
deve corresponder à configuração do PAM no caso raro de você executar um aplicativo
que não oferece suporte ao PAM.
Onde o PAM obtém suas informações sobre o esquema de criptografia de senha?
Lembre-se de que existem duas maneiras de o PAM interagir com as senhas: a função
auth (para verificar uma senha) e a função password (para definir uma senha). É mais
fácil rastrear o parâmetro de configuração de senha. A melhor maneira é provavelmente
apenas grep :

$ grep password.*unix /etc/pam.d/*

As linhas correspondentes devem conter pam_unix.so e ser algo assim:

senha suficiente pam_unix.so obscuro sha512

Os argumentos obscurecem e sha512 dizem ao PAM o que fazer ao definir uma


senha. Primeiro, o PAM verifica se a senha é “obscura” o suficiente (ou seja, a senha
não é muito semelhante à senha antiga, entre outras coisas), e então o PAM usa o
algoritmo SHA512 para criptografar a nova senha.

Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários 197


Machine Translated by Google

Mas isso acontece apenas quando um usuário define uma senha, não quando o
PAM está verificando uma senha. Então, como o PAM sabe qual algoritmo usar ao
autenticar? Infelizmente, a configuração não lhe dirá nada; não há argumentos de
criptografia para pam_unix.so para a função auth .
As páginas de manual também não dizem nada.
Acontece que (no momento da redação deste artigo) pam_unix.so simplesmente tenta adivinhar o
algoritmo, geralmente pedindo à biblioteca libcrypt para fazer o trabalho sujo de tentar um
monte de coisas até que algo funcione ou não haja mais nada para tentar. Portanto, você
normalmente não precisa se preocupar com o algoritmo de criptografia de verificação.

7.11 Olhando para o futuro


Estamos agora no ponto médio de nossa progressão neste livro, tendo abordado muitos dos
blocos de construção vitais de um sistema Linux. A discussão sobre log e usuários em um
sistema Linux mostrou como é possível dividir serviços e tarefas em pedaços pequenos e
independentes que ainda podem
interagir até certo ponto.

Este capítulo tratou quase exclusivamente do espaço do usuário, e agora precisamos


refinar nossa visão dos processos do espaço do usuário e dos recursos que eles consomem.
Para fazer isso, voltaremos ao kernel no Capítulo 8.

198 Capítulo 7
Machine Translated by Google

ACLOSERLOOKATPROCESSE S
8
E UTILIZAÇÃO DE RECURSOS

Este capítulo o aprofunda nas relações entre os


processos, o kernel e os recursos do sistema.
Existem três tipos básicos de recursos de hardware:
CPU, memória e E/S.
Os processos competem por esses recursos, e o trabalho do
kernel é alocar recursos de forma justa. O próprio kernel
também é um recurso — um recurso de software que os
processos usam para executar tarefas como criar novos
processos e comunicar-se com outros processos.
Muitas das ferramentas que você vê neste capítulo são consideradas
ferramentas de monitoramento de desempenho. Eles são particularmente úteis se
o seu sistema estiver lento demais e você estiver tentando descobrir o motivo. No
entanto, você não deve se distrair com o desempenho. Tentando otimizar um sistema
Machine Translated by Google

que já está funcionando corretamente é uma perda de tempo. As configurações padrão na maioria dos
sistemas são bem escolhidas, portanto, você deve alterá-las apenas se tiver necessidades muito
incomuns. Em vez disso, concentre-se em entender o que as ferramentas realmente medem, e você
obterá uma grande percepção de como o kernel funciona e como ele interage com os processos.

8.1 Processos de Rastreamento


Você aprendeu a usar ps na Seção 2.16 para listar processos em execução em seu sistema em um
determinado momento. O comando ps lista os processos atuais e suas estatísticas de uso, mas pouco
informa como os processos mudam ao longo do tempo. Portanto, não o ajudará a determinar
imediatamente qual processo está usando muito tempo de CPU ou memória.

O programa superior fornece uma interface interativa para as informações que o ps exibe. Ele
mostra o status atual do sistema, bem como os campos a ps
a listagem é exibida e é atualizada a cada segundo. Talvez o mais importante, top lista os processos
mais ativos (por padrão, aqueles que atualmente ocupam mais tempo de CPU) na parte superior de sua
tela.
Você pode enviar comandos para o topo com teclas. Seu uso mais frequente
comandos lidam com a alteração da ordem de classificação ou filtragem da lista de processos:

Barra de espaço Atualiza a exibição imediatamente

M Classifica pelo uso de memória residente atual

T Classifica pelo uso total (cumulativo) da CPU

P Classifica pelo uso atual da CPU (o padrão)

u Exibe apenas os processos de um usuário

f Seleciona estatísticas diferentes para exibir

? Exibe um resumo de uso para todos os principais comandos

OBSERVAÇÃO Os comandos de pressionamento de tecla superior diferenciam maiúsculas de minúsculas.

Dois utilitários semelhantes, atop e htop, oferecem um conjunto aprimorado de visualizações e


recursos. A maioria de seus recursos extras adiciona funcionalidades encontradas em outras ferramentas.
Por exemplo, htop compartilha muitas das habilidades do comando lsof descritas na próxima seção.

8.2 Encontrando arquivos abertos com lsof


O comando lsof lista os arquivos abertos e os processos que os utilizam. Como o Unix dá muita
ênfase aos arquivos, o lsof está entre as ferramentas mais úteis para encontrar pontos problemáticos.
Mas lsof não para em arquivos comuns — ele pode listar recursos de rede, bibliotecas dinâmicas,
pipes e muito mais.

200 Capítulo 8
Machine Translated by Google

8.2.1 Lendo a Saída lsof


A execução de lsof na linha de comando geralmente produz uma quantidade enorme de saída. O seguinte
é um fragmento do que você pode ver. Esta saída (ligeiramente ajustada para legibilidade) inclui arquivos
abertos do processo systemd (init), bem como um processo vi em execução :

#lsof _

COMANDO PID USER FD 1 root MODELO TAMANHO DO NOME DO NÓ

sistemad cwd 1 root rtd VOCÊS DISPOSITIVO/DESLIGADO 2/


sistemad VOCÊS 8,1 4096 8,1 4096
1595792
8,1 2/
sistemad 1 root txt 1 root REG 8,1 1700792 8,1 121016 9961784 /lib/systemd/systemd
sistemad mem REG 9961570 /lib/x86_64-linux-gnu/libm-2.27.so
sistemad 1 mem raiz REG 9961695 /lib/x86_64-linux-gnu/libudev.so.1

--recorte--
nós 1994 juser cwd nós 1994 juser VOCÊS 8,1 4096 4587522 /home/juser
3u REG 8,1 12288 786440 /tmp/.ff.swp

--recorte--

A saída lista os seguintes campos na linha superior:

COMMAND O nome do comando para o processo que contém o descritor de arquivo.

PID O ID do processo.

USER O usuário que está executando o processo.

FD Este campo pode conter dois tipos de elementos. Na maioria das saídas anteriores, a coluna FD
mostra a finalidade do arquivo. O campo FD também pode listar o descritor de arquivo do arquivo
aberto – um número que um processo usa junto com as bibliotecas do sistema e o kernel para
identificar e manipular um arquivo; a última linha mostra um descritor de arquivo de 3.

TYPE O tipo de arquivo (arquivo normal, diretório, soquete e assim por diante).

DEVICE O número principal e secundário do dispositivo que contém o arquivo.


SIZE/OFF O tamanho do arquivo.

NODE O número do inode do arquivo.

NOME O nome do arquivo.

A página de manual lsof(1) contém uma lista completa do que você pode ver para cada campo,
mas a saída deve ser autoexplicativa. Por exemplo, observe as entradas com cwd no campo FD . Essas
linhas indicam os diretórios de trabalho atuais dos processos. Outro exemplo é a última linha, que mostra
um arquivo temporário que o processo vi de um usuário (PID 1994) está usando.

OBSERVAÇÃO Você pode executar lsof como root ou como usuário comum, mas obterá mais informações como root.

Um olhar mais atento aos processos e utilização de recursos 201


Machine Translated by Google

8.2.2 Usando lsof


Existem duas abordagens básicas para executar lsof:

• Liste tudo e canalize a saída para um comando como less e, em seguida, pesquise o que você
está procurando. Isso pode demorar um pouco devido à quantidade de saída gerada.

•Restringir a lista que lsof fornece com opções de linha de comando.

Você pode usar opções de linha de comando para fornecer um nome de arquivo como argumento
e ter lsof listando apenas as entradas que correspondem ao argumento. Por exemplo, o comando
a seguir exibe entradas para arquivos abertos em /usr e todos os seus subdiretórios:

$ lsof +D /usr

Para listar os arquivos abertos para um determinado ID de processo, execute:

$ lsof -p pid

Para um breve resumo das muitas opções do lsof , execute lsof -h. A maioria das opções
pertence ao formato de saída. (Veja o Capítulo 10 para uma discussão sobre o lsof
recursos de rede.)

NOTA lsof é altamente dependente das informações do kernel. Se você executar uma atualização de distribuição
para o kernel e lsof, o lsof atualizado pode não funcionar até que você reinicialize com o novo kernel.

8.3 Execução do Programa de Rastreamento e Chamadas do Sistema


As ferramentas que vimos até agora examinam os processos ativos. No entanto, se você não tem
idéia de por que um programa morre quase imediatamente após a inicialização, lsof não o ajudará. Na
verdade, você teria dificuldade em executar lsof simultaneamente com um comando com falha.

Os comandos strace (rastreamento de chamada do sistema) e ltrace (rastreamento de


biblioteca) podem ajudá-lo a descobrir o que um programa tenta fazer. Essas ferramentas
produzem quantidades extraordinariamente grandes de saída, mas quando você souber o que
procurar, terá mais informações à sua disposição para rastrear problemas.

8.3.1 linha
Lembre-se de que uma chamada de sistema é uma operação privilegiada que um processo do
espaço do usuário solicita que o kernel execute, como abrir e ler dados de um arquivo.
O utilitário strace imprime todas as chamadas de sistema que um processo faz. Para vê-lo em ação,
execute este comando:

$ strace cat /dev/null

202 Capítulo 8
Machine Translated by Google

Por padrão, o strace envia sua saída para o erro padrão. Se você deseja salvar a saída em
um arquivo, use a opção -o save_file . Você também pode redirecionar anexando 2> save_file à sua
linha de comando, mas também capturará qualquer erro padrão do comando que estiver examinando.

No Capítulo 1, você aprendeu que quando um processo deseja iniciar outro processo, ele
invoca a chamada de sistema fork() para gerar uma cópia de si mesmo e, em seguida, a cópia
usa um membro da família exec() de chamadas de sistema para iniciar a execução um novo
programa. O comando strace começa a trabalhar no novo processo (a cópia do processo original)
logo após a chamada fork() . Portanto, as primeiras linhas da saída deste comando devem
mostrar execve() em ação, seguido por uma chamada de inicialização de memória, brk(), como
segue:

execve("/bin/cat", ["cat", "/dev/null"], 0x7ffef0be0248 /* 59 vars */) = 0


brk(NULL) = 0x561e83127000

A próxima parte da saída trata principalmente do carregamento de bibliotecas


compartilhadas. Você pode ignorar isso, a menos que realmente queira se aprofundar no
sistema de biblioteca compartilhada:

access("/etc/ld.so.nohwcap", diretório = -1 ENOENT (Nenhum arquivo ou


F_OK))
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=119531, ...}) = 0
mmap(NULL, 119531, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fa9db241000
fechar(3) =0

--recorte--
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34 \2\0\0\0\0\0"..
., 832) = 832

Além disso, pule a saída do mmap até chegar às linhas próximas ao


final da saída que se parece com isso:

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 1), ...}) = 0


openat(AT_FDCWD, "/dev/null", O_RDONLY) = 3
fstat(3, {st_mode=S_IFCHR|0666, st_rdev=madeev(0x1, 3), ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
= 0x7fa9db21b000
read(3, "", 131072) =0
munmap(0x7fa9db21b000, 139264) =0
close(3) close(1) close(2) exit_group(0) =0
+++ saiu com 0 +++ =0
=0
=?

Esta parte da saída mostra o comando em ação. Primeiro, observe a chamada openat()
(uma pequena variante de open()), que abre um arquivo. O 3 é um resultado que significa
sucesso (3 é o descritor de arquivo que o kernel retorna após abrir

Um olhar mais atento aos processos e utilização de recursos 203


Machine Translated by Google

o arquivo). Abaixo disso, você pode ver onde cat lê de /dev/ null (a chamada read() , que
também tem 3 como descritor de arquivo). Então não há mais nada para ler, então o
programa fecha o descritor de arquivo e sai com exit_group().
O que acontece quando o comando encontra um erro? Tente strace cat
not_a_file e examine a chamada open() na saída resultante:

openat(AT_FDCWD, "not_a_file", O_RDONLY) = -1 ENOENT (Nenhum arquivo


ou diretório)

Como open() não conseguiu abrir o arquivo, ele retornou -1 para sinalizar um erro.
Você pode ver que o strace relata o erro exato e fornece uma breve descrição do erro.

Arquivos ausentes são o problema mais comum com programas Unix, então se o log
do sistema e outras informações de log não forem muito úteis e você não tiver mais a quem
recorrer quando estiver tentando rastrear um arquivo ausente, strace
pode ser de grande utilidade. Você pode até usá-lo em daemons que se bifurcam ou se
separam. Por exemplo, para rastrear as chamadas do sistema de um dae mon fictício
chamado crummyd, digite:

$ strace -o crummyd_strace -ff crummyd

Neste exemplo, a opção -o para strace registra a ação de qualquer processo filho que
crummyd gera em crummyd_strace.pid, onde pid é o ID do processo filho.

8.3.2 traço
O comando ltrace rastreia chamadas de bibliotecas compartilhadas. A saída é semelhante
à do strace, e é por isso que está sendo mencionado aqui, mas não rastreia nada no nível
do kernel. Esteja avisado de que há muito mais chamadas de biblioteca compartilhada do
que chamadas de sistema. Você definitivamente precisará filtrar a saída, e o próprio ltrace
possui muitas opções internas para ajudá-lo.

OBSERVAÇÃO Consulte a Seção 15.1.3 para obter mais informações sobre bibliotecas compartilhadas. O comando ltrace não funciona
em binários vinculados estaticamente.

8.4 Tópicos
No Linux, alguns processos são divididos em partes chamadas threads. Um encadeamento
é muito semelhante a um processo - ele tem um identificador (ID do encadeamento ou TID)
e o kernel agenda e executa encadeamentos como processos. No entanto, ao contrário de
processos separados, que geralmente não compartilham recursos do sistema, como memória
e conexões de E/S com outros processos, todas as threads dentro de um único processo
compartilham seus recursos de sistema e alguma memória.

8.4.1 Processos Single-Threaded e Multithread


Muitos processos têm apenas um thread. Um processo com um thread é de thread único
e um processo com mais de um thread é multithread. Tudo

204 Capítulo 8
Machine Translated by Google

os processos começam com um único thread. Esse encadeamento inicial geralmente é


chamado de encadeamento principal. A thread principal pode iniciar novas threads, tornando
o processo multithread, semelhante ao modo como um processo pode chamar fork() para
iniciar um novo processo.

OBSERVAÇÃO É raro fazer referência a threads quando um processo é de thread único. Este livro não
menciona threads, a menos que processos multithread façam diferença no que você vê ou
experimenta.

A principal vantagem de um processo multithread é que, quando o processo tem muito


a fazer, os threads podem ser executados simultaneamente em vários processadores,
potencialmente acelerando a computação. Embora você também possa obter computação
simultânea com vários processos, os encadeamentos iniciam mais rápido que os processos e
geralmente é mais fácil ou mais eficiente para os encadeamentos se comunicarem usando sua
memória compartilhada do que para os processos se comunicarem por meio de um canal, como
uma conexão de rede ou um cano.
Alguns programas usam threads para superar problemas de gerenciamento de vários
recursos de E/S. Tradicionalmente, um processo às vezes usa fork() para iniciar um novo
subprocesso para lidar com um novo fluxo de entrada ou saída. Threads oferecem um mecanismo
semelhante sem a sobrecarga de iniciar um novo processo.

8.4.2 Visualizando Tópicos


Por padrão, a saída dos comandos ps e top mostra apenas processos.
Para exibir as informações do thread em ps, adicione a opção m . A Listagem 8-1 mostra alguns
exemplos de saída.

$m
PID TTY COMANDO DE TEMPO DE ESTADO
- 0:00 bash1
3587 pts/3
--
S 0:00 -
- 0:00 bash2
3592 pontos/4
--
S 0:00 -
-
12534 tty7 668:30 /usr/lib/xorg/Xorg -core :03
--
SSL+ 659:55 -
--
SSL+ 0:00 -
--
SSL+ 0:00 -
--
SSL+ 8:35 -

Listagem 8-1: Visualizando tópicos com ps m

Esta listagem mostra processos junto com threads. Cada linha com um número
ber na coluna PID (em 1, 2 e 3) representa um processo, como na saída ps normal. As
linhas com traços na coluna PID representam as threads associadas ao processo. Nesta saída,
os processos em 1
e 2 têm apenas um encadeamento cada, mas o processo 12534 em 3 é multiencadeado, com
quatro encadeamentos.

Um olhar mais atento aos processos e utilização de recursos 205


Machine Translated by Google

Se você deseja visualizar os TIDs com ps, você pode usar uma saída personalizada para
esteira. A Listagem 8-2 mostra apenas os PIDs, TIDs e comando:

$ ps m -o pid,tid,comando
PID TIME COMANDO
3587 - festança

- 3587 -
3592 - festança

- 3592 -
12534 -
/usr/lib/xorg/Xorg -core :0
- 12534 -
- 13227 -
- 14443 -
- 14448 -

Listagem 8-2: Mostrando PIDs e TIDs com ps m


A saída de amostra nesta listagem corresponde aos encadeamentos mostrados na Listagem
8-1. Observe que os TIDs dos processos single-thread são idênticos aos PIDs; este é o fio principal.
Para o processo multithread 12534, o thread 12534 também é o thread principal.

OBSERVAÇÃO Normalmente, você não interagirá com threads individuais como faria com os processos. Você
precisa saber muito sobre como um programa multithread foi escrito para atuar em um thread por vez
e, mesmo assim, fazer isso pode não ser uma boa ideia.

Os threads podem confundir as coisas quando se trata de monitoramento de recursos


porque threads individuais em um processo multithread podem consumir recursos
simultaneamente. Por exemplo, top não mostra threads por padrão; você precisará pressionar H para
ligá-lo. Para a maioria das ferramentas de monitoramento de recursos que você está prestes a ver,
você terá que fazer um pouco de trabalho extra para ativar a exibição de thread.

8.5 Introdução ao Monitoramento de Recursos


Agora vamos discutir alguns tópicos no monitoramento de recursos, incluindo tempo de processador
(CPU), memória e E/S de disco. Examinaremos a utilização em uma escala ampla do sistema, bem
como por processo.
Muitas pessoas tocam no funcionamento interno do kernel Linux com o interesse de melhorar
o desempenho. No entanto, a maioria dos sistemas Linux funciona bem com as configurações padrão
de uma distribuição, e você pode passar dias tentando ajustar o desempenho de sua máquina sem
resultados significativos, especialmente se não souber o que procurar. Então, em vez de pensar em
desempenho enquanto você experimenta as ferramentas deste capítulo, pense em ver o kernel em
ação enquanto ele divide os recursos entre os processos.

206 Capítulo 8
Machine Translated by Google

8.5.1 Medindo o Tempo de CPU

Para monitorar um ou mais processos específicos ao longo do tempo, use a opção -p para
o início, com esta sintaxe:

$ top -p pid1 [-p pid2 ...]

Para descobrir quanto tempo de CPU um comando usa durante sua vida útil, use
time. Infelizmente, há alguma confusão aqui, porque a maioria dos shells tem um comando
de tempo embutido que não fornece estatísticas extensas, e há um utilitário de sistema em /
usr/bin/time. Você provavelmente encontrará o bash
shell embutido primeiro, então tente executar o tempo com o comando ls :

$ hora ls

Depois que ls terminar, time deve imprimir a saída como a seguir:

real 0m0,442s
do utilizador 0m0.052s
sistema 0m0.091s

O tempo do usuário (usuário) é o número de segundos que a CPU gastou executando


o próprio código do programa. Alguns comandos são executados tão rapidamente que o tempo
de CPU é próximo de 0. O tempo do sistema (sys ou system) é quanto tempo o kernel gasta
fazendo o trabalho do processo (por exemplo, lendo arquivos e diretórios).
Finalmente, o tempo real (real) (também chamado de tempo decorrido) é o tempo total
gasto para executar o processo do início ao fim, incluindo o tempo que a CPU gastou
realizando outras tarefas. Esse número normalmente não é muito útil para medição de
desempenho, mas subtrair o tempo do usuário e do sistema do tempo decorrido pode dar uma
ideia geral de quanto tempo um processo gasta esperando pelo sistema e recursos externos.
Por exemplo, o tempo gasto esperando que um servidor de rede responda a uma solicitação
aparecerá no tempo decorrido, mas não no tempo do usuário ou do sistema.

8.5.2 Ajustando as Prioridades do Processo

Você pode alterar a maneira como o kernel agenda um processo para dar ao processo
mais ou menos tempo de CPU do que outros processos. O kernel executa cada processo
de acordo com sua prioridade de agendamento, que é um número entre –20 e 20, sendo –
20 a prioridade principal. (Sim, isso pode ser confuso.)

O comando ps -l lista a prioridade atual de um processo, mas é um pouco


mais fácil ver as prioridades em ação com o comando top , como mostrado aqui:

$ topo
Tarefas: 244 no total, 2 em execução, 242 dormindo, 0 paradas, 0 zumbis
CPU(s): 31,7%us, 2,8%sy, 0,0%ni, 65,4%id, 0,2%wa, 0,0%hi, 0,0%si, 0,0%st
Memória: 6137216k total, 5583560k usado, 553656k livre, 72008k buffers
Troca: total de 4135932k, 694192k usado, 3441740k livre, 767640k em cache

Um olhar mais atento aos processos e utilização de recursos 207


Machine Translated by Google

USUÁRIO 0 1280m 763m 32m S 58 12.7 213:00.65 navegação-cromo


PID 28883 bri 20 0 210m 43m 28m R 44 0,7 14292:35 Xorg 20 0 4138 2001m
1175 root 289m S 0,7 14292:35 Xorg 20 0 4138 2001m 289m 20 0 881M
4022 bri 359M 32M S 20 0 152M 10M 7064
29 3,4
S 20
3640:13
0 312Mchromium-browse
37M 14M S 20 02
4029 bri 321M 105M 18M S 20 0 331M 99M3,5 32:50,86
21M S 20chromium-browse
0 232M 60M 13m2S
3971 bri 20 0 6,0 563:06,88 chromium-browse 1
5378 bri 0,2 24:30.21 xfce4-session 0 0,6
3821 bri 29:25.57 soffice.bin 0 1,8 34:55.01
4117 bri chromium-browse 121:44,19 cromo-
4138 bri navegação 0 1,0 37:33,78 cromo-
4274 bri navegação 0 14,1 29:59.27 cromo-
4267 bri navegação 0 0,7 109:55,65 xfce4-
2327 bri panel

Nesta saída superior , a coluna PR (prioridade) lista a prioridade de


agendamento atual do kernel para o processo. Quanto maior o número, menor a
probabilidade de o kernel agendar o processo se outros precisarem de tempo de CPU.
A prioridade de agendamento por si só não determina a decisão do kernel de dar tempo
de CPU a um processo, entretanto, o kernel também pode alterar a prioridade durante a
execução do programa de acordo com a quantidade de tempo de CPU que o processo consome.
Ao lado da coluna de prioridade está a coluna NI (valor agradável) , que dá uma
dica para o escalonador do kernel. É com isso que você se importa ao tentar influenciar
a decisão do kernel. O kernel adiciona o valor nice à prioridade atual para determinar o
próximo intervalo de tempo para o processo. Quando você define o valor de nice mais
alto, você está sendo “mais gentil” com outros processos porque o kernel os prioriza.

Por padrão, o valor nice é 0. Agora, digamos que você esteja executando uma
grande computação em segundo plano que não deseja atrapalhar sua sessão interativa.
Para fazer com que esse processo fique em segundo plano para outros processos e
execute apenas quando as outras tarefas não tiverem nada para fazer, você pode
alterar o valor nice para 20 com o comando renice (onde pid é o ID do processo que
você deseja alterar ):

$ renice 20 pid

Se você for o superusuário, você pode definir o valor nice para um número negativo,
mas fazer isso é quase sempre uma má ideia porque os processos do sistema podem
não ter tempo de CPU suficiente. Na verdade, você provavelmente não precisará alterar
muito os valores agradáveis porque muitos sistemas Linux têm apenas um único
usuário, e esse usuário não executa muita computação real. (O valor agradável era
muito mais importante quando havia muitos usuários em uma única máquina.)

8.5.3 Medindo o desempenho da CPU com médias de carga


O desempenho geral da CPU é uma das métricas mais fáceis de medir. A média de
carga é o número médio de processos atualmente prontos para execução. Ou seja, é
uma estimativa do número de processos que são capazes de usar a CPU em um
determinado momento – isso inclui processos que estão em execução e aqueles que
estão esperando uma chance de usar a CPU. Ao pensar em uma média de carga, lembre-
se de que a maioria dos processos em seu sistema geralmente está aguardando entrada

208 Capítulo 8
Machine Translated by Google

(do teclado, mouse ou rede, por exemplo), o que significa que eles não estão prontos para serem
executados e não devem contribuir com nada para a média de carga. Apenas os processos que
estão realmente fazendo alguma coisa afetam a média de carga.

Como usar o tempo de atividade

O comando uptime informa três médias de carga, além de quanto tempo o kernel está em
execução:

$ tempo de atividade

... até 91 dias, ... carga média: 0,08, 0,03, 0,01

Os três números em negrito são as médias de carga dos últimos 1 minuto, 5 minutos e 15
minutos, respectivamente. Como você pode ver, este sistema não está muito ocupado: uma média
de apenas 0,01 processos foram executados em todos os processadores nos últimos 15 minutos.
Em outras palavras, se você tivesse apenas um processador, ele estava executando aplicativos de
espaço do usuário por apenas 1% dos últimos 15 minutos.

Tradicionalmente, a maioria dos sistemas de desktop exibe uma média de carga de


cerca de 0 quando você está fazendo qualquer coisa, exceto compilar um programa ou jogar um
jogo. Uma carga média de 0 geralmente é um bom sinal, porque significa que seu processador não
está sendo desafiado e você está economizando energia.
No entanto, os componentes da interface do usuário em sistemas desktop atuais tendem a
ocupam mais CPU do que no passado. Em particular, certos sites (e especialmente seus
anúncios) fazem com que os navegadores se tornem consumidores de recursos.

Se uma média de carga subir para cerca de 1, um único processo provavelmente está usando
a CPU quase o tempo todo. Para identificar esse processo, use o comando superior ; o
processo geralmente subirá para o topo da tela.
A maioria dos sistemas modernos tem mais de um núcleo de processador ou CPU, então
vários processos podem ser executados simultaneamente. Se você tiver dois núcleos, uma
média de carga de 1 significa que apenas um dos núcleos provavelmente está ativo em um
determinado momento e uma média de carga de 2 significa que ambos os núcleos têm apenas o
suficiente para fazer o tempo todo.

Gerenciando Cargas

Altas Uma média de carga alta não significa necessariamente que seu sistema está com
problemas. Um sistema com memória e recursos de E/S suficientes pode lidar facilmente com
muitos processos em execução. Se sua média de carga for alta e seu sistema ainda responder bem,
não entre em pânico; o sistema tem muitos processos compartilhando a CPU. Os processos
precisam competir uns com os outros pelo tempo do processador e, como resultado, levarão mais
tempo para realizar seus cálculos do que se cada um deles tivesse permissão para usar a CPU o
tempo todo. Outro caso em que uma média de carga alta pode ser normal é com um servidor da
Web ou de computação, onde os processos podem iniciar e terminar tão rapidamente que o
mecanismo de medição da média de carga não pode funcionar de forma eficaz.

No entanto, se a média de carga for muito alta e você sentir que o sistema está ficando
lento, você pode estar tendo problemas de desempenho de memória

Um olhar mais atento aos processos e utilização de recursos 209


Machine Translated by Google

problemas. Quando o sistema está com pouca memória, o kernel pode começar a thrash, ou trocar
rapidamente a memória de e para o disco. Quando isso acontecer, muitos processos ficarão prontos
para execução, mas sua memória poderá não estar disponível, de modo que permanecerão no estado
pronto para execução (contribuindo para a média de carga) por muito mais tempo do que normalmente.
A seguir, veremos por que isso pode acontecer explorando a memória com mais detalhes.

8.5.4 Monitorando o Status da Memória


Uma das maneiras mais simples de verificar o status da memória do seu sistema como um todo é
executar o comando free ou visualizar /proc/ meminfo para ver quanta memória real está sendo usada
para caches e buffers. Como acabamos de mencionar, problemas de desempenho podem surgir
devido à falta de memória. Se não estiver sendo usada muita memória cache/buffer (e o restante da
memória real for usada), talvez você precise de mais memória. No entanto, é muito fácil culpar a falta
de memória por cada problema de desempenho em sua máquina.

Como funciona a memória

Conforme explicado no Capítulo 1, a CPU possui uma unidade de gerenciamento de memória (MMU)
para adicionar flexibilidade no acesso à memória. O kernel auxilia a MMU dividindo a memória usada
pelos processos em pedaços menores chamados páginas.
O kernel mantém uma estrutura de dados, chamada tabela de páginas, que mapeia os endereços
de páginas virtuais de um processo para endereços de páginas reais na memória. À medida que um
processo acessa a memória, a MMU traduz os endereços virtuais usados pelo processo em endereços
reais com base na tabela de páginas do kernel.
Na verdade, um processo de usuário não precisa que todas as suas páginas de memória
estejam imediatamente disponíveis para executar. O kernel geralmente carrega e aloca páginas
conforme um processo precisa delas; esse sistema é conhecido como paginação sob demanda ou
apenas paginação sob demanda. Para ver como isso funciona, considere como um programa é iniciado
e executado como um novo processo:

1. O kernel carrega o início do código de instrução do programa nas páginas de memória.

2. O kernel pode alocar algumas páginas de memória de trabalho para o novo processo.

3. À medida que o processo é executado, ele pode chegar a um ponto em que a próxima instrução em
seu código não esteja em nenhuma das páginas que o kernel carregou inicialmente. Nesse
ponto, o kernel assume o controle, carrega a página necessária na memória e permite que o
programa retome a execução.

4. Da mesma forma, se o programa requer mais memória de trabalho do que foi alocado
inicialmente, o kernel lida com isso encontrando páginas livres (ou abrindo espaço) e
atribuindo-as ao processo.

Você pode obter o tamanho da página de um sistema observando a configuração do kernel:

$ getconf PAGE_SIZE
4096

Esse número está em bytes e 4k é típico para a maioria dos sistemas Linux.

210 Capítulo 8
Machine Translated by Google

O kernel não mapeia arbitrariamente páginas de memória real para endereços virtuais; ou seja, ele
não coloca todas as páginas disponíveis em um grande pool e aloca a partir daí. A memória real tem muitas
divisões que dependem de limitações de hardware, otimização do kernel de páginas contíguas e outros fatores.
No entanto, você não deve se preocupar com nada disso quando estiver apenas começando.

Falhas de página

Se uma página de memória não estiver pronta quando um processo quiser usá-la, o processo acionará uma
falha de página. No caso de uma falha de página, o kernel assume o controle da CPU do processo para preparar
a página. Existem dois tipos de falhas de página: menores e maiores.

Falhas de página menores


Uma falha de página secundária ocorre quando a página desejada está na memória principal, mas
a MMU não sabe onde ela está. Isso pode acontecer quando o processo solicita mais memória ou
quando a MMU não tem espaço suficiente para armazenar todos os locais de página de um processo
(a tabela de mapeamento interna da MMU geralmente é bem pequena). Nesse caso, o kernel informa
a MMU sobre a página e permite que o processo continue. Falhas de página menores não são motivo
de preocupação, e muitas ocorrem durante a execução de um processo.

Principais falhas de página


Uma falha de página principal ocorre quando a página de memória desejada não está na memória
principal, o que significa que o kernel deve carregá-la do disco ou de algum outro mecanismo de
armazenamento lento. Muitas falhas de página importantes atrapalharão o sistema, porque o kernel
deve fazer uma quantidade substancial de trabalho para fornecer as páginas, roubando a chance dos
processos normais
para correr.

Algumas falhas de página importantes são inevitáveis, como aquelas que ocorrem quando você carrega o
código do disco ao executar um programa pela primeira vez.
Os maiores problemas acontecem quando você começa a ficar sem memória, o que força o kernel a
começar a trocar páginas de memória de trabalho para o disco para dar espaço para novas páginas e
pode levar a thrashing.

Você pode detalhar as falhas de página para processos individuais com os comandos ps, top e time .
Você precisará usar a versão do sistema de tempo
(/usr/bin/time) em vez do shell embutido. O seguinte mostra um exemplo simples de
como o comando time exibe falhas de página (a saída do comando cal
comando é irrelevante, então estamos descartando-o redirecionando-o para /dev/ null):

$ /usr/bin/time cal > /dev/null


0.00usuário 0.00sistema 0:00.06decorrido 0%CPU (0avgtext+0avgdata 3328maxresident)k
648 entradas + 0 saídas (2 maiores + 254 menores) falhas de página 0 trocas

Um olhar mais atento aos processos e utilização de recursos 211

Você também pode gostar