Samuel Henrique Bucke Brito
Novatec
© Novatec Editora Ltda. 2017. Todos os direitos reservados e protegidos pela Lei 9.610 de 19/02/1998. É proibida a reprodução desta obra, mesmo parcial, por qualquer processo, sem prévia autorização, por escrito, do autor e da Editora. Editor: Rubens Prates MP20170926 Revisão gramatical: Patrizia Zagni Editoração eletrônica: Carolina Kuwabata Capa: Carolina Kuwabata ISBN: 978-85-7522-619-3 Histórico de impressões: Setembro/2017
Primeira edição
Novatec Editora Ltda. Rua Luís Antônio dos Santos 110 02460-000 – São Paulo, SP – Brasil Tel.: +55 11 2959-6529 Email: novatec@novatec.com.br Site: www.novatec.com.br Twitter: twitter.com/novateceditora Facebook: facebook.com/novatec LinkedIn: linkedin.com/in/novatec
capítulo 1
Introdução
Em 25 de agosto de 1991, Linus Benedict Torvalds, com 21 anos na época, anunciou publicamente a versão 0.01 do kernel Linux. Ele era estudante de Ciência da Computação na Universidade de Helsinki (Finlândia) quando escreveu o kernel do Linux (em linguagem C) sem maiores pretensões, segundo ele mesmo. Logo no ano seguinte a seu desenvolvimento (1992), o kernel do Linux foi licenciado sob a GNU GPL, uma licença pública geral para software livre que foi idealizada por Richard Stallman em 1989. O desenvolvimento do kernel Linux nunca parou desde seu lançamento e, ao longo de todos esses anos, recebeu a colaboração de uma comunidade que atualmente é composta de milhares de desenvolvedores de todos os lugares do mundo, já tendo passado pelo lançamento de quatro versões principais em 1994 (v1.0), 1996 (v2.0), 2001 (v3.0) e 2015 (v4.0). É importante entender que o Linux não é um sistema operacional propriamente dito, mas uma de suas partes mais importantes, que é o núcleo denominado kernel, elemento central responsável pelo interfaceamento entre o hardware no baixo nível com as aplicações no alto nível. Um kernel sozinho não tem muita utilidade sem os programas que são de interesse e uso cotidiano dos usuários, motivo pelo qual surgiram centenas de distribuições Linux ao longo dos anos. Atualmente, duas das principais distribuições Linux empregadas em servidores são o Debian GNU/Linux e o Ubuntu Server, motivo pelo qual foram escolhidas como temática deste livro. Ambas são muito similares do ponto de vista operacional, já que o Ubuntu Server é uma derivação do Debian com mais pacotes pré-instalados por padrão. O que determina a escolha de uma dessas duas distribuições é a política de suporte comercial e a filosofia por trás de cada uma delas, que são muito diferentes. Por isso, faço um breve descritivo dessas características na sequência.
15
16
Serviços de Redes em Servidores Linux Observação: é justo registrar que o Debian GNU/Linux e o Ubuntu Server não são as únicas distribuições no mercado de servidores Linux, obviamente. Outras distribuições frequentemente instaladas em servidores e que merecem destaque são Red Hat Enterprise Linux (RHEL), CentOS, SUSE Linux Enterprise Server (SLES), Oracle Linux e Slackware.
1.1 Debian GNU/Linux O Debian GNU/Linux (https://www.debian.org) é uma das mais tradicionais distribuições na história do Linux, cuja origem praticamente coincide com o ano em que Linus Torvalds desenvolveu seu kernel (1991). Foi em 15 de setembro de 1993 que Ian Murdock anunciou a versão 0.01 do Debian e, desde 1994, é distribuído livremente no espírito do Projeto GNU, tendo sua primeira versão estável sido lançada em 1996. O Debian GNU/Linux tem esse nome porque utiliza tanto o kernel Linux como os softwares livres do sistema GNU. Até hoje, o projeto Debian é o maior exemplo de esforço coletivo de desenvolvimento de software livre na história da computação, inclusive sendo oficializado em contrato social.
Como o Debian GNU/Linux foca seus esforços na estabilidade das versões lançadas e depende exclusivamente do trabalho voluntário da comunidade envolvida na continuidade desse projeto, possui um ciclo de atualizações mais demorado do que outras distribuições que têm o suporte financeiro de uma empresa. No entanto, essa característica costuma pesar em favor dele no mercado de servidores, embora possa ser desfavorável em algumas situações. Além do zelo histórico pela estabilidade do sistema, um dos motivos pelo qual o Debian é uma das principais distribuições Linux é seu sistema de gerenciamento de pacotes, conhecido como Advanced Package Tool (APT), um front-end amigável para a ferramenta DPKG que manipula os pacotes com extensão .deb. Com mais de 51 mil pacotes de softwares pré-compilados, cada aplicação do Debian pode ser
Capítulo 1 ■ Introdução
17
facilmente instalada no sistema por meio do APT, que busca seus pacotes e suas dependências em repositórios cuidadosamente inspecionados e constantemente verificados pelo trabalho voluntário da sua reconhecida comunidade técnica.
1.2 Ubuntu Server O Ubuntu (https://www.ubuntu.com) é uma distribuição de Linux baseada no Debian que foi originalmente lançada pela Canonical Ltd em 2004, uma empresa fundada pelo milionário sul-africano Mark Shuttleworth e que trabalha na promoção do software livre. A Canonical é proprietária da logomarca do Ubuntu e responsável por sua distribuição com o compromisso público de mantê-lo livre e gratuito para sempre.
Em 2014, registrou mais de 22 milhões de usuários da sua versão desktop, sendo atualmente responsável por praticamente toda a fatia de usuários de Linux no desktop em conjunto com a base de usuários do Linux Mint (uma derivação do Ubuntu). Com o suporte de uma empresa com fins lucrativos, o Ubuntu tem uma política de lançamento de novas versões a cada seis meses que é rigorosamente cumprida e dá nome às suas versões no formato AA.MM, ou seja, é fácil identificar que o Ubuntu Server 17.04 foi lançado em abril (MM = 04) de 2017 (AA = 17). Por outro lado, essa mesma política respeitável e agressiva de lançamento semestral de novas atualizações também acaba impactando negativamente na estabilidade do sistema e no aumento do número de registros de bugs. Para contornar esse problema, a cada dois anos é lançada uma versão LTS com suporte de longo prazo que garante atualizações básicas e de segurança pelo período de cinco anos, um diferencial relevante que contribuiu para o crescimento da sua popularidade no mercado de servidores. Além disso, há de se reconhecer que nos últimos anos o Ubuntu Server tem avançado bastante no mercado de servidores em razão de seu suporte de infraestrutura como serviço (IaaS), sendo amplamente suportado pelos grandes provedores de soluções de computação em nuvem. O modelo de negócios provido pela Canonical que oferece suporte técnico especializado a seu produto em troca de pagamento, caso haja interesse, pesa favoravelmente na adoção do Ubuntu Server em algumas
18
Serviços de Redes em Servidores Linux
situações. É comum que grandes empresas tenham políticas de segurança da informação que requeiram contratos com terceiros que garantam a operação ininterrupta dos seus sistemas e assumam a responsabilidade em caso de incidentes envolvendo o software executado em seus servidores. Nesses casos, o Debian GNU/Linux não é uma opção aceitável porque se depara com a política de segurança da empresa, de forma que o Ubuntu Server acaba sendo a opção natural ao lado do Red Hat Enterprise Linux (RHEL) ou do SUSE Linux Enterprise Server (SLES). A principal diferença entre os modelos de negócios da Canonical e da Red Hat é que o Ubuntu Server é gratuito na sua integridade e pode ser colocado em operação sem nenhuma contratação de suporte comercial da Canonical, enquanto no RHEL o pagamento é obrigatório porque o sistema só entra em operação se sua licença estiver ativada.
1.3 Revisão de comandos básicos Este livro é um guia para administradores de servidores Debian GNU/Linux e Ubuntu Server que têm como foco a manutenção e operação dos principais serviços de redes de computadores, por isso seu objetivo não é ensinar os princípios básicos de operação do sistema operacional. Ao contrário, estou partindo do princípio de que o leitor já está familiarizado com essa operação básica do Linux, que inclui tópicos relacionados aos comandos exibidos no terminal 1.1. Terminal 1.1 – Revisão de comandos básicos sysadmin@Linux:~$ mkdir teste sysadmin@Linux:~$ touch ./teste/arquivo1.txt ./teste/arquivo2.txt sysadmin@Linux:~$ cd teste sysadmin@Linux:~/teste$ ls -l total 0 -rw-rw-r—- 1 sysadmin sysadmin 0 Mai 11 14:53 arquivo1.txt -rw-rw-r—- 1 sysadmin sysadmin 0 Mai 11 14:53 arquivo2.txt sysadmin@Linux:~/teste$ rm arquivo1.txt sysadmin@Linux:~/teste$ ls -l total 0 -rw-rw-r—- 1 sysadmin sysadmin 0 Mai 11 14:53 arquivo2.txt sysadmin@Linux:~/teste$ cd .. sysadmin@Linux:~$ rm -rf ./teste sysadmin@Linux:~$ nano script.sh
Capítulo 1 ■ Introdução
19
(...) Executa o Editor de Texto NANO (...) CTRL+X p/ sair sysadmin@Linux:~$ chmod +x ./script.sh sysadmin@Linux:~$ ls -l total 0 -rwxrwxr-x 1 sysadmin sysadmin 0 Mai 11 14:53 script.sh sysadmin@Linux:~$ ./script.sh (...) Executa o Script
No restante deste capítulo, pode ser encontrada uma revisão “relâmpago” da navegação na árvore de diretórios do sistema, da manipulação de arquivos e diretórios, da definição de permissões em arquivos e diretórios e da possibilidade de execução de comandos sequenciais e encadeados.
1.3.1 Estrutura de diretórios do Linux O sistema de arquivos do Linux foi concebido com base nos mesmos princípios do seu antecessor Unix, de forma que cada disco físico ou partição lógica devem ser associados com um ponto de montagem que nada mais é do que um diretório com seus respectivos subdiretórios. Dessa forma, a figura dos discos físicos e das partições lógicas fica invisível para os usuários que simplesmente enxergam uma abstração com a visão lógica da árvore de diretórios do Linux. Observação: obviamente, os administradores de sistemas Linux têm uma série de ferramentas à disposição para visualizar os discos físicos e as partições lógicas disponíveis no sistema, incluindo seus pontos de montagens (por exemplo, por meio do comando fdisk ou da tabela de partições que fica localizada em /etc/fstab e é utilizada pelo kernel durante o processo de boot). A propósito, a definição prévia desses pontos de montagens é uma das tarefas básicas que todo administrador deve realizar durante o processo inicial de instalação do Linux em servidores.
Existe um padrão seguido pela comunidade Linux que orienta como os diretórios básicos do sistema de arquivos devem ser nomeados e para que fins específicos devem ser utilizados denominado Filesystem Hierarchy Standard (FHS). A proposta do padrão FHS não é engessar os administradores de sistemas que continuam tendo liberdade para organizar seus diretórios locais, mas tornar coerente para desenvolvedores e administradores a localização de arquivos na estrutura da árvore de diretórios do Linux.
20
Serviços de Redes em Servidores Linux
A árvore de diretórios do Linux tem um ponto de montagem principal denominado raiz (representado por /) a que todos os demais diretórios estão vinculados na condição de subdiretórios. Esse diretório raiz deve conter os arquivos principais para viabilizar o boot do sistema (kernel Linux) e sua recuperação em caso de desastres. A recomendação é que o diretório raiz seja enxuto, com a menor quantidade possível de arquivos e subdiretórios na mesma partição, de modo que os demais subdiretórios derivados dele sejam pontos de montagens vinculados a outras partições com mais espaço. Observe que se trata de uma importante recomendação, mas não é uma exigência, o que significa que o sistema funcionará normalmente caso seja instalado com um único ponto de montagem vinculado à raiz. Ainda que não seja uma exigência, é fortemente recomendado que pelo menos as partições /home (pastas dos usuários) e /var (arquivos de log do sistema) tenham seus próprios pontos de montagem vinculados a outras partições. Não é uma boa ideia misturar arquivos de usuários na mesma partição em que existem arquivos essenciais para a operação do sistema. A mesma recomendação vale para os arquivos de logs que ao longo do tempo demandarão bastante espaço em disco a ponto de comprometer o desempenho do sistema ou até mesmo travá-lo se não houver um mecanismo de monitoramento com cota que limite o consumo de dados. A figura 1.1 ilustra a disposição espacial dessa estrutura em árvore do Linux com alguns dos seus diretórios e subdiretórios mais comuns. Repare que essa é apenas uma visão lógica do todo (abstração) que não diz nada sobre como esses diretórios estão associados a discos físicos ou partições lógicas.
Figura 1.1 – Visão lógica da estrutura da árvore de diretórios no Linux.
Capítulo 1 ■ Introdução
21
A tabela 1.1 relaciona os diretórios que devem existir a partir da raiz do Linux (“/”) com uma breve descrição do seu conteúdo, segundo recomendações do padrão FHS. Tabela 1.1 – Estrutura de diretórios no Linux (padrão FHS) Diretório
Descrição
/bin
Binários essenciais de programas/comandos
/boot
Arquivos estáticos do carregador de boot
/dev
Arquivos que representam dispositivos físicos
/etc
Arquivos de configuração do sistema
/home
Pastas dos usuários
/lib
Módulos do kernel e bibliotecas compartilhadas
/media
Observação
Opcional
Ponto de montagem de mídias removíveis
/mnt
Ponto de montagem de sistemas de arquivos temporários
/opt
Pacotes de softwares adicionados
/proc
Informações de processos do kernel
/root
Pasta do superusuário root
/sbin
Binários essenciais do sistema
/srv
Dados providos pelo servidor
/tmp
Arquivos temporários
/usr
Hierarquia secundária
/var
Dados variáveis (logs)
Opcional
1.3.2 Navegação na árvore de diretórios A tarefa mais básica constantemente realizada no shell por intermédio da linha de comando é a simples navegação na estrutura de diretórios do Linux. O comando cd é utilizado para fazer essa navegação, permitindo que o usuário mude seu posicionamento avançando nos subdiretórios aninhados ou mesmo retorne a níveis mais altos próximos à raiz. Sem dúvida, trata-se de uma tarefa bastante simples, mas que requer algum grau de abstração do usuário para acompanhar mentalmente sua posição na estrutura de diretórios. A informação do diretório corrente em que o usuário está posicionado pode ser exibida a qualquer momento com o uso do comando pwd. No Debian GNU/Linux e no Ubuntu Server, é exibida no prompt logo após o nome do usuário e do host, no formato: root@Linux:/etc/dhcp#
22
Serviços de Redes em Servidores Linux
Existem alguns caracteres especiais que permitem agilizar o esforço de navegação. O caractere “ponto” (.) faz referência ao diretório corrente em que o usuário está posicionado, enquanto o caractere “dois pontos” (..) faz referência ao diretório um nível anterior. Outra opção comum é o caractere “tilde” (~) que faz referência ao diretório home do usuário, ou seja, para o usuário sysadmin, o símbolo ~ é equivalente a /home/sysadmin. Observação: o superusuário root é o único do sistema que tem seu diretório home localizado em /root, em vez de ficar em /home como os demais usuários do sistema. Ao contrário do que muitos pensam, essa separação não é feita por uma questão de segurança para impedir o acesso não autorizado de terceiros aos arquivos do superusuário root, já que isso seria facilmente resolvido por meio de permissões no diretório. Essa separação é importante porque caso ocorra algum problema no sistema que impeça o acesso à partição vinculada ao ponto de montagem /home, ainda será possível acessar a raiz e o superusuário terá à disposição seus arquivos pessoais, provavelmente compostos de ferramentas úteis para executar procedimentos de reparação do sistema.
O uso desses caracteres especiais permite que qualquer diretório do sistema seja referenciado por um caminho parcial denominado relativo, uma forma de simplificação do caminho completo que é denominado absoluto. A notação é absoluta sempre que um caminho é informado por completo desde sua origem na raiz (/). Por exemplo, quando utilizamos o comando ls para exibir o conteúdo de um diretório a vários níveis de distância de nossa posição corrente, procedimento observado na primeira execução desse comando no terminal 1.2. Em síntese, basta lembrar que um caminho absoluto sempre começará a partir da raiz com o caractere “/”. Terminal 1.2 – Navegação na árvore de diretórios root@Linux:/# ls -l /etc/dhcp total 28 (...) -rw-r--r-- 1 root root 1735 Jan 16 2017 dhclient.conf -rw-r--r-- 1 root root 3331 Jan 19 2017 dhcpd6.conf -rw-r--r-- 1 root root 3496 Jan 19 2017 dhcpd.conf root@Linux:/# cd etc root@Linux:/etc# ls -l ./dhcp/ total 28 (...) -rw-r--r-- 1 root root 1735 Jan 16 2017 dhclient.conf
Capítulo 1 ■ Introdução
23
-rw-r--r-- 1 root root 3331 Jan 19 2017 dhcpd6.conf -rw-r--r-- 1 root root 3496 Jan 19 2017 dhcpd.conf root@Linux:/etc# ls -l total 28 (...) -rw-r--r-- 1 root root -rw-r--r-- 1 root root -rw-r--r-- 1 root root
dhcp/
1735 Jan 16 2017 dhclient.conf 3331 Jan 19 2017 dhcpd6.conf 3496 Jan 19 2017 dhcpd.conf
A notação é relativa quando informamos apenas um caminho parcial a partir da nossa posição corrente. Por exemplo, quando utilizamos o ls para exibir apenas um subdiretório diretamente aninhado ao diretório de nossa posição corrente. Na segunda execução do comando ls (Terminal 1.2), informamos apenas um caminho relativo, por isso, antes de executar o comando, nos posicionamos em /etc, para, somente então, pedir para listar o diretório a partir da nossa posição atual, fazendo referência ao caractere ponto (.). Por padrão, o Linux sempre assume a posição corrente do usuário na execução de comandos para simplificar a navegação por caminhos relativos, permitindo que o caractere ponto (.) seja omitido, conforme observado na terceira e última execução do comando ls ainda no terminal 1.2. Em síntese, caminhos iniciados por “/” são absolutos e os demais, relativos.
1.3.3 Manipulação de arquivos e diretórios Dentre as tarefas mais básicas para lidar com a linha de comando, estão as ações de criar, exibir, copiar, mover e remover arquivos, realizadas, respectivamente, pelos comandos touch, cat, cp, mv e rm. De maneira similar, diretórios podem ser criados e removidos pelos comandos mkdir e rmdir. O comando rmdir somente funcionará se o diretório estiver vazio. Então, um “atalho” frequentemente utilizado pelos administradores para remover rapidamente um diretório com todo o seu conteúdo é o comando rm -rf <nome_diretório> (veja um exemplo no terminal 1.1). Esse comando pode ser potencialmente perigoso, principalmente se você estiver logado no sistema com o superusuário root. Acho que é um clichê dizer que muito cuidado deve ser tomado ao utilizá-lo, não é mesmo? Um arquivo também é automaticamente criado pelo sistema quando tentamos executá-lo com algum editor de textos, caso esse arquivo não exista. Os editores de textos são programas fundamentais para edição rápida dos arquivos de configuração do sistema, uma tarefa frequentemente realizada pelos administradores de
24
Serviços de Redes em Servidores Linux
servidores Linux. Existem vários editores de texto bastante populares, dos clássicos vi e vim aos mais simples de operar, como o nano e o mcedit. Os administradores mais experientes frequentemente utilizam o vi (ou o vim) por velhos hábitos, já que esse editor está nativamente presente em qualquer distribuição de Linux e pode ser a única opção em procedimentos emergenciais de reparação do sistema. Apesar disso, você deve utilizar o editor de textos que o deixe mais confortável para editar os arquivos de configuração com mais eficiência. No final das contas, o importante é o resultado do conteúdo dos arquivos que você edita, e não como você edita esses arquivos. No Debian GNU/Linux, o vi e o nano são duas opções pré-instaladas por padrão, mas o vim e o mcedit podem ser facilmente instalados a partir do APT com os comandos apt-get install vim e apt-get install mc, respectivamente. O Ubuntu Server já vem pré-instalado com o vi, vim e nano, de forma que o mcedit pode ser instalado a partir do APT pelo mesmo comando anterior. O nano é um editor de textos bastante comum na comunidade Debian. Possui uma interface simplista que contém uma barra no rodapé que traz o resumo das principais combinações de teclas que podem ser utilizadas para operá-lo, sendo as combinações mais básicas CTRL+O (salvar) e CTRL+X (sair). O mcedit é um editor tão simples quanto o nano e (também) possui uma barra no rodapé com diferentes opções associadas com números. As opções desse menu superior são acessadas pelas teclas de função dos respectivos números, com destaque para as teclas F2 (salvar) e F10 (sair). De todos esses editores, o vi é o mais complexo de aprender a operar por possuir diferentes modos de operação (navegação, edição e comando) que o administrador deve conhecer antes de utilizá-lo, caso contrário terá dificuldades em editar um arquivo. Ao executar o vi, não é possível editar o conteúdo de um arquivo porque estará em modo de navegação, aguardando a inserção das instruções relacionadas na tabela 1.2. De acordo com essas instruções, será colocado em modo de edição ou de comando. Depois de abrir o vi, a tecla i pode ser pressionada para colocá-lo em modo de edição, tornando possível digitar livremente para alterar o conteúdo do arquivo. A qualquer momento, pode ser pressionada a tecla ESC para retornar ao modo de navegação. Ao digitar dois pontos (:) no modo de navegação, o vi é colocado em modo de comando e passa a reconhecer as letras indicadas na tabela 1.3. Em modo de comando, são permitidas ações como salvar (:w) ou encerrar (:q) o aplicativo. O primeiro contato com o vi pode ser um pouco confuso porque será necessário decorar as teclas mais importantes, mas com o tempo sua operação ficará mais natural.
Capítulo 1 ■ Introdução
25
Tabela 1.2 – Resumo de teclas de navegação do vi Tecla
Ação
A
Inserir texto no final da linha
dd
Remover uma linha inteira (e colocar na memória)
i
Entrar em modo de edição na posição atual do cursor (*)
I
Inserir texto no início da linha
o
Adicionar linha abaixo do cursor atual
O
Adicionar linha acima do cursor atual
p
Colar conteúdo da memória no texto
r
Substituir um único caractere
s
Substituir texto na atual posição do cursor
u
Desfazer a última ação executada
x
Apagar um único caractere
y
Copiar um item na memória
yy
Copiar uma linha inteira na memória
Tabela 1.3 – Resumo de comandos do vi Tecla
Ação
:!
Permite executar um comando do shell
:q
Sair do aplicativo
:q!
Sair do aplicativo sem salvar as alterações
:wq
Sair do aplicativo e salvar as alterações
Outro recurso que pode ser útil é a possibilidade de criar links simbólicos (atalhos) de arquivos ou diretórios que estejam localizados em outro local do sistema por intermédio do comando ln -s. Por exemplo, o comando seguinte criará um link simbólico no diretório home do usuário sysadmin, apontando para o arquivo originalmente armazenado em /etc/dhcp/dhcpd.conf. Esse recurso é frequentemente utilizado em novas versões de programas para fins de compatibilidade quando há alteração na localização dos seus arquivos internos no sistema. ln -s /etc/dhcp/dhcpd.conf /home/sysadmin/
26
Serviços de Redes em Servidores Linux
1.3.4 Permissões em arquivos e diretórios Os sistemas do tipo Unix, inclusive o Linux, adotam um mecanismo simples e poderoso para representar os diferentes tipos de permissão sobre um arquivo. Basicamente, todo arquivo pode ter três tipos de permissões sobre si, sendo cada tipo representado por uma letra e um valor numérico: r ou 4 (22) = leitura | w ou 2 (21) = escrita | x ou 1 (20) = execução
A permissão de leitura permite que o conteúdo do arquivo seja visualizado, mas não é possível alterá-lo. A permissão de escrita permite que o arquivo seja editado, movido ou removido, mas não é possível executá-lo se for um script ou programa. A permissão de execução permite que um script ou programa seja executado. Outra característica importante é que esses três tipos de permissões podem ser aplicados sobre três objetos diferentes: usuário | grupo | outros
O usuário é o proprietário do arquivo, ou seja, o responsável por sua criação no sistema. Todo usuário criado no sistema automaticamente é membro de um grupo de mesmo nome, podendo, posteriormente, o administrador associá-lo com outros grupos. Qualquer objeto que não seja o dono do arquivo ou membro do grupo é necessariamente tratado pelo sistema como “outros”. Com base nessa lógica simples, é possível reproduzir um sistema de permissões bastante flexível que atende bem a qualquer tipo de situação. Observe novamente no terminal 1.2 que ao listarmos o conteúdo de um diretório com o comando ls -l, são exibidas informações detalhadas sobre cada um dos arquivos e subdiretórios. Logo no começo de cada linha, existem dez caracteres utilizados pelo sistema para representar seu sistema de permissões. O primeiro caractere representa a natureza do arquivo, que, basicamente, pode ser: Caractere
Descrição
-
Arquivo
d
Diretório
l
Link simbólico
b
Arquivo de dispositivo
c
Arquivo de dispositivo
p
Canal FIFO
s
Socket
Capítulo 1 ■ Introdução
27
Os próximos nove caracteres devem ser visualizados como três conjuntos de três caracteres, de forma que o primeiro conjunto equivalha ao usuário dono do arquivo, o segundo conjunto equivalha ao grupo e o terceiro conjunto equivalha aos outros, conforme ilustrado na figura 1.2. Cada conjunto de três caracteres é composto das letras r (leitura), w (escrita) e x (execução), sempre nessa sequência. A ausência de uma permissão é indicada pelo caractere traço (-) no lugar da respectiva letra. Assim, é possível representar todas as combinações possíveis de permissões envolvendo leitura, escrita e execução para todos os tipos de objetos do sistema, ou seja, usuários, grupos e outros.
Figura 1.2 – Permissão de arquivos no Linux.
O fato de cada tipo de permissão ser representado por uma letra e também por um número permite utilizar um formato numérico para fazer referência às permissões dos objetos, de forma que todas as combinações possíveis são variações de 0 a 7, conforme relacionado na tabela 1.4. Tabela 1.4 – Combinações de permissões Valor numérico
Tipo de permissão
0
---
1
--x
2
-w-
3
-wx
4
r--
5
r-x
6
rw-
7
rwx
28
Serviços de Redes em Servidores Linux
Para chegar ao número equivalente a cada combinação de letras, basta somar os valores numéricos de cada tipo de permissão. O método numérico é denominado octal porque o menor valor possível da soma das permissões de um objeto é 0 e o maior valor possível é 7, ou seja, todas as permissões são indicadas por elementos do sistema de numeração octal. Por exemplo, com base na figura 1.2, o usuário dono do arquivo tem permissão de leitura (4), de escrita (2) e de execução (1) e a combinação rwx equivale ao número 7, que é a simples soma de cada uma das permissões individuais. No mesmo exemplo, o grupo e os outros têm apenas permissão de leitura (4). Para aplicar na prática essa lógica de permissão em qualquer arquivo, basta utilizar o comando chmod, sendo possível escrevê-lo de forma mais curta com o método numérico (octal) ou mesmo por meio da representação por letras. Quando o administrador estiver confortável com o método octal, dificilmente deixará de utilizá-lo para dar preferência ao método das letras. A seguir, exemplifico a aplicação dos dois métodos para permitir que o usuário dono de um arquivo tenha permissão de leitura e escrita, que o grupo do arquivo tenha permissão de somente leitura e para que outros não tenham permissão nenhuma: root@Linux:/# chmod u=rw,g=r,o= arquivo.txt root@Linux:/# chmod 640 arquivo.txt
Na primeira representação por letras, a opção o= poderia ser omitida, já que não está recebendo nenhuma permissão de fato. Outro detalhe é que o comando chmod representado com letras não precisa sempre referenciar todos os objetos seguido do sinal de igual (=) e de todas as permissões. Pode ser que em alguma situação queiramos simplesmente dar permissão plena de execução para um arquivo qualquer, sem diferenciar os objetos usuário, grupo e outros. Por exemplo, considerando que o arquivo denominado arquivo.txt tem permissão rw-r----- (ou 640), para adicionar a permissão de execução nele, bastaria utilizar o seguinte comando: root@Linux:/# chmod +x arquivo.txt
Ao fazer isso, fique atento que o resultado será rwxr-x—x (ou 751). Ao se tratar de diretórios, a lógica dos tipos de permissão muda um pouco em relação aos arquivos, pelo fato de que o diretório é uma estrutura diferente de um arquivo isolado. O modo de executar o comando chmod é o mesmo em diretórios, mas muda o significado das letras rwx. A permissão de leitura permite que o conteúdo existente dentro de um diretório seja exibido (por intermédio do comando ls), mas, sozinha, essa permissão não
Capítulo 1 ■ Introdução
29
permite acessá-lo (com o comando cd), o que pode parecer um conceito estranho à primeira vista. A permissão de escrita permite que o conteúdo interno do diretório (arquivos e subdiretórios) seja editado, movido ou removido. A permissão de execução permite que o diretório seja acessado pelo comando cd, mas, sozinha, essa permissão não permite que seu conteúdo seja exibido (por meio do comando ls), o que novamente pode parecer estranho. O melhor jeito de ficar à vontade com essa dinâmica das permissões dos diretórios é praticá-la. Outro recurso útil é a manipulação do usuário e grupo de um determinado arquivo. No terminal 1.2, repare novamente que, ao executar o comando ls -l, existem dois nomes na sequência dos caracteres de permissão que representam, respectivamente, o usuário (dono) e o grupo do arquivo. Vamos assumir que um arquivo qualquer denominado exemplo.txt seja de propriedade do usuário root e pertença ao grupo root (root:root). Basta utilizar o comando chown para alterar o usuário e grupo do arquivo, por exemplo, para tornar o usuário sysadmin seu proprietário e vincular o arquivo ao grupo admin (sysadmin:admin): root@Linux:/# chown sysadmin:admin exemplo.txt
Por fim, o usuário/grupo de um arquivo e suas permissões não podem simplesmente ser alterados por qualquer usuário do sistema. É necessário ser proprietário do arquivo (ou o superusuário root) para fazer qualquer tipo de alteração na propriedade e nas permissões em arquivos.
1.3.5 Comandos encadeados e redirecionamento de fluxo São vários os recursos oferecidos pelo shell Linux à interface de linha de comando, até mesmo no que diz respeito à sua enorme flexibilidade para lidar com múltiplos comandos simultaneamente por um processo denominado encadeamento de comandos. O encadeamento pode ocorrer de forma sequencial ou condicional, além de ser possível redirecionar o fluxo da execução para outros comandos ou arquivos externos. Existem vários operadores lógicos e de redirecionamento que podem ser utilizados para separar múltiplos comandos e cada um desses operadores é interpretado de maneira diferente pelo shell. O encadeamento é sequencial quando a execução dos múltiplos comandos, normalmente independentes entre si, é feita pela separação de cada um por meio do caractere ponto e vírgula (;) no formato: <comando1> ; <comando2> ; <comando3>
30
Serviços de Redes em Servidores Linux
Um exemplo típico em que esse recurso pode ser útil é quando desejamos visualizar na mesma tela as configurações de apenas duas interfaces de rede de um servidor que opera como roteador de várias sub-redes diretamente conectadas nele. Essa ação poderia ser facilmente executada separadamente em duas linhas independentes, mas também poderia ser agilizada agrupando sequencialmente os dois comandos em uma única linha. Por exemplo: root@Linux:/# ifconfig eth0 ; ifconfig eth2
Observe que é possível utilizar vários comandos sequencialmente em uma mesma linha. Logo, fica fácil perceber que o comando clear poderia ser incluído no começo para limpar a tela antes de exibir as informações das interfaces eth0 e eth2: root@Linux:/# clear; ifconfig eth0; ifconfig eth2
Outra possibilidade útil de conhecer diz respeito à execução de múltiplos comandos de maneira condicional. O encadeamento condicional permite executar um comando somente se o comando anterior falhou ou mesmo se este foi executado com sucesso. Essas duas lógicas condicionais podem ser objetivamente compreendidas da seguinte maneira: a) se o comando anterior falhou, então execute o comando seguinte; b) se o comando anterior foi um sucesso, então execute o comando seguinte. No primeiro caso, ou seja, para executar o comando seguinte somente se o comando anterior falhar, essa instrução poderá ser passada ao shell utilizando o operador lógico || (OU) na separação dos comandos individuais. A seguir, trago um exemplo simples de sua aplicação em que a mensagem de erro somente será exibida no terminal se o comando anterior falhar, ou seja, se não for possível remover o diretório /root/backup, então o alerta (echo) será disparado no terminal: rm -rf /root/backup || echo "ERRO AO REMOVER ARQUIVO!"
No segundo caso, ou seja, para executar o comando seguinte somente se o comando anterior foi um sucesso, essa instrução poderá ser passada ao shell utilizando o operador lógico && (E) na separação dos comandos individuais. Na sequência, cito outro exemplo hipotético de sua aplicação em que o diretório /root/backup somente é removido se antes seu conteúdo foi comprimido em outro arquivo denominado backup.tar.gz. Se o procedimento de compressão do backup falhar, então o diretório original não será removido do sistema: tar -cvzf backup.tar.gz /root/backup && rm -rf /root/backup
Capítulo 1 ■ Introdução
31
O potencial do shell Linux não termina na execução de múltiplos comandos encadeados de maneira sequencial ou condicional. Também permite o redirecionamento de fluxo entre múltiplos comandos, de maneira que a saída do comando anterior seja utilizada para alimentar a entrada do próximo comando e assim sucessivamente, por meio do caractere | entre os comandos. Para exemplificar esse procedimento, primeiramente visualizaremos o que é a saída de um comando para depois pensar em como essa saída pode alimentar a entrada de outro comando. Na parte superior do terminal 1.3, observe que o comando ps aux é utilizado para exibir na tela uma lista com todos os processos em execução no servidor. Ocorre que normalmente a relação de processos ocupa várias páginas, o que dificulta sua consulta. O comando grep permite localizar uma palavra em um arquivo que deve ser fornecido como parâmetro de entrada na sua execução, mas, em vez de informar um arquivo externo, podemos simplesmente redirecionar a saída do comando ps aux como entrada no comando grep para fazê-lo procurar por algum processo que contenha a palavra ssh, por exemplo, em seu nome. A princípio, essa descrição pode parecer mais complicada do que realmente é, já que o comando para fazer isso é bastante simples e pode ser observado na parte inferior do terminal 1.3. Terminal 1.3 – Exemplo de redirecionamento de fluxo sysadmin@Linux:/# ps aux USER PID %CPU %MEM root 1 0.0 0.0
VSZ RSS TTY 5060 2872 ?
STAT START Ss Mar12
TIME COMMAND 2:23 /lib/systemd/systemd
(...) conteúdo omitido com várias páginas de processos... sysadmin@Linux:/# ps aux | grep ssh root 451 0.0 0.1 8108 4492 ?
Ss
Mar12
3:19 /usr/sbin/sshd -D
Também é possível utilizar os caracteres > ou >> para redirecionar o conteúdo de uma saída qualquer na tela para um arquivo externo, o que pode ser bastante útil em algumas situações. Por exemplo, podemos armazenar a configuração temporária de uma interface de rede configurada dinamicamente (via DHCP) em um arquivo externo com o seguinte comando: root@Linux:/# ifconfig eth1 >> ifconfig-eth1.txt
32
Serviços de Redes em Servidores Linux
Ao utilizar o comando anterior, a saída será diretamente armazenada no arquivo externo e não aparecerá na tela. Uma diferença importante é que o operador > sobrescreve a saída por cima do conteúdo original do arquivo, enquanto o operador >> anexará a saída ao conteúdo existente no arquivo. Uma característica ainda mais poderosa do shell é que todos os recursos revisados até agora podem ser combinados entre si. Por exemplo, o seguinte comando poderia ser utilizado para exibir a saída dos processos do sistema, aplicar um filtro para localizar uma palavra específica e, então, armazenar o resultado filtrado no arquivo externo ps-ssh.txt no diretório home do usuário sysadmin: ps aux | grep ssh > /home/sysadmin/ps-ssh.txt
As possiblidades são ainda maiores se o administrador utilizar a flexibilidade das expressões regulares e recursos de programação como variáveis, variáveis especiais, operadores aritméticos, operadores lógicos, operadores relacionais, operadores de redirecionamento, estruturas condicionais, estruturas de repetição etc. Esses recursos todos estão além do escopo deste livro, mas saiba que são muito valiosos porque permitem desenvolver scripts para automatizar praticamente qualquer rotina administrativa do servidor. Enfim, são infinitas as possibilidades no shell Linux...