Escolar Documentos
Profissional Documentos
Cultura Documentos
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
“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
COMO LINUX
FUNCIONA
3ª edição
O que é superusuário
Deveria saber
São Francisco
Machine Translated by Google
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.
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
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).
BREVE CONTEÚDO
Prefácio. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxi
Capítulo 3: Dispositivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Capítulo 7: Configuração do sistema: registro, hora do sistema, trabalhos em lote e usuários . . . . . . . . 167
Capítulo 14: Uma breve pesquisa sobre a área de trabalho e impressão do Linux . . . . . . . . . . . . . . . . . . . . . 347
Í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
2
COMANDOS BÁSICOS E HIERARQUIA DE DIRETÓRIOS 11
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
5
COMO AS BOTAS DO LINUX KERNEL 117
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
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
xiii
Conteúdo em detalhes
Machine Translated by Google
9
ENTENDENDO SUA REDE E SUA CONFIGURAÇÃO 223
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
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
. .. .. .. .. .. . .. .. .. .. .. . .. .. ..
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
15
FERRAMENTAS DE DESENVOLVIMENTO 363
16
INTRODUÇÃO À COMPILAÇÃO DE SOFTWARE
DO CÓDIGO DE FONTE C 385
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.
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.
$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
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.
Prefácio xxiii
Machine Translated by Google
xxiv Prefácio
Machine Translated by Google
1
A GRANDE IMAGEM
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.
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 do usuário
Kernel Linux
Drivers de dispositivo
Hardware
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.
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.
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. 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.
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.
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.
• 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.
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.
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.
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.
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,
Processos do usuário
8 Capítulo 1
Machine Translated by Google
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.
10 Capítulo 1
Machine Translated by Google
2
COMANDOS BÁSICOSAND
HIERARQUIA DE DIRETÓRIO
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).
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.
12 Capítulo 2
Machine Translated by Google
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.
$ cat /etc/passwd
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:
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.
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.
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.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:
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:
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.
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.
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ê
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.
$ eco *
• 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.
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.
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.
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:
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:
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:
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
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.
É 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:
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á.
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.
2.5.8 classificar
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.
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á
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.
$ COISA = blá
$ exportação COISAS
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
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
$ 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.
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.)
*
estrela, asterisco Expressão regular, caractere glob
. ponto Diretório atual, delimitador de arquivo/nome de host
! bang Negação, histórico de comando
24 Capítulo 2
Machine Translated by Google
NOTA Você verá frequentemente caracteres de controle marcados com um acento circunflexo; por exemplo, ^C para CTRL-C.
Teclas Ação
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.
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.
$ man ls
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--
OBSERVAÇÃO Se você tiver alguma dúvida sobre os comandos descritos nas seções anteriores,
poderá encontrar as respostas usando o comando man .
Seção Descrição
1 Comandos do usuário
6 Jogos
$ man 5 senha
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.
Para enviar a saída do comando para um arquivo em vez do terminal, use o >
caractere de redirecionamento:
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.)
$ 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.
$ 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:
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 /dsafsda
ls: não é possível acessar /dsafsda: nenhum arquivo ou diretório
•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.
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:
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.)
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
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.
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.
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.
Isso geralmente acontece quando você tenta matar um processo que não é seu.
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
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.
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
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.
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 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.
$ 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 :
Um processo parado ainda está na memória, pronto para continuar de onde parou.
Use o sinal CONT para continuar executando o processo novamente:
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.
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 .
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:
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.
Permissões do usuário
Permissões de grupo
Modelo Outras permissões
-r-r--r--
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.)
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”.
36 Capítulo 2
Machine Translated by Google
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:
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.
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.
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:
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.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:
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 (-).
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.
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.)
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.
$ gunzip arquivo.tar.gz
$ tar arquivo xvf.tar
40 Capítulo 2
Machine Translated by Google
2.18.4 zcat
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:
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).
/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.)
/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.
• Você não tem registro dos usuários que realizaram alterações no sistema
comandos.
•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:
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:
OBSERVAÇÃO Use o comando visudo para editar / etc/sudoers. Este comando verifica erros de sintaxe de arquivo
depois que você salva o arquivo.
$ 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.)
46 Capítulo 2
Machine Translated by Google
3
DISPOSITIVOS
É 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.
É 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:
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
Bloquear dispositivo
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.
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.
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:
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:
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.
skip=num Pule os primeiros blocos num no arquivo de entrada ou fluxo e não os copie
para a saída.
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.
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
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.
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.
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.
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
Dispositivos 55
Machine Translated by Google
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.
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
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.
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.
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. O udevd analisa suas regras, filtra e atualiza o uevent com base nessas regras e executa
ações ou define mais atributos de acordo.
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
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ê:
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"
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:
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:
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:
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:
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--
$ udevadm monitor
A saída (por exemplo, quando você insere um dispositivo de mídia flash) se parece com
este exemplo abreviado:
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.
Computador
Barramento SCSI
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
$ 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
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
Subsistema SCSI
Subsistema USB
Subsistema USB
Hardware
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.
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.
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.)
$ 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
66 Capítulo 3
Machine Translated by Google
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.
Kernel Linux
Subsistema SCSI
Dispositivos 67
Machine Translated by Google
Machine Translated by Google
4
DISCOS E SISTEMAS DE ARQUIVOS
Tabela de partição
Partição Partição
Dados do arquivo
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
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.
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)
Sistema de arquivo
Dispositivo de armazenamento
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.
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:
72 Capítulo 4
Machine Translated by Google
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.
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.
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.
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 :
Depois, existem alguns dispositivos que parecem ser partições, mas são chamados
de discos:
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.
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.
•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:
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.
•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 /sys/ block/ device/ para interfaces de sistema de partição alteradas ou /dev para
dispositivos de partição alterados.
• 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)
• 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:
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:
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:
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 :
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.
Cilindro
Cabeça
Fuso
Braço
Prato
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.
NOTA A palavra setor é confusa, porque os programas de particionamento do Linux podem usá-la para
significar um valor diferente.
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.
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
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
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.
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.
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.
$ 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.
$ 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 .
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:
Por exemplo, para montar o Fourth Extended filesystem encontrado no dispositivo /dev/ sdf2 em /
home/ extra, use este comando:
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:
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.
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:
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.
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.
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.
-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.
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:
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.
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.
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.
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.
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
O dispositivo ou UUID A maioria dos sistemas Linux atuais não usa mais o dispositivo em /etc/
fstab, preferindo o UUID.
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).
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:
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.
$ 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
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.
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.
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:
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.)
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:
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
•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”.
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.
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
Para usar uma partição de disco inteira como swap, siga estas etapas:
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:
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.
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:
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.
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.
Grupo de volumes
96 Capítulo 4
Machine Translated by Google
•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.
# vgs
VG #PV #LV #SN Attr VSize VFree
free-vg 1 2 0 wz - n- <10,00g 36,00m
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:
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.
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
# 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
Segmentos 1
Alocação você herda
Setores de leitura antecipada auto
- atualmente configurados para 256
Bloquear dispositivo 253:0
$ 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.
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
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
#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
•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.
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.
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:
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.
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:
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 :
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
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.
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:
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
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.
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:
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.
# lvremove myvg/mylv2
Você realmente deseja remover e DESCARTAR o volume lógico ativo myvg/mylv2? [s/n]: sim
Volume lógico:
mylv1 (20 GB)
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.
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:
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):
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:
É 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ê.
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.)
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:
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).
5. Descubra o esquema para mapear dados dos PVs para os volumes lógicos.
NOTA Se você estiver interessado na aparência do cabeçalho LVM em um PV, você pode executar um
mando como este:
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
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
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.
#tabela dmsetup
myvg-mylv1: 0 31326208 linear 8:33 2048
myvg-mylv1: 31326208 10960896 linear 8:17 2048
110 Capítulo 4
Machine Translated by Google
$ 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.
(raiz)
você_1 você_2
tabela de inodes
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"
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
Para examinar dir_1/ file_2 neste sistema de arquivos, o kernel faz o seguinte:
3. Localiza o nome dir_1 nos dados do diretório do inode 2, que aponta para o inode
número 12.
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).
$ ls -i
12 você_1 7633 você_2
É 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).
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
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.
5
COMO AS BOTAS DO LINUX KERNEL
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
118 Capítulo 5
Machine Translated by Google
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.
1. Inspeção da CPU
2. Inspeção de memória
4. Descoberta de dispositivos
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.
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:
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.
$ 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
root=/dev/mapper/my-system-root
root=UUID=17f12d53-c3d7-4ab3-943e-a0a72366c9fa
120 Capítulo 5
Machine Translated by Google
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.
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:
•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
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.
•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).
122 Capítulo 5
Machine Translated by Google
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.
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.
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.
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.
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.
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)
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
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)/
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.
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:
NOTA Muitas variáveis como $font originam-se de uma chamada load_env perto do início do
grub.cfg.
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.
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
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
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.
# 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.
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).
•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.
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
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:
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.
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:
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.
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.
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
}
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
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.
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”.
Vamos encerrar nossa discussão sobre o GRUB observando como ele funciona:
9. O GRUB executa um comando de inicialização para carregar e executar o kernel conforme especificado
pelo comando linux da configuração.
• 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.
6
COMO COMEÇA O ESPAÇO DO USUÁRIO
1. calor
• 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.
•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.
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.
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:
OBSERVAÇÃO Você pode encontrar uma lista completa de tipos de unidade na página de manual do systemd(1).
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
sysinit.target
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.
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.
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.
[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.
Especificadores
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.
$ systemctl lista-unidades
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 .
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
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:
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:
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.
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.
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:
[Unidade]
Descrição=teste 1
[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:
· 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:
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.
2. Se a unidade tiver uma seção [Install] , desative a unidade para remover quaisquer links simbólicos
criados pelo sistema de dependência:
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.
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.
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.
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:
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.
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.
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.
Quando você usa o pedido, o systemd espera até que uma unidade tenha um status ativo
antes de ativar suas unidades dependentes.
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).
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:
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).
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:
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.
1. Você cria uma unidade do sistema (chame-a de Unidade A) para o serviço do sistema que
deseja fornecer.
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.
2. Quando qualquer coisa tenta acessar o recurso, o systemd bloqueia o recurso e a entrada
para o recurso é armazenada em buffer.
•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.
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 :
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:
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:
NOTA O telnet pode não ser instalado por padrão em sua distribuição.
Instâncias e transferência
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.
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
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
Unidade R
Disponível
Unidade E
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
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.
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.
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.
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:
3. A ação que o init deve tomar (nível de execução padrão para 5 no anterior
exemplo).
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
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.
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 :
158 Capítulo 6
Machine Translated by Google
Iniciar S10sysklogd
S12 início do kernel
S15netstd_init start
início S18netbase
--recorte--
S99sshd iniciar
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.
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).
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.
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.
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.
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.
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:
3. O systemd associa o nome do script a uma unidade de serviço (por exemplo, /etc/ init.d/ foo seria
foo.service).
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.
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.
# 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:
2. Se um processo não responde depois de um tempo, o init o mata, primeiro tentando um sinal
TERM.
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
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
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.
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.
CONFIGURAÇÃO DO SISTEMA :
7
EXPLORAÇÃO MADEIREIRA , SYSTEMTIME , LOTE
TRABALHOS E USUÁRIOS
• 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
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.
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
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).
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.
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
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'
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
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.
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.
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
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
$ 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.
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.
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:
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.
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).
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.
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.
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
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.
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:
•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.
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.
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.
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.
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
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.
•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.
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
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.
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.
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.)
raiz:*:0:juser
daemon:*:1:
bin:*:2:
sistema:*:3:
adm:*:4:
disco:*:6:juser,beazley
nogrupo:*:65534:
usuário:*:1000:
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 !.
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.
Nome do grupo
Senha
ID do grupo
Membros adicionais
disco:*:6:juser,beazley
Figura 7-2: Uma entrada no arquivo de grupo
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
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.
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
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).
$ 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
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:
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.
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.
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.
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) :
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.
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
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.
[Unidade]
Description=Exemplo de serviço de teste
[Serviço]
Tipo = oneshot
ExecStart=/usr/bin/logger -p local3.debug Sou um registrador
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.
•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.
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:
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 .
$ às 22h30
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.
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:
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.
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:
188 Capítulo 7
Machine Translated by Google
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.
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.
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.)
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?
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:
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.
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.
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.
192 Capítulo 7
Machine Translated by Google
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.
Tipos de função
Um aplicativo de usuário pode solicitar ao PAM que execute uma das quatro funções a
seguir:
mensagem do dia).
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 :
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):
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
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.
Argumentos do módulo
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).
•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
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.
198 Capítulo 7
Machine Translated by Google
ACLOSERLOOKATPROCESSE S
8
E UTILIZAÇÃO DE RECURSOS
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.
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:
200 Capítulo 8
Machine Translated by Google
#lsof _
--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--
PID O ID do 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).
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.
• 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.
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
$ 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.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:
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:
--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
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
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:
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:
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.
204 Capítulo 8
Machine Translated by Google
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.
$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 -
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.
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 -
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.
206 Capítulo 8
Machine Translated by Google
Para monitorar um ou mais processos específicos ao longo do tempo, use a opção -p para
o início, com esta sintaxe:
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
real 0m0,442s
do utilizador 0m0.052s
sistema 0m0.091s
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.)
$ 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
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.)
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.
O comando uptime informa três médias de carga, além de quanto tempo o kernel está em
execução:
$ tempo de atividade
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.
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
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.
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:
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.
$ 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.
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):