Guia para Domínio Avançado dos Comandos do Linux - Parte 1

Por Arup Nanda

Publicado Agosto 2006

No excelente artigo de Sheryl Calish, "Guide to Linux File Command Mastery" (Guia para domínio dos comandos de arquivo do Linux), você aprendeu alguns comandos típicos do Linux, que são valiosos principalmente para quem está começando com esse sistema operacional. Mas agora que você domina os conceitos básicos, vamos progredir para alguns comandos mais sofisticados que você achará extremamente úteis.

Nesta série de quatro partes, você aprenderá alguns truques não tão conhecidos sobre vários comandos típicos, além de variações de utilização que os tornam mais úteis. À medida que a série evoluir, aprenderá comandos cada vez difíceis de dominar.

Observe que eles podem ser diferentes dependendo da versão específica do Linux usada ou do kernel específico compilado, mas, nesse caso, as diferenças deverão ser mínimas.

Alterações Sem Transtornos para o Proprietário, o Grupo e as Permissões

No artigo de Sheryl, você aprendeu como usar os comandos chown e chgrp para alterar a propriedade e o grupo dos arquivos. Vamos supor que haja vários arquivos como este: 

# ls -l
total 8
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file2
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file3
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file4
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file5
-rwxr-xr-x    1 oracle   dba           132 Aug  4 04:02 file6


e que seja preciso alterar as permissões de todos os arquivos para que correspondam àquelas de file1. É lógico que você poderia emitir chmod 644 * para fazer essa alteração – mas e se estiver escrevendo um script para fazer isso e não souber as permissões de antemão? Ou então, talvez você esteja fazendo várias alterações nas permissões, com base em muitos arquivos diferentes, e ache inviável percorrer as permissões de cada um deles e modificá-las adequadamente.

Uma abordagem mais eficaz é tornar as permissões semelhantes àquelas do outro arquivo. Este comando faz com que as permissões de file2 sejam as mesmas de file1: 

chmod --reference file1 file2

Agora, se você conferir:  

# ls -l file[12]
total 8
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 oracle   dba           132 Aug  4 04:02 file2

As permissões de file2 foram alteradas exatamente como em file1. Você não precisou obter as permissões de file1 antes.

Também pode usar o mesmo truque na associação de grupos dos arquivos. Para fazer com que o grupo de file2 seja o mesmo de file1, você emitiria: 

# chgrp --reference file1 file2
# ls -l file[12]
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 oracle   users         132 Aug  4 04:02 file2

Evidentemente, o que funciona para alterar os grupos também funcionará para o proprietário. A seguir está o procedimento para usar o mesmo truque em uma alteração de propriedade. Se as permissões tiverem estas características:  

# ls -l file[12] 
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 oracle   dba           132 Aug  4 04:02 file2

Você poderá alterar a propriedade assim: 

# chown --reference file1 file2
# ls -l file[12] 
-rw-r--r--    1 ananda   users          70 Aug  4 04:02 file1
-rw-r--r--    1 ananda   users         132 Aug  4 04:02 file2

Observe que o grupo e também o proprietário foram alterados.

Dica para usuários Oracle


Este é um truque que pode ser usado para alterar a propriedade e as permissões de executáveis Oracle em um diretório com base em algum executável de referência. Isso se prova especialmente útil em migrações nas quais você pode (e talvez deva) instalar como um usuário diferente e depois movê-las para seu proprietário de software Oracle regular.

Mais Detalhes Sobre os Arquivos

O comando ls, com seus muitos argumentos, fornece algumas informações muito úteis sobre os arquivos. Um comando diferente e menos conhecido – stat – oferece informações ainda mais úteis.

A seguir está o procedimento para você usá-lo no executável “oracle”, encontrado em $ORACLE_HOME/bin. 

# cd $ORACLE_HOME/bin
# stat oracle
  File: `oracle'
  Size: 93300148        Blocks: 182424     IO Block: 4096   Regular File
Device: 343h/835d       Inode: 12009652    Links: 1    
Access: (6751/-rwsr-s--x)  Uid: (  500/  oracle)   Gid: (  500/     dba)
Access: 2006-08-04 04:30:52.000000000 -0400
Modify: 2005-11-02 11:49:47.000000000 -0500
Change: 2005-11-02 11:55:24.000000000 -0500

Observe as informações obtidas com esse comando: além do tamanho de arquivo normal (que de qualquer maneira pode ser obtido de ls -l), é obtida a quantidade de blocos que esse arquivo ocupa. O tamanho de bloco típico do Linux é de 512 bytes, por isso um arquivo de 93.300.148 bytes ocuparia (93300148/512=) 182226,85 blocos. Como os blocos são usados em sua totalidade, esse arquivo usa uma quantidade inteira de blocos. Em vez de adivinhar, é possível simplesmente obter os blocos exatos.

Com o resultado anterior, você também obtém o GID e o UID da propriedade do arquivo e a representação octal das permissões (6751). Se quiser restaurá-lo para as mesmas permissões atuais, você poderá usar chmod 6751 oracle, em vez de explicitamente escrever por extenso as permissões.

A parte mais útil do resultado anterior são as informações de registro de data e hora de acesso a arquivos. Elas mostram que o arquivo foi acessado em 2006-08-04 04:30:52 (conforme mostrado ao lado de “Access:”), ou 04 de agosto de 2006, às 4h30min52s. Essa foi a data e hora em que alguém começou a usar o banco de dados. O arquivo foi modificado em 2005-11-02 11:49:47 (conforme mostrado ao lado de Modify:). Por fim, o registro de data e hora ao lado de “Change:” mostra quando o status do arquivo foi alterado.

-f, um modificador do comando stat, mostra as informações sobre o sistema de arquivos, e não do arquivo: 

# stat -f oracle
  File: "oracle"
    ID: 0        Namelen: 255     Type: ext2/ext3
Blocks: Total: 24033242   Free: 15419301   Available: 14198462   Size: 4096
Inodes: Total: 12222464   Free: 12093976

Outra opção, -t, oferece exatamente as mesmas informações, mas em uma única linha: 

# stat -t oracle 
oracle 93300148 182424 8de9 500 500 343 12009652 1 0 0 1154682061 
1130950187 1130950524 4096

Isso é muito útil em scripts de shell nos quais um simples comando de recortar pode ser usado para extrair os valores para processamento adicional.

Dica para usuários Oracle


Quando você reconecta o Oracle (geralmente em instalações de patches), ele move os executáveis existentes para um nome diferente antes de criar o novo. Por exemplo, é possível reconectar todos os utilitários por 

relink utilities


Ele recompila, entre outras coisas, o executável sqlplus. Move o executável sqlplus existente para sqlplusO. Se a recompilação falhar por algum motivo, o processo de reconexão renomeará sqlplusO como sqlplus e as alterações serão canceladas. Da mesma maneira, se você descobrir um problema de funcionalidade após aplicar um patch, poderá desfazê-lo rapidamente renomeando o arquivo manualmente.

A seguir está o procedimento para usar stat nesses arquivos: 

# stat sqlplus*
  File: 'sqlplus'
  Size: 9865            Blocks: 26         IO Block: 4096   Regular File
Device: 343h/835d       Inode: 9126079     Links: 1    
Access: (0751/-rwxr-x--x)  Uid: (  500/  oracle)   Gid: (  500/     dba)
Access: 2006-08-04 05:15:18.000000000 -0400
Modify: 2006-08-04 05:15:18.000000000 -0400
Change: 2006-08-04 05:15:18.000000000 -0400
 
  File: 'sqlplusO'
  Size: 8851            Blocks: 24         IO Block: 4096   Regular File
Device: 343h/835d       Inode: 9125991     Links: 1    
Access: (0751/-rwxr-x--x)  Uid: (  500/  oracle)   Gid: (  500/     dba)
Access: 2006-08-04 05:13:57.000000000 -0400
Modify: 2005-11-02 11:50:46.000000000 -0500
Change: 2005-11-02 11:55:24.000000000 -0500


Vemos que sqlplusO foi modificado em 11 de novembro de 2005, enquanto sqlplus foi modificado em 04 de agosto de 2006, o que também corresponde à hora de alteração do status de sqlplusO . Também vemos que a versão original de sqlplus esteve em vigor de 11 de novembro de 2005 a 04 de agosto de 2006. Se você quiser diagnosticar alguns problemas de funcionalidade, esse será um bom ponto de partida. Além das alterações nos arquivos, como você sabe a hora de alteração da permissão, pode correlacioná-la a quaisquer problemas de funcionalidade percebidos.

Outro resultado importante é o tamanho do arquivo, que é diferente – 9865 bytes do sqlplus, em contraste com 8851 do sqlplusO – indicando que as versões não são meras recompilações; elas na verdade foram alteradas com as bibliotecas adicionais (talvez). Isso também indica uma possível causa de alguns problemas.

Tipos de Arquivos

Resumo dos comandos desta parte da série


Comando Uso
chmod
Para alterar as permissões de um arquivo, usando o parâmetro - -reference
chown
Para alterar o proprietário de um arquivo, usando o parâmetro - -reference
chgrp
Para alterar o grupo de um arquivo, usando o parâmetro - -reference
stat
Para descobrir os atributos estendidos de um arquivo, como a data do último acesso
file
Para descobrir o tipo do arquivo, como ASCII, de dados e assim por diante
diff
Para ver a diferença entre os dois arquivos
cmp
Para comparar os dois arquivos
comm
Para ver os pontos em comum entre dois arquivos, com o resultado em três colunas
md5sum
Para calcular o valor de hash de MD5 dos arquivos, usados para determinar se um arquivo foi alterado

 

Ao ver um arquivo, como saber que tipo de arquivo é? O comando file informa isso. Por exemplo: 

# file alert_DBA102.log
alert_DBA102.log: ASCII text

O arquivo alert_DBA102.log é um arquivo de texto ASCII. Vamos ver outros exemplos: 

# file initTESTAUX.ora.Z
initTESTAUX.ora.Z: compress'd data 16 bits

O código informa que o arquivo está compactado, mas como saber o tipo do arquivo que foi compactado? Uma opção é descompactá-lo e executar o arquivo com ele; mas isso seria praticamente impossível. Uma opção mais eficiente é usar o parâmetro -z: 

# file -z initTESTAUX.ora.Z
initTESTAUX.ora.Z: ASCII text (compress'd data 16 bits)

Outra peculiaridade é a presença de links simbólicos: 

# file -z initTESTAUX.ora.Z
initTESTAUX.ora.Z: ASCII text (compress'd data 16 bits)

Isso é útil, mas para qual tipo de arquivo está sendo apontado? Em vez de executar o arquivo novamente, é possível usar a opção -l: 

# file -L spfile+ASM.ora.ORIGINAL
spfile+ASM.ora.ORIGINAL: data

Vemos claramente que o arquivo é um arquivo de dados. Observe que o spfile é um arquivo binário, em contraste com init.ora; por isso o arquivo aparece como arquivo de dados.

Dica para usuários Oracle

Vamos supor que você esteja analisando um arquivo de rastreamento no diretório de destino de depuração do usuário, mas não tem certeza se o arquivo está localizado em outro diretório e meramente existe como um link simbólico, ou se alguém o compactou (ou mesmo renomeou). Uma coisa você sabe: com certeza é um arquivo ASCII. Eis o que você pode fazer: 

file -Lz * | grep ASCII | cut -d":" -f1 | xargs ls -ltr

Esse comando verifica os arquivos ASCII, mesmo se estiverem compactados, e os lista em ordem cronológica.

Comparando Arquivos

Como saber se dois arquivos – file1 e file2 – são idênticos? Há várias abordagens e cada uma tem suas vantagens.

diff. O comando mais simples é diff, que mostra a diferença entre dois arquivos. A seguir está o conteúdo de dois arquivos: 

# cat file1
In file1 only
In file1 and file2
# cat file2
In file1 and file2
In file2 only

Se você usar o comando diff, poderá ver a diferença entre os arquivos conforme a seguir: 

# diff file1 file2
1d0
< In file1 only
2a2
> In file2 only
#

No resultado, um sinal "<" na primeira coluna indica que a linha existe no arquivo mencionado primeiramente – ou seja, file1. Um sinal ">" nesse lugar indica que a linha existe no segundo arquivo (file2). Os caracteres 1d0 na primeira linha do resultado mostram o que precisa ser feito em sed para operar no arquivo file1 para torná-lo idêntico a file2.

Outra opção, -y, mostra o mesmo resultado, mas lado a lado: 

# diff -y file1 file2 -W 120
In file1 only                             <
In file1 and file2                             In file1 and file2
                                          >    In file2 only

A opção -W é facultativa; ela meramente instrui o comando para que use uma tela com largura de 120 caracteres, o que é útil para arquivos com linhas longas.

Se você quer apenas saber se, e não necessariamente como, os arquivos são diferentes, pode usar a opção -q. 

# diff -q file3 file4
# diff -q file3 file2
Files file3 and file2 differ


Os arquivos file3 e file4 são os mesmos, portanto não há resultado; no outro caso, relata-se o fato de que os arquivos são diferentes.

Se você está escrevendo um script de shell, talvez seja útil produzir os resultados de maneira que possam ser analisados. A opção -u faz isso: 

# diff -u file1 file2        
--- file1       2006-08-04 08:29:37.000000000 -0400
+++ file2       2006-08-04 08:29:42.000000000 -0400
@@ -1,2 +1,2 @@
-In file1 only
 In file1 and file2
+In file2 only

O resultado mostra o conteúdo de ambos os arquivos, mas suprime as duplicidades; os sinais + e – na primeira coluna indicam as linhas dos arquivos. Nenhum caractere na primeira coluna indica a presença em ambos os arquivos.

O comando leva em consideração o espaço em branco. Se quiser ignorar o espaço em branco, use a opção -b. Use a opção -B para ignorar as linhas em branco. Por fim, use -i para ignorar a diferenciação de maiúsculas e minúsculas.

O comando diff também pode ser aplicado a diretórios. O comando: 

diff dir1 dir2

mostra os arquivos presentes em qualquer um dos diretórios, ou em ambos. Se encontrar um subdiretório no mesmo nome, não fará o detalhamento para ver se algum arquivo individual é diferente. A seguir está um exemplo: 

# diff DBA102 PROPRD
  Common subdirectories: DBA102/adump and PROPRD/adump
  Only in DBA102: afiedt.buf
  Only in PROPRD: archive
  Only in PROPRD: BACKUP
  Only in PROPRD: BACKUP1
  Only in PROPRD: BACKUP2
  Only in PROPRD: BACKUP3
  Only in PROPRD: BACKUP4
  Only in PROPRD: BACKUP5
  Only in PROPRD: BACKUP6
  Only in PROPRD: BACKUP7
  Only in PROPRD: BACKUP8
  Only in PROPRD: BACKUP9
  Common subdirectories: DBA102/bdump and PROPRD/bdump
  Common subdirectories: DBA102/cdump and PROPRD/cdump
  Only in PROPRD: CreateDBCatalog.log
  Only in PROPRD: CreateDBCatalog.sql
  Only in PROPRD: CreateDBFiles.log
  Only in PROPRD: CreateDBFiles.sql
  Only in PROPRD: CreateDB.log
  Only in PROPRD: CreateDB.sql
  Only in DBA102: dpdump
  Only in PROPRD: emRepository.sql
  Only in PROPRD: init.ora
  Only in PROPRD: JServer.sql
  Only in PROPRD: log
  Only in DBA102: oradata
  Only in DBA102: pfile
  Only in PROPRD: postDBCreation.sql
  Only in PROPRD: RMANTEST.sh
  Only in PROPRD: RMANTEST.sql
  Common subdirectories: DBA102/scripts and PROPRD/scripts
  Only in PROPRD: sqlPlusHelp.log
Common subdirectories: DBA102/udump and PROPRD/udump


Observe que os subdiretórios comuns são relatados simplesmente como tais, mas não é feita nenhuma comparação. Se quiser fazer o detalhamento adicional e comparar os arquivos nesses subdiretórios, você deverá usar o comando a seguir: 

diff -r dir1 dir2

Esse comando recursivamente entra em cada subdiretório para comparar os arquivos e relata a diferença entre os arquivos de mesmo nome.

Dica para usuários Oracle

Um uso comum do diff é distinguir entre diferentes arquivos init.ora. Como melhor prática, sempre copio o arquivo com um novo nome – por exemplo, initDBA102.ora como initDBA102.080306.ora (para indicar 03 de agosto de 2006) – antes de fazer alguma alteração. Um simples diff entre todas as versões do arquivo informa rapidamente o que foi alterado e quando.

Esse é um comando bastante poderoso para gerenciar o Oracle Home. Como melhor prática, nunca atualizo um Oracle Home ao aplicar patches. Por exemplo, vamos supor que a versão atual do Oracle seja 10.2.0.1. O ORACLE_HOME poderia ser /u01/app/oracle/product/10.2/db1. Quando chega a hora de aplicar um patch nele para o 10.2.0.2, eu não aplico o patch nesse Oracle Home. Em vez disso, começo uma instalação nova em /u01/app/oracle/product/10.2/db2 e aplico patch nesse Home. Depois de pronto, eu uso este código: 

# sqlplus / as sysdba
SQL> shutdown immediate
SQL> exit
# export ORACLE_HOME=/u01/app/oracle/product/10.2/db2
# export PATH=$ORACLE_HOME/bin:$PATH
# sqlplus / as sysdba
SQL> @$ORACLE_HOME/rdbms/admin/catalog
...

e assim por diante.

A finalidade dessa abordagem é que o Oracle Home original não seja atrapalhado e eu possa facilmente reverter a situação em caso de problema. Isso também significa que o banco de dados sai do ar e volta novamente, quase que instantaneamente. Se eu instalasse o patch diretamente no Oracle Home, teria de encerrar o banco de dados por bastante tempo – durante toda a aplicação do patch. Além disso, se a aplicação do patch tivesse falhado por algum motivo, eu não teria um Oracle Home limpo.

Agora que tenho vários Oracle Homes, como posso ver o que foi alterado? É bem simples, pois posso usar: 

diff -r /u01/app/oracle/product/10.2/db1 /u01/app/oracle/product/10.2/db2 | 
grep -v Common

O código informa as diferenças entre os dois Oracle Homes e entre os arquivos de mesmo nome. Alguns arquivos importantes como tnsnames.ora, listener.ora e sqlnet.ora não devem mostrar grandes diferenças, mas se mostrarem, precisarei entender o porquê.

cmp. O comando cmp é semelhante a diff: 

# cmp file1 file2   
file1 file2 differ: byte 10, line 1

O resultado é retornado como o primeiro sinal de diferença. Você pode usar isso para identificar os possíveis pontos diferentes dos arquivos. Como diff, cmp tem muitas opções, sendo a mais importante delas a opção -s, que meramente retorna um código:

  • 0, se os arquivos forem idênticos
  • 1, se forem diferentes
  • Algum outro número diferente de zero, se não for possível fazer a comparação

A seguir está um exemplo: 

# cmp -s file3 file4
# echo $?
0

A variável especial $? indica o código de retorno do último comando executado. Nesse caso, é 0, o que significa que os arquivos file1 e file2 são idênticos. 

# cmp -s file1 file2
# echo $?
1

significa que file1 e file2 não são os mesmos.

Essa propriedade de cmp pode se provar útil em script de shell, em que você meramente quer verificar se dois arquivos são diferentes de alguma maneira, mas não necessariamente verificam qual é a diferença. Outro uso importante desse comando é comparar arquivos binários, em que diff pode não ser confiável.

Dica para usuários Oracle

Lembre-se de uma dica anterior: ao reconectar executáveis Oracle, a versão mais antiga é mantida antes de ser sobrescrita. Assim, ao se reconectar, o executável sqlplus é renomeado como “sqlplusO” e o recém-compilado sqlplus é colocado em $ORACLE_HOME/bin. Então, como garantir que o sqlplus recém-criado seja de alguma maneira diferente? Basta usar: 

# cmp sqlplus sqlplusO
sqlplus sqlplusO differ: byte 657, line 7

Se você verificar o tamanho: 

# ls -l sqlplus*
-rwxr-x--x    1 oracle   dba          8851 Aug  4 05:15 sqlplus
-rwxr-x--x    1 oracle   dba          8851 Nov  2  2005 sqlplusO

Mesmo que o tamanho seja igual em ambos os casos, cmp provou que os dois programas são diferentes.

comm. O comando comm é semelhante aos outros, mas o resultado aparece em três colunas, separadas por tabulações. A seguir está um exemplo: 

# comm file1 file2
        In file1 and file2
In file1 only
In file1 and file2
        In file2 only

Esse comando é útil quando se quer ver o conteúdo de um arquivo não no outro, e não apenas uma diferença – uma espécie de utilitário MINUS na linguagem SQL. A opção -1 suprime o conteúdo encontrado no primeiro arquivo: 

# comm -1 file1 file2
In file1 and file2
In file2 only

md5sum. Este comando gera um valor hash de MD5 de 32 bits dos arquivos: 

# md5sum file1
ef929460b3731851259137194fe5ac47  file1

Dois arquivos com a mesma soma de verificação podem ser considerados idênticos. Entretanto, a utilidade desse comando vai além da mera comparação de arquivos. Ele também pode oferecer um mecanismo para garantir sua integridade.

Vamos supor que você tenha dois arquivos importantes – file1 e file2 – que precisam ser protegidos. Você pode usar a verificação da opção --check para confirmar que os arquivos não foram alterados. Primeiro, crie um arquivo de soma de verificação para esses dois arquivos importantes e mantenha-o em local seguro: 

# md5sum file1 file2 > f1f2

Depois, ao verificar se os arquivos ainda estão intactos: 

# md5sum --check f1f2      
file1: OK
file2: OK

Vemos claramente que eles não foram modificados. Agora altere um deles e verifique o MD5: 

# cp file2 file1
# md5sum --check f1f2
file1: FAILED
file2: OK
md5sum: WARNING: 1 of 2 computed checksums did NOT match

O resultado mostra claramente que file1 foi modificado.

Dica para usuários Oracle

O md5sum é um comando extremamente poderoso para implementações de segurança. Alguns dos arquivos de configuração que você gerencia, como listener.ora, tnsnames.ora e init.ora, são cruciais em uma infra-estrutura Oracle bem-sucedida e qualquer modificação pode resultar em tempo de inatividade. Em geral eles fazem parte de seu processo de controle de alterações. Em vez de apenas confiar na palavra de terceiros de que esses arquivos não foram alterados, comprove usando a soma de verificação de MD5. Crie um arquivo de soma de verificação e sempre que fizer uma alteração planejada, recrie-o. Como parte da compliance, verifique esse arquivo usando o comando md5sum. Se alguém sem querer atualizou um dos arquivos cruciais, você imediatamente detectará a alteração.

Na mesma linha, você também pode criar somas de verificação de MD5 para todos os executáveis em $ORACLE_HOME/bin e compará-las periodicamente para modificações não-autorizadas.

Conclusão

Até agora você aprendeu somente alguns dos comandos Linux que achará úteis para executar seu trabalho com eficácia. Na próxima parte da série, descreverei alguns comandos mais sofisticados porém úteis, como strace, whereis, renice, skill e muitos outros.


Arup Nanda ( arup@proligence.com) é DBA Oracle há mais de 12 anos, lidando com todos os aspectos de gerenciamento de banco de dados – como ajuste de performance, segurança e recuperação de catástrofes, dentre outros. É co-autor de PL/SQL for DBAs (O'Reilly Media, 2005), foi “DBA do Ano” da Oracle Magazine em 2003 e é ACE Oracle.