Unix: Conceitos e Comandos Básicos


Este documento é um tutorial de introdução ao Unix. É fundamentalmente prático, e deve ser acompanhado por testes e exercícios. Para não tornar o texto pesado, fugiu-se da exaustão, por isso as descrições dos comandos são sempre parcias, e devem ser completadas pela documentação on-line da plataforma em uso.

Conteúdo


Ligando e Desligando a Máquina

Salvo orientação específica do hardware em uso, ligar uma máquina Unix não costuma envolver maiores detalhes do que o acionamento de um botão liga/desliga no console da máquina e uma eventual intervenção humana logo em seguida, solicitando o boot efetivo do sistema a partir de um menu de opções.

O boot costuma gerar uma razoável quantidade de mensagens que aparecem no console da máquina. Normalmente elas referem-se aos diferentes estágios do reconhecimento e inicialização do hardware. É interessante conhecê-las, não obstante, salvo contingências, podem ser ignoradas até que surja o prompt ou a janela de login.

O desligamento é um processo mais delicado. O Unix utiliza parte da memória principal como cache de disco, a fim de acelerar as operações de leitura e gravação de arquivos. Antes de se desligar a máquina, é necessário assegurar que os discos estejam sincronizados com o cache, o que é feito pelo comando sync, que deve ser precedido do encerramento de todos os processos, a fim de que não ocorra uma dessincronização em seguida. Todos esses passos são tomados pelo comando shutdown:

$ shutdown -y -g 1 -i 5   (Solaris)
$ shutdown -h now         (Linux)
Em sistemas baseados em PC, o shutdown por vezes é acionável através do ctrl-alt-del.

Manipulando arquivos e diretórios

O shell é o programa que lê e executa os comandos que você passa a digitar logo após logar no sistema, como cd ou ls. Via de regra você estará usando o Bourne shell (sh), ou o C shell (csh), ou aperfeiçoamentos desses, como o Korn shell (ksh) ou o Bourne again shell (bash). Via de regra você poderá descobrir qual deles está usando ao executar um ps ou um finger com o seu username com argumento.

Obsoleta ou não, a interface de linha de comandos possui características ainda não suficientemente reproduzidas nas interfaces gráficas, como a possibilidade de uso remoto com baixa banda, e a programabilidade. No caso do Unix, há ainda a vantagem dela estar melhor estandardizada que as interfaces gráficas. Em boa parte dessas notas estaremos nos referindo à interface de linha de comandos, mas abordaremos também a interface gráfica ao final. Vejamos alguns típicos comandos dos sistemas Unix-like:


Shell Scripts

Seqüências de comandos que se necessita repetir com grande frqüência podem ser colocados num arquivo que, ao ser ``executado'', ocasiona o disparo de cada um dos comandos da seqüência, na ordem indicada. Um arquivo desses é um shell script, cujo equivalente no MS-DOS são os arquivos ``.BAT''.

Mesmo que nunca se escreva nenhum, com certa freqüência é necessário analisar shell scripts a fim de elucidar o modo de uso de determinados comandos, ou de realizar diagnósticos. Suponhamos por exemplo que você não se lembre como usar um comando chamado xpatgen, mas esteja com um shell num diretório que contém scripts, que usam entre outros o xpatgen. Basta então buscar ocorrências dele nos scripts:

$ grep xpatgen *
patgen: xpatgen -cal_bl

Com isso sabemos que o script patgen executa o xpatgen, e relembramos o modo de executar esse comando, o que talvez já seja suficiente para a necessidade do momento.

Shell scripts utilizam com freqüência de variáveis de environment e de parâmetros de linha de comando. Assim, se ao analisar um script você se deparar com algo como $HOST, lembre-se de que nesse ponto será substituído o valor da variável HOST, e que $1 significa o primeiro parâmetro da linha de comandos, $2 o segundo, e assim por diante.


Variáveis de Environment

Além dos parâmetros de linha de comandos como -l ou outros, pode-se também passar parâmetros a um programa através do uso de variáveis de environment. As mais comuns são:

Para exibir o valor de uma delas pode-se usar echo, antepondo o operador $ ao nome da variável, por exemplo:

$ echo $TERM

Existem dois estilos de atribuição de valores a variáveis de environment, o do Bourne shell, usado pelo sh, ksh e bash:

$ TERM=vt100; export TERM
e o do C shell, usado pelo csh e pelo tcsh:

% setenv TERM vt100


Uso de Metacaracteres

O metacaracter mais utilizado provavelmente é o ``*''. Por exemplo,

$ rm *

irá remover todos os arquivos do diretório corrente. É necessário prestar atenção a dois detalhes quando se usa metacaracteres:

  1. O caracter ``.'' não tem o significado de separador entre nome e sufixo que possui no MS-DOS, por isso ``*.*'' significa todos os arquivos em cujo nome ocorre ao menos um ponto.

  2. A expansão do metacaracter é feita pelo shell, e não pela aplicação, por isso o comando

    $ mv *.txt *.bak

    não irá surtir o efeito esperado de renomear todos os arquivos que terminam com ``.txt'' para ``.bak'' (para essa operação deve-se usar o comando for).

Os shells Unix aceitam também o metacaracter ``?'', que significa qualquer caracter e tambem intervalos, como [0-9] (qualquer dígito decimal), entre outros.


Uso de Expressões Regulares

Aplicativos Unix via de regra aceitam expressões regulares como argumentos de busca. Os usos mais freqüentes delas são bem ilustrados através do aplicativo grep. Nos casos abaixo ele será utilizado para buscar uma dada expressão em todos os arquivos do diretório corrente:

  1. Busca de ocorrências de algum dos anos da década de 80:

    $ grep "198[0-9]" * 

  2. Busca de uma ocorrência da palavra "yellow" seguida de uma ocorrência da palavra "page", separadas por zero ou mais caracteres quaisquer:

    $ grep -i "yellow.*page" * 

  3. Busca de uma das palavras "roget" ou "thesaurus":

    $ grep -i "roget\|thesaurus" * 

A sintaxe das expressões regulares pode variar um pouco, dependendo da plataforma e da ferramenta. Via de regra as diferenças consistem em proteger-se ou não alguns caracteres especiais, e nas extensões que algumas ferramentas introduzem. Note por exemplo, o uso do egrep, em comparação com o uso do grep acima:

$ egrep -i "roget|thesaurus" * 

Via de regra todas as ferramentas Unix que lidam com texto, como o more, o sed, e o vi, entre outros, aceitam expressões regulares como argumento de buscas.


Manipulando processos

Um processo é um programa em execução. Num computador que possui apenas uma cpu, na verdade apenas um processo pode estar sendo executado em cada instante. O que se faz é executar um processo durante uma fração fixa de segundo, congelá-lo e passar a executar um outro, e assim por diante, criando a ilusão de simultaneidade.

Através do comando ps pode-se examinar os processos correntes. Por exemplo:

$ ps
PID TTY STAT  TIME COMMAND
 45 v02 S     0:00 -bash
105 v02 R     0:00 ps

O ps em geral omite muitos processos a fim de exibir uma saída limpa. Através das opções a e x (ou e no Solaris), pode-se exibir todos os processos correntes. O número de um processo é usado, por exemplo quando é necessário interromper prematuramente a sua execução, através do comando kill.

A finalidade primária do comando kill não é matar um processo, mas enviar um sinal para ele. O Unix possui diversos sinais predefinidos, como SIGHUP, SIGPIPE, SIGTERM, etc. O atendimento a um sinal entretanto é responsabilidade do processo, ou do programador que fez o programa, e por isso a forma com que cada processo reagirá a cada sinal poderá variar. A fim de se interromper a execução de um processo, deve-se enviar para ele o sinal SIGKILL:

 $ kill -SIGKILL 45
 $ kill -9 45

As duas formas acima em geral são equivalentes (o número associado a cada sinal pode variar com a plataforma).

O caracter ``&'' colocado ao final da linha de comandos instrui o shell para disparar o comando em background, a fim de que se possa continuar usando o shell mesmo antes desse comando encerrar a sua execução.

O comando nice faz com que um processo seja disparado com baixa prioridade.

 $ nice gzip -9 *

O comando nohup faz com que o processo sendo disparado se torne imune ao sinal SIGHUP. Em combinação com o &, ele permite o disparo de programas que permanecerão em execução mesmo após o logout do usuário. Exemplos:

 $ nohup gzip -9 * &

Através do comando at pode-se programar a execução de um comando para um horário determinado. Por exemplo:

 $ at now + 1 minute
 ls
 ctrl-d

O comando ls será dessa forma executado daqui a um minuto. Note que na linha seguinte do comando at o que se escreve é na verdade um shell script, terminado com control-d. Ao invés de digitá-lo, poder-se-ia lê-lo de um arquivo através do redirecionamento da entrada:

 $ at now + 1 minute <meuscript 

A execução periódica de um comando se faz através do cron, que é disparado no boot do sistema e monitora as tabelas de execução periódica de comandos de todos os usuários (a cada usuário corresponde uma tabela). Uma tal tabela é chamada crontab. Através dela pode-se especificar que um comando seja executado a cada hora, ou diariamente, ou semanalmente, etc. A edição, inspeção e remoção da crontab de um usuário é feita através do comando crontab, e opções -e, -l e -d. Cada linha da crontab indica um comando e a periodicidade com que ele deve ser executado (minutos, horas, dias do mês, meses e dias da semana). Por exemplo:

 $ crontab -l
 40 07 * * * updatedb
 0 22 5 * * pagamento
 0 6,12,15,18 * * * fetch
 0 0 * * 6 backup

No caso a crontab contém três comandos. O updatedb deverá ser executado todos os dias às 7:40. O comando pagamento deverá ser executado às 22:00 do dia 5 de cada mês, e o backup será executado à zero hora de cada sábado.

Note que a crontab é um arquivo texto simples, e quando se executa o comando crontab com a opção -e, entra-se num editor de textos para editá-la. O editor de textos utilizado normalmente será o vi, ou aquele especificado na variável de environment EDITOR.


Configurando o terminal

O terminal pode ser um terminal no sentido estrito do termo, conectado ao computador por uma linha serial, ou então o próprio console da máquina, ou uma aplicação como o xterm emulando um terminal dentro do Xwindows,

A configuração do terminal é necessária para executar aplicativos como editores de texto visuais, ou para os comandos de teclado como backspace serem corretamente reconhecidos. Essa configuração envolve a configuração do driver do sistema, feita através do comando stty e o informe da aplicação, normalmente feito através da variável TERM. Vejamos exemplos de situações onde uma delas ou ambas são necessárias, e como realizá-la:

  1. Ao pressionar a tecla backspace, ao invés de ser apagado o caracter anterior, surge na tela os caracteres ``^H''. Solução:

    $ stty erase ^H

  2. Ao executar o more ou o vi, algumas linhas permanecem escondidas, ou o scroll comporta-se de forma errática. Solução: cheque quantas linhas (vamos supor: 24) e quantas colunas (vamos supor: 80) o seu terminal/emulador possui e execute

    $ stty rows 24 cols 80

  3. Após o uso de alguma aplicação, os caracteres aparecem trocados ou o eco deixou de funcionar, ou quando pressiono enter o cursor permanece na mesma linha. Tentativa de solução:

    $ stty sane

  4. Ao tentar executar uma aplicação, a mensagem de erro terminal capability cm required, ou Terminal type is not defined, ou Terminal type is not powerful enough, ou outra semelhante foi exibida. Solução: cheque o tipo de terminal que você está usando ou emulando (dificilmente será algo diferente de xterm ou vt100) e atribua para a variável de environment TERM esse valor.


Diretórios Principais do Sistema

No Unix não há o conceito de nomes de drives, como C:, mas todos os paths partem de uma raiz comum, o root directory ``/''. Quando a máquina possui vários discos diferentes (ou ao menos várias partições diferentes de um mesmo disco), cada uma delas em geral corresponderá a uma subárvore do filesystem, como /usr, /var ou ainda nomes não standard como /disco2, que são chamados de seus pontos de montagem. O comando mount executado sem parâmetros listará os diferentes dispositivos físicos montados (discos locais e remotos e suas partições) e a subárvore correspondente a cada um deles. A tabela que indica todas essas montagens é o arquivo /etc/fstab. Apesar de algumas pequenas diferenças de plataforma para plataforma, os diretórios principais do sistema são:

/bin
/sbin
/etc
/home
/lib
/proc
/tmp
/usr
Binários básicos, como sh e ls.
Binários básicos de administração do sistema.
Arquivos de configuração do sistema e scripts de boot.
Os diretórios dos usuários residem aqui.
Bibliotecas básicas.
Estado corrente do sistema e dos processos.
Arquivos temporários.
Demais binários e bibliotecas.

O termo básico aplicado acima aos diretórios /bin e /lib quer significar principalmente essenciais para o boot e operação mínima do sistema. A separação desses elementos básicos, em contraposição aos que são deixados no /usr, deve-se a razões práticas, principalmente para facilitar a organização de redes de máquinas compartilhando subárvores de diretório. De fato, é comum que o diretório /usr ao invés de estar replicado em todas as máquina da rede esteja residindo fisicamente num único disco, e sendo compartilhado por todas as máquinas.


Atributos e Nomes de Arquivos

No Unix cada arquivo (inclusive diretórios, que são casos particulares de arquivos), conta com um conjunto de atributos de leitura, escrita e execução, que são setáveis através do comando chmod, e podem ser exibidos pelo comando ls -l:

$ ls -l /bin/cat
-rwxr-xr-x   1 root     root        16584 Dec 16 20:09 /bin/cat

A string -rwxr-xr-x representa os atributos do arquivo /bin/cat. O primeiro caracter (-) significa que se trata de um arquivo regular, em contraposição aos diretórios (d), device special files (c) e links simbólicos (l). Os 9 caracteres restantes informam as permissões de leitura, escrita e execução desse arquivo relativas ao seu proprietário, ao seu grupo, e a todos os demais. O proprietário e o grupo são informados logo à direita, e no caso são o usuário root e o grupo root.

Note que no Unix não existem os atributos de arquivo oculto ("hidden") e do sistema ("system"), suportados no MS-DOS. Não obstante, arquivos cujo primeiro caractere é ponto (".") normalmente são omitidos pelo ls, a não ser que se utilize a opção -a (de "all"), conforme comentamos no início.

Um atributo importantíssimo existente no Unix é o chamado setuid, através do qual um processo adquire ao ser executado os privilégios do owner do arquivo. Isso é frequentemente utilizado por programas que são disparados por usuários não privilegiados mas que por algum motivo necessitam dos privilégios do superusuário, por exemplo:

  $ ls -l /usr/sbin/pppd
  -rwsr-xr-x  1 root   bin   104876  Apr 27  1998 /usr/sbin/pppd

Sem os privilégios de superusuário, um usuário comum não conseguiria configurar a interface ppp e nem alterar a tabela de rotas do sistema, no momento em que se conecta ao provedor Internet. Assim, o pppd, ao ser executado, requisitará os privilégios do owner do arquivo, que no caso é o superusuário, e dessa forma ele poderá realizar essas operações.

No Unix via de regra são suportados nomes ``longos'' (até 64 ou às vezes até 256 caracteres), e o ``.'' não é um separador entre o nome do arquivo e sua extensão, mas um caracter como os outros. Não obstante, a noção de ``sufixo'' é utilizada informalmente para facilitar a identificação de alguns formatos de arquivos, por exemplo:

.tar
.zip
.Z
.gz
Archive produzido com tar
Archive comprimido produzido com zip
Arquivo comprimido com compress
Arquivo comprimido com gzip

Archives (o termo não tem correspondente em português) são concatenações de vários arquivos ou de subárvores inteiras num único arquivo. Em Unix, tipicamente são produzidos com tar:

$ tar cvf /tmp/etc.tar /etc
$ tar tvf /tmp/etc.tar /etc
$ cd  /tmp; tar xvf etc.tar

O primeiro comando irá criar o archive /tmp/etc.tar, composto por toda a subárvore /etc. O segundo exibirá o conteúdo desse archive. O terceiro irá extrair todo o seu conteúdo dentro do diretório /tmp, ou seja, recriará aquela mesma subárvore como uma subárvore do diretório /tmp.


Intercambiando Disquetes com o MS-DOS

Via de regra as plataformas Unix-like oferecem ferramentas para lidar com disquetes ``formatados'' no MS-DOS (ou, mais precisamente, disquetes que usam FAT). Um set de ferramentas bastante popular é o mtools, que oferece clones das ferramentas do MS-DOS. Exemplos de uso:

$ mformat a:
$ mcopy a:relat.txt .
$ mdir a:
Versões recentes dessas ferramentas lidam também com o VFAT do Windows 95, que permite nomes de arquivos ``longos''.

O intercâmbio de arquivos texto entre Unix e MS-DOS deve ser feito com cuidado. Por herança das antigas impressoras, o fim-de-linha no MS_DOS é codificado através de dois caracteres (CR e LF), enquanto no Unix há apenas um (o LF), além do que o final do arquivo é sinalizado no MS-DOS por um CTRL-Z. O mcopy possui a opção -t para realizar essas conversões quando copia de ou para disquetes.


O Kernel

O Kernel do Unix (e de virtualmente qualquer outro sistema operacional) possui um papel de que convém ter noções, a fim de se poder compreender melhor o funcionamento do sistema, realizar diagnósticos e procedimentos administrativos como adição de componentes de hardware. Algum conhecimento do papel do kernel é importante também para se ter uma noção mais clara do uso de arquivos especiais e do diretório /proc.

O Kernel ordinariamente reside no filesystem como um outro arquivo qualquer. No Linux, ele é em geral o arquivo /vmlinuz ou /boot/vmlinuz, ou ainda /boot/vmlinuz-2.0.36. Ele é um programa, ainda que um pouco diferente dos programas de aplicação como o /bin/ls. O kernel é carregado e posto em execução no boot da máquina, e a sua execução somente se encerra com o shutdown.

De forma simplificada, o seu papel é num primeiro momento reconhecer o hardware e inicializar os respectivos drivers. Em seguida ele entra num estado administrativo onde funciona como intermediário entre as aplicações e o hardware. Por exemplo, quando uma aplicação necessita alocar mais memória, ela solicita isso ao kernel. É o kernel que distribui o tempo de CPU aos vários processos ativos. É ele que habitualmente realiza a entrada e saída de dados nas diferentes portas de comunicação.

É por isso que a adição de hardware novo a uma máquina pode requerer a substituição ou ao menos a reconfiguração do kernel. Os kernels mais recentes do Linux oferecem vários mecanismos de configuração que os tornam sobremaneira flexíveis, a ponto de ser rara a necessidade de substituição do kernel. Os dois mecanismos fundamentais de se configurar a operação do kernel são a passagem de parâmetros no momento do boot (realizada pelo LILO) e a carga de módulos, feita manualmente ou por mecanismos automáticos como o kerneld.

O diálogo entre as aplicações e o kernel realiza-se fundamentalmente através dos system calls, que são serviços que o kernel oferece, como por exemplo read(2). Os device special files são maneiras de se referir ao kernel os dispositivos físicos ou lógicos com que se pretende operar, por exemplo a primeira porta serial ou a segunda unidade de fita, ou o disco principal do sistema. Neles, o importante não é o nome, mas sim os números de dispositivo, ou mais precisamente o major e o minor device numbers. Device special files são criados através do comando mknod, ou através de interfaces mais amigáveis, como o comando MAKEDEV.

Os sistemas Unix-like mais recentes oferecem um outro mecanismo de comunicação com o kernel, que é o filesystem /proc. As entradas desse filesystem são pseudo-arquivos cujo conteúdo reflete o estado atual de inúmeras estruturas de dados internas do kernel. Assim, um programa de aplicação passa a poder comunicar-se com o kernel através dos mecanismos ordinários de leitura e escrita de arquivos.

Em muitos casos a comunicação entre as aplicações e o kernel é intermediada por bibliotecas, principalmente a libc. Elas oferecem serviços de mais alto nível que os system calls do kernel, tornando mais simples o trabalho de programação.

Redirecionamento da Entrada e da Saída; Pipes

Processos num sistema Unix habitualmente possuem três dispositivos de I/O ``padrões'', a ``saída padrão'', a ``entrada padrão'' e a ``saída de erros''. O Unix permite que esses dispositivos (e outros) sejam definidos no momento da execução, podendo escolher o console, um ``pipe'', a impressora, um circuito virtual de rede conectando duas máquinas, uma linha física serial ou outras coisas.

Usuários de MS-DOS talvez já tenham feito coisas como

C> DIR >PRN:

para imprimir a saída de um comando. Essa sintaxe foi herdada do Unix daí a semelhança:

$ ls -l >/dev/lp1

Naturalmente tanto no MS-DOS quanto no Unix existem formas mais apropriadas para se imprimir algo, mas no momento esse exemplo convém. Shells do estilo ``Bourne'' (sh, ksh, bash) permitem redirecionamento da saída de erros através da seguinte sintaxe:

$ rm /bin/ls 2>/tmp/error
O ``2'' deve-se a que, internamente, a saída de erros corresponde ao descritor 2 (o 0 é a entrada padrão e o 1 é a saída padrão).

A entrada pode ser redirecionada de forma semelhante:

$ wc </tmp/error 
Os shells Unix oferecem um recurso para a ligação da saída padrão de um processo com a entrada padrão de outro, chamado pipe:

$ ls|wc

No exemplo a saída do ls está sendo usada como entrada do wc. Note que o shell dispara os dois processos ao mesmo tempo. Se o primeiro estiver produzindo saída numa taxa superior à que o segundo lê, o sistema operacional paralizará o primeiro sempre que o buffer que armazena o tráfego estiver cheio. Isso significa, por exemplo, que um pipe pode ser usado mesmo quando o volume total da saída do primeiro processo é extraordinariamente grande, por exemplo quando se tenta localizar informações de arquivos deletados através de um dump de todos os setores do disco.


Comunicação Serial e Paralela

O Unix apresenta as portas de comunicação seriais e paralelas na forma de arquivos especiais. Já vimos um exemplo do seu uso no ítem Redirecionamento da Entrada e da Saída, em que fizemos a impressão da saída de um comando.

Na comunicação entre dois computadores, utiliza-se freqüentemente portas seriais, e às vezes também as paralelas. Em muitos casos, quando a distância entre os dois é grande, haverá uso de modems, e eventualmente também de uma linha telefônica. Através de três exemplos práticos pode-se ter um bom panorama do uso de comunicação serial no Unix. Como os procedimentos variam um pouco dependendo das plataformas em uso, só é possível indicá-los de forma genérica:

a) Adição de um terminal

  1. Conectar a serial do terminal com a da máquina Unix.
  2. Disparar no Unix a variante do getty disponível.
  3. Logar no terminal.
  4. Transferir arquivos se o terminal oferecer esse recurso.

b) Conexão a um sistema remoto

  1. Disparar algum emulador de terminal disponível.
  2. Selecionar a serial em que o modem está conectado.
  3. Configurar o modo de operação da serial (velocidade, bits).
  4. Configurar o modem através de comandos AT, se necessário.
  5. Instruir o modem para discar, com ATD
  6. Aguardar a negociação.
  7. Logar.

c) Estabelecimento de um link ppp

  1. Executar a conexão ao sistema remoto como indicada acima.
  2. Iniciar o ppp no sistema remoto.
  3. Disparar o pppd localmente.

Em PCs, os conectores externos das portas seriais são conectores DB-9 ou DB-25 macho, e os das paralelas são DB-25 fêmea.


Configuração do TCP/IP

Numa rede TCP/IP, a cada máquina está associado um número IP, que é um inteiro de 32 bits, normalmente escrito na forma de octetos, como 192.168.0.5. A cada máquina está associado um nome, como por exemplo marte ou pimenta.

A atribuição tanto do número quanto do nome é feita durante o processo de boot, a partir da especificação deles feita através da edição manual de arquivos de configuração e/ou do uso de aplicativos de gerenciamento do sistema específicos de cada plataforma.

Na verdade, o número IP não está associado à máquina, mas a uma determinada interface dela. Via de regra, a interface envolvida é a ethernet. Tanto para exibir quanto para setar manualmente o número IP de uma interface usa-se o comando ifconfig. Por exemplo, o comando:

$ ifconfig -a

irá listar todas as interfaces com informações de cada uma. A interface ethernet costuma chamar-se le0 (Solaris) ou eth0 (Linux). Além do ethernet, é comum usar-se portas seriais para criar interfaces TCP/IP, principalmente para criar links com linhas telefônicas. As placas ethernet costuma oferecer dois ou mais tipos de conectores. Ela pode ou não descobrir automaticamente qual está em uso. Em caso negativo, você deverá informá-la, o que habitualmente é feito através de um software de configuração que acompanha a placa.

O passo seguinte é a configuração das rotas. Através delas a máquina sabe por onde enviar datagramas a fim de que eles cheguem em seus destinos. Equivale de certa forma à sinalização do tráfego urbano, com placas indicativas da direção a tomar para atingir cada destino (Ponte do Limão à esquerda, ou Avenida Bandeirantes em frente, etc).

Cada rota envolve um destino, uma máscara, um gateway e uma interface. Pode-se exibir todas elas através do comando netstat:

$ netstat -r
Destination  Gateway       Genmask        Iface
192.168.1.0  *             255.255.255.0  eth0
127.0.0.0    *             255.0.0.0      lo
default      192.168.1.1   0.0.0.0        eth0

Suponha que você deseja atingir a máquina 192.168.1.7. A aplicação da tabela de rotas indica, através de uma operação e bit-a-bit entre 192.168.1.7 e a máscara 255.255.255.0, que deve ser usada a primeira rota. Como não há gateway, a comunicação será feita diretamente através do ethernet.

Se o destino agora for 200.136.35.65, as duas primeiras rotas não nos servirão (experimente aplicar o e como no caso anterior). Portanto será usada a rota default, e como ela especifica um gateway, a comunicação terá que ser feita através dele. Assim, toda vez que se pretender enviar alguma informação para o 200.136.35.65, esta será enviada antes para o gateway 192.168.1.1, na esperança de que este consiga roteá-la para o seu destino.


Serviços TCP/IP

Atualmente é comum as pessoas confundirem Internet com a teia mundial WWW, entretanto muito antes de surgir a teia, a Internet já usava um sem-número de serviços construídos a partir dos protocolos de transporte TCP e UDP.

Um circuito TCP entre duas máquinas equivale a um pipe duplo entre dois processos, cada um rodando em uma das máquinas. O telnet é um típico serviço que se utiliza desse recurso, a fim de criar sessões remotas. Pode-se exibir todas os circuitos TCP ativos através do comando netstat:

$ netstat -t

O FTP, por sua vez, cria dois circuitos, utilizando um para envio de comandos e outro de dados. Através do uso de alguns comandos simples, permite transferir arquivos de ou para uma máquina remota. Os principais comandos do FTP são:

asc,bin
hash
get,put
mget,mput
prompt
modo de transferência texto/binário
faz o display de um ``#''a cada 1kb transferido
transfere de/para a máquina remota o arquivo especificado
idem, múltiplos arquivos
liga/desliga o modo interativo


Disparo do Xwindows e das suas aplicações

O disparo do X é desnecessário quando o sistema opera num runmode em que o X está permanentemente ativo. Nesse caso, o próprio login é feito numa janela, ao invés de no console no modo texto.

Quando for necessário disparar o X manualmente, via de regra haverá dois ou três scripts já preparados para isso, como o startx ou o openwin. O que eles fazem basicamente é definir uma série de parâmetros e executar o xinit, que por sua vez dispara o Xserver e o Window Manager.

Convém não perder de vista que o Xwindows é um sistema cliente-servidor. O Xserver é o programa que conhece o hardware gráfico, é capaz de colocar o display no modo desejado, e desenhar nele. As aplicações conectam o Xserver através de um circuito TCP (por exemplo) e enviam a ele comandos através dos quais desenham as suas janelas e o conteúdo delas. O Window Manager é responsável por desenhar as molduras das janelas, criar menus de aplicações, e controlar o foco.

Assim, é natural que no disparo de cada aplicação seja necessário especificar qual é o server a ser utilizado. Isso normalmente se faz através da opção de linha de comando -display, ou através da variável de environment DISPLAY.

$ xterm -display 192.168.0.1:0.0
$ DISPLAY=192.168.0.1:0.0; export DISPLAY; xterm

Quando o Xserver está rodando numa máquina Unix, a permissão para um cliente usá-lo é dada através do comando xhost:

$ xhost +192.168.1.5    (autoriza o cliente 192.168.1.5)
$ xhost -192.168.1.5    (desautoriza o cliente 192.168.1.5)
$ xhost                 (lista os clientes autorizados)

Pode-se autorizar permanentemente um cliente a usar um determinado Xserver adicionando-o ao arquivo /etc/X0.hosts (um cliente por linha).

Ao longo dos anos foram sendo criados inúmeros Window Managers diferentes para o Xwindows. Algumas vezes além do window manager foram criadas também complexas bibliotecas oferecendo serviços de alto nível que além de simplificar o trabalho de programação tamém permitem estandardizar o aspecto visual e os recursos das janelas das aplicações. Um dos produtos mais conhecidos dessa linha é o Motif. O advento do Free Software criou outras opções, sendo as mais em voga atualmente o GTK e o QT, que são utilizados respectivamente pelo GNOME e pelo KDE.


Procedimentos de boot e o init

O boot do Unix consiste inicialmente na carga e execução do kernel. Em seguida, é disparado o processo init, que segue as instruções do arquivo /etc/inittab, que portanto é o ponto de partida para tudo o que se pretenda configurar a nível de disparo de processos ao longo do boot.

O inittab não é um script como o AUTOEXEC.BAT, mas uma lista de ações, algumas delas de valor permanente para todo o curso da operação do sistema. Cada linha válida representa um processo que o init deve disparar. O termo respawn significa que, além de disparar, o init deverá monitorar o processo e, se porventura ao longo da operação do sistema ele for encerrado, o init deverá redispará-lo.

Via de regra as linhas do inittab referem-se ou à chamada de scripts de configuração inicial do sistema, que são executados apenas uma vez, ou aos processos de controle de login no sistema, que são redisparados sempre que ocorre um logout. O inittab inclui ainda o conceito de runlevel, o que cria a flexibilidade de se poder inicializar a máquina em um de vários possíveis modos de operação. Na prática, costuma haver três modos principais, o single-user, utilizado para manutenção, um gráfico e um não gráfico.

Quanto aos scripts de configuração (normalmente são os arquivos e/ou diretórios /etc/rc.*, dependendo da plataforma a mecânica de disparo deles pode ser bastante complexa. Note que cada runlevel pode disparar ou deixar de disparar alguns scripts, a fim de estabelecer o modo de operação desejado. Em quase todas as versões mais recentes do Linux essa mecânica segue o padrão dos diretórios /etc/rc.d/rcN.d, onde N é cada um dos runlevels. O conteúdo desses diretórios são links para cada um dos scripts de ativação ou desativação de serviços básicos (interfaces de rede, servidor de email, etc), com números embutidos nos nomes dos links, a fim de definir a ordem em que devem ser processados.


Referências

Virtualmente qualquer informação técnica sobre sistemas Unix-like pode ser obtida na Teia Mundial. Estou colocando aqui apenas um referência clássica (o Livro do Bach), e um link para uma lista de pontos de entrada de documentação sobre Linux.

[1] Bach, M. J. The Design of the Unix Operating System, Prentice-Hall, 1986.

[2] Alguns links de Linux, inclusive para materiais em português, estão disponíveis em http://www.ime.usp.br/~ueda/ldoc/links.html .