Introdução a shell script
Introdução Programar em shell faz voltarmos a filosofia clássica do UNIX que é quebrar projetos complexos em subtarefas mais simples (isso é conhecido como princípio KISS, de Keep It Simple Stupid). Um conhecimento em shell script é essencial para qualquer um que deseja se tornar um administrador de sistemas, pois usando scripts, podemos realizar tarefas de administração muito mais rapidamente e muito mais facilmente (imagine a diferença entre ter que cadastrar trezentos usuários manualmente ou fazer um script com 6 linhas que cadastra todos estes usuários e ainda pode definir uma senha padrão para eles).
Todos os exemplos daqui podem ser testados bastando apenas salvar o arquivo em formato ASCII (pode-se usar qualquer editor de texto para isso, vi ou emacs por exemplo) e dar a permissão de execução ao arquivo do script (com chmod u+x nome-do-script).
A essência da programação em scripts pode ser resumida em saber lidar bem com pipes (se pronuncia páipes), redirecionamentos e pouco mais que uma dúzia de comandos.
Eu pretendo com este (futuro) conjunto de textos passar um exemplo simples e explicar os detalhes dele seja novos comandos ou mesmo o porque de um redirecionamento ao invés de um pipe. Além disso, pretendo explicar alguns conceitos como por exemplo como fazer um laço num script e etc.
O uso de Pipes No primeiro exemplo, vamos ver um script que simplesmente conta quantos são os usuários cadastrados no sistema.
#!/bin/bash
cat /etc/passwd |wc -l
A primeira linha (#!/bin/bash) apenas informa ao sistema qual shell usar e a segunda, lê o arquivo com informações do usuário e repassa estas informações por pipe para o comando wc -l, que apenas conta o número de linhas recebidas pela entrada padrão (stdin).
O pipe nada mais é que o símbolo | e este faz com que tudo o que for saída padrão (stdout) do comando antes do pipe seja repassado para a entrada padrão do comando após o pipe. O comando cat neste exemplo irá direcionar o conteúdo do arquivo /etc/passwd para sua saída padrão (este arquivo nada mais é do que o banco de dados de usuários de um sistema Unix e cada usuário é representado por exatamente uma linha deste arquivo). Sabendo que cada usuário ocupa uma linha, basta contarmos quantas linhas tem este arquivo para sabermos quantos usuários o sistema possui. É aí que o comando wc entra. Com o parâmetro -l, wc conta o número de linhas recebidas resultando neste caso no número de usuários do sistema. Simples não ?
Após salvarmos o arquivo (que vou chamar de script.sh), damos a permissão de execução para o arquivo com chmod u+x script.sh e o executamos com ./script.sh. A saída dele deve ser apenas um número, como 35.
Aqui começam os problemas: você sabe que existem 35 usuários no sistema, mas e o seu chefe (aquele mesmo que tem dificuldade até para mudar o papel de parede daquele sistema operacional), ele vai saber o que este número sem lógica significa ?
Expansão de comandos Agora que já vimos como usar pipes, vamos começar a deixar nossos scripts mais amigáveis.
#!/bin/bash
echo “Existem `cat /etc/passwd |wc -l` usuarios no sistema”
Neste exemplo, usamos o comando echo que simplesmente irá ecoar tudo o que estiver entre as aspas para a saída padrão mas, antes disso, o bash irá executar os comandos entre as crases e retornar para o echo a saída do comando. O echo vai receber entre as aspas algo como Existem 35 usuarios no sistema e irá ecoar isso (agora o seu chefe vai saber o que o seu script faz !).
Trabalhando com variáveis Nosso pequeno script até agora apenas executa comandos, ele não armazena informação alguma. Se precisarmos do número de usuários cadastrados no sistema em algum outro momento, teremos que executar os comandos novamente ou podemos armazenar o resultado dele em uma variável:
#!/bin/bash
tmp=`cat /etc/passwd | wc -l`
echo “Existem $tmp usuarios no sistema”
No exemplo anterior, armazenamos o número de usuários do sistema numa variável chamada tmp e a passamos como parâmetro para o echo (o shell expande as variáveis antes de executar o comando, neste exemplo a variável foi tratada pelo shell como se o próprio comando entre crases tivesse sido executado novamente, mas isto não foi preciso pois o shell “lembrou” do resultado da última execução). O shell sabe que é uma variável porque colocamos um $ antes do nome dela.
Trabalhando com laços para (for) Podemos incrementar nosso script fazendo, por exemplo, ele contar quantas vezes um usuário conectou ao sistema. Neste caso, usaremos o comando last, que retorna todos os logins que obtiveram sucesso no sistema desde a instalação do mesmo (ou desde que o log foi rotacionado pela última vez) e o comando cut, que serve para cortar parte de uma linha:
#!/bin/bash
for user in `cat /etc/passwd|cut -d “:” -f 1`;do
cont=`last|grep $user|wc -l`
echo “usuario $user conectou $cont vezes”
done
Explicando com detalhes: o cut recebe cada linha do comando cat e retorna apenas o primeiro campo (-f 1) usando “:” como separador de campos (se você executar apenas cat /etc/passwd poderá observar que o primeiro campo corresponder ao nome dos usuários no sistema). O for construído desta maneira, irá montar um vetor (referenciado pela variável user ) onde cada posição contém o nome de um usuário do sistema. Além disso, cada passo do laço será exatamente o nome de um usuário.
Dentro do laço, a variável count receberá a saída da execução do comando last (para obter uma lista de todo mundo que se logou no sistema) passando a saída por pipe para grep (onde iremos filtrar para mostrar apenas as linhas com o usu&aaute;rio user) e finalmente irá repassar, também por pipe, para wc (onde iremos contar quantas linhas aparece o nome do usuário, ou seja, quantas vezes ele se logou no sistema).
Ainda no laço, iremos ecoar o nome do usuário que estamos lendo da lista naquele momento e a valor atual de cont. Para finalizar o laço, usamos done.i
Testes de condições (if / else) No script anterior, vimos que vários usuários se conectaram 0 vezes ao sistema. A maioria deles é usuário do sistema que nunca terá login algum (se tiver, é bom se analisar o motivo, pode ser alguma falha de segurança sendo explorada).
Mas e se eu não quiser mostrar quem nunca se conectou ? Poderíamos apenas fazer um teste para ver se a variável cont esta com valor 0 e, se não estiver, imprimimos a mensagem.
#!/bin/bash
for user in `cat /etc/passwd|cut -d “:” -f 1`;do
cont=`last|grep $user|wc -l`
if [ $cont -ne 0 ]; then
echo “usuario $user conectou $cont vezes”
fi
done
Neste script, adicionamos o teste se (if) onde verificamos se a variável cont é diferente ( -ne, not equal) de zero. Se for diferente, o script executa o bloco entre o if e o fi (fi finaliza um bloco if) e a mensagem informando o número de logins do usuário será mostrada.
Além disso, poderíamos colocar uma mensagem informando que o usuário nunca se logou ao sistema (ao invés de informar que ele se logou zero vezes).
#!/bin/bash
for user in `cat /etc/passwd|cut -d “:” -f 1`;do
cont=`last|grep $user|wc -l`
if [ $cont -eq 0 ]; then
echo “usuario $user nunca conectou ao sistema”
else
echo “usuario $user conectou $cont vezes”
fi
done
Neste exemplo, mudamos o teste para se igual (-eq, equal) a zero, então mostre a mensagem e adicionamos um senão ( else), mostre outra mensagem.

Post a Comment