Por que, quando conecto um disco, ele não funciona no sistema operacional, um pendrive não é lido pelo sistema? E a interface de rede se recusa a aparecer na lista de dispositivos? Como conectar discos e configurar seu funcionamento ou permitir o uso de uma determinada lista de dispositivos? Todas essas e outras perguntas vamos considerar a resposta, analisando a arquitetura e o princípio de funcionamento com dispositivos no Linux. Após este tutorial, você será capaz de configurar, gerenciar o estado e a permissão dos dispositivos no seu sistema por conta própria.
Como funciona o mapeamento de discos no Linux?
Vamos dividir o ciclo completo de montagem de um disco no Linux, a fim de entender como ele funciona no sistema. E o que pode ser feito para resolver os problemas que surgem?
Conectamos fisicamente ou virtualmente o disco ao nosso sistema, e então as informações sobre o novo dispositivo chegam ao kernel. O kernel seleciona um driver para seu funcionamento e coleta informações sobre o dispositivo. No Linux, qualquer dispositivo é um "arquivo", e isso significa que o kernel, após coletar as informações, grava os dados em um arquivo na pasta /dev. Mas este não é um arquivo comum de descrição do dispositivo conectado, e sim um ponto de acesso ao disco!
Os programas podem abrir, ler, gravar e manipular esses arquivos de dispositivo usando chamadas de sistema padrão como open(), read(), write() e ioctl(). Essas chamadas são passadas através do arquivo de dispositivo para o driver do dispositivo, que então se comunica com o hardware através do kernel.
O driver do dispositivo converte as chamadas do sistema em comandos de hardware, que o kernel passa para o dispositivo. O retorno do dispositivo também passa pelo driver de volta ao software.
Depois disso, o kernel cria o evento uevents e o controle passa para o Udev, que é um gerenciador de dispositivos com um conjunto de regras preparado. Estes são usados para alterar o nome do dispositivo, direitos de acesso do usuário, bloqueio e scripts ao conectar ou desconectar dispositivos. Se houver critérios que exigem alterações, o Udev irá até o diretório /dev e executará as ações necessárias.
Como conectar um drive ao Linux?
Todas as etapas deste tutorial podem ser realizadas em servidores em nuvem poderosos. A Serverspace oferece servidores VPS isolados para uso comum e virtualizado.
Levará algum tempo para implantar a capacidade do servidor. Depois disso, você pode se conectar de qualquer uma das maneiras convenientes!
Agora vamos olhar a situação na prática, precisamos montar um disco e dar a ele um nome especial, proibir a conexão de dispositivos com um determinado UUID e executar um script para automatizar nossas tarefas. Isso pode ser qualquer coisa: particionar um novo disco, rotacionar arquivos antigos ou notificar o administrador.
Vamos conectar o disco e fazer alguma configuração básica: particionar e definir o sistema de arquivos. Use o comando lsblk para examinar os discos montados:
O novo disco aparece como vdb sem volumes lógicos ou particionamento. Para começar a usá-lo, é necessário criar uma tabela e volumes, e então selecionar um sistema de arquivos para a partição lógica que será suportada pelo sistema operacional. Depois disso, monte o disco no sistema operacional. Para fazer isso, vá até o utilitário fdisk e digite o comando:
Por padrão, uma tabela MBR é criada para o disco, que pode ser sobrescrita e é preferível usar particionamento GPT em seu lugar. Para isso, especifique a letra g, após isso a tabela será recriada e o disco será reparticionado. Para criar um novo volume na tabela atual, pressione n para definir seus parâmetros:
Selecione o tipo da partição e especifique o primeiro e o último setor para criar um volume. Depois disso veremos o resultado de que um volume de 10 GB foi criado, resta escrever as alterações e salvá-las com o comando w. Para que o disco seja processado pelo sistema operacional, é necessário inicializar o sistema de arquivos para o volume. Para isso, use o utilitário mkfs.ext4:
Para montar um disco temporariamente, podemos usar o comando mount, onde devemos primeiro especificar o próprio disco e o ponto de montagem. Mas esta solução será válida até a reinicialização, para montar um novo disco automaticamente cada vez — vá para a pasta /etc/fstab e faça alterações:
Para inicializar um drive, você precisa especificar seu UUID ou caminho direto, no nosso caso /dev/vdb1. Para ver os discos atuais, digite lsblk.
Ótimo, o drive está montado e pronto para uso! Agora, ele passará pela etapa de montagem em cada reinicialização, no entanto, e se for necessário renomeá-lo? Ou permitir que apenas um número limitado de pessoas o utilize?
Como gerenciar o drive e usar o udev?
Para gerenciar dispositivos de bloco e simbólicos, use o utilitário udev, que se comunica com o kernel através de eventos uevent. Todas as configurações para os dispositivos são feitas em arquivos de configuração para cada dispositivo separadamente. Para criar um link simbólico ou restringir o acesso, você precisa conhecer os parâmetros únicos do disco a ser pesquisado:
Para escrever uma regra é necessário encontrar um valor único para um disco, neste caso é ATTR{serial} com um certo número. Para escrever uma regra, vamos até a pasta rules.d, onde todos os algoritmos previamente escritos para o funcionamento com cada dispositivo são armazenados. Vamos criar uma regra chamada:
Vamos escrever a seguinte sintaxe, que primeiro encontrará o dispositivo correto e depois aplicará as configurações das regras udev:
Depois salve o arquivo e reinicie o serviço udev:
E verifique os parâmetros relevantes através do comando:
No arquivo de regras do udev, você pode usar diferentes condições de validação, como:
- SUBSYSTEM: Verifica o subsistema do dispositivo. Exemplo: SUBSYSTEM=="block" (o dispositivo pertence ao subsistema de blocos).
- KERNEL: Verifica o nome do dispositivo especificado pelo kernel. Exemplo: KERNEL=="sd*" (o nome do dispositivo começa com "sd").
- ATTR{attribute}: Verifica o atributo do dispositivo. Exemplo: ATTR{size}=="1024" (o atributo de tamanho do dispositivo é 1024).
- ENV{environment_variable}: Verifica uma variável de ambiente. Exemplo:
ENV{ID_SERIAL}=="1234567890" (o número de série do dispositivo é 1234567890). - DRIVER: Verifica o driver do dispositivo. Exemplo: DRIVER=="usb-storage" (o dispositivo usa o driver usb-storage).
- ACTION: Verifica a ação realizada no dispositivo. Exemplo: ACTION=="add" (o dispositivo foi adicionado) ou ACTION=="remove" (o dispositivo foi removido).
- PROGRAM: Executa um comando e verifica o resultado. Exemplo: PROGRAM="/path/to/script" (executa um script no caminho especificado).
- RESULT: Verifica o resultado da execução do programa. Exemplo: RESULT=="1" (o resultado da execução do programa é 1).
- TEST: Verifica a existência de um arquivo ou diretório. Exemplo: TEST=="/path/to/file" (verifica a existência de um arquivo no caminho especificado).
Todos os atributos acima podem ser usados para filtrar o dispositivo. Também para cada um deles são usados elementos lógicos, por exemplo == ou != na condição. Os parâmetros de ação são então especificados:
- SYMLINK+=: Cria uma referência simbólica ao dispositivo. Exemplo: SYMLINK+="mydevice" (cria um link simbólico /dev/mydevice).
- NAME=: Atribui um nome ao dispositivo. Exemplo: NAME="mydisk" (atribui o nome do dispositivo como mydisk).
- OWNER=: Define o proprietário do dispositivo. Exemplo: OWNER="username" (define o proprietário do dispositivo como username).
- GROUP=: Define o grupo do dispositivo. Exemplo: GROUP="disk" (define o grupo do dispositivo como disk).
- MODE=: Define os direitos de acesso do dispositivo. Exemplo: MODE="0660" (define os direitos de acesso como 0660).
- RUN+=: Executa o programa ou script especificado. Exemplo: RUN+="/path/to/script" (executa o script no caminho especificado).
- IMPORT=: Importa variáveis de ambiente do programa ou arquivo especificado. Exemplo: IMPORT{program}="/path/to/program" (importa variáveis de um programa).
- OPTIONS=: Define opções adicionais para o dispositivo. Exemplo: OPTIONS+="last_rule" (especifica que esta é a última regra para este dispositivo).
- ATTR{attribute}=: Define o valor do atributo do dispositivo. Exemplo: ATTR{power/control}="auto" (define o valor do atributo power/control como "auto").
- ENV{environment_variable}=: Define o valor de uma variável de ambiente. Exemplo: ENV{UDISKS_IGNORE}="1" (define a variável de ambiente UDISKS_IGNORE como 1).
- TEST=: Verifica a existência de um arquivo ou diretório. Exemplo: TEST=="/path/to/file" (verifica a existência de um arquivo no caminho especificado).