Operações matemáticas com shell script

Uma coisa que chama a atenção em shell script são as operações matemáticas. Em shell script a princípio elas não são resolvidas diretamente, para resolver essas operações é necessário usar algum comando auxiliar, por exemplo:


a=1;
b=2;
# c=$a+$b; não iria funcionar
d=$(( $a + $b )); # ok

obs. também é possível usar os comandos let, expr e bc para resolver operações matemáticas.

Mas essa caracteristica apesar de ser padrão, pode ser modificada usando o comando ‘declare -i’ para criar as variáveis, veja:


a=1;
b=2;
declare –i c; # a variavel c é do tipo inteiro
c=$a+$b; # a operacao é resolvida diretamente...
# cuidado com os epaços...

Isso garante que a variável ‘c’ é do tipo inteiro, e não vai aceitar outros tipos de valores, algo parecido com o que ocorre com linguagens fortemente tipadas, mas diferentemente dessas, ao se atribuir um valor diferente do estipulado não será emitida uma mensagem de erro, veja:


declare –i c; # c é inteiro
c=”paulo”;
echo $c # imprime 0 (zero)

Ao tentar setar uma string em ‘c’ o valor é desconsiderado, ficando o valor de zero no lugar.

É importante perceber que usando o comando ‘declare -i’, além da variável assumir (parcialmente) caracteristicas de uma linguagem fortemente tipada, também terá alterações no seu escopo. Veja os exemplos:


Function teste() {
a=10;
}
teste # executa a função
echo $a #imprimie 10

Diferente de outras linguagens as variáveis dentro de funções não são por padrão locais, ou seja, elas iram escapar para o escopo principal quando a função for executada (caracteristica bem estranha, na minha opinião), mas se for usado o comando ‘declare –i’ isso não acontece:


Function teste() {
declare –i a=10;
}
teste
echo $a # nao imprimi 10

valeu pessoal, espero que seja util…

Obs. Se você precisa que as variáveis dentro de funções sejam locais e não quer usar o declare –i ou as suas variáveis não são numericas use “local a=10”;

Configurando o GRUB2 no Debian Squeeze

Os principais arquivos de configuração do GRUB2 são o /boot/grub/grub.cfg, o /etc/default/grub e também os scripts localizados no diretório /etc/grub.d/.

Na verdade, a configuração manual do GRUB2 é feita apenas no arquivo /etc/default/grub e nos scripts do diretório /etc/grub.d/. O arquivo /boot/grub/grub.cfg apesar de ser o principal arquivo de configuração, não deve ser alterado manualmente, esse arquivo será configurado pelo comando update-grub tendo como base o conteúdo dos arquivos anteriores.

/etc/grub.d/

Os arquivos do diretório /etc/grub.d/ são scripts responsáveis por montar o arquivo /boot/grub/grub.cfg. Esses scripts serão executados pelo comando update-grub, por tanto, devem ter permissão de execução.

A ordem de execução desses arquivos segue a ordem alfabética de seus nomes, por exemplo: o arquivo 05_debian_theme é executado antes do 10_linux.

Alguns scripts desse diretorio são:

00_header: é o script que carrega as configurações que estão no arquivo /etc/default/grub, por exemplo: o tempo de espera e a entrada de boot padrão.

05_debian_theme: Define a aparência do GRUB2

10_linux: Localiza os kernels do sistema operacional e cria suas entradas no menu.

20_memtest86+: Cria as entradas do memtest.

30_os-prober: Busca outros sistemas operacionais e cria as suas entradas no menu.

40_custom: é apenas um modelo para criar entradas adicionais no menu do GRUB2.

/etc/default/grub

O arquivo /etc/default/grub não é exatamente um script, nele é possível alterar diretamente o valor de varias variáveis de configuração, por isso, esse arquivo é bem mais amigável que os scripts do diretório grub.d.

Configurações

Configurar as cores do menu:

Tecnicamente o arquivo responsável por essa configuração é o script 05_debian_theme, mas por se tratar de um script, ele exige um certo conhecimento em programação, felizmente existe uma forma mais simples de fazer essa configuração: Crie o arquivo /boot/grub/custom.cfg e dentro dele coloque o seguinte conteúdo:

set color_normal=light-gray/black

set color_highlight=blue/white

set menu_color_normal=magenta-light-grayset

menu_color_highlight=blue/white

Onde:

color_normal : Cor da fonte e do background

color_highlight: Cor da fonte e do background com seleção

menu_color_normal:  Cor da fonte e do background do menu

menu_color_highlight: Cor da fonte e do background do menu com seleção

Alguma das cores possíveis são: black, blue, green, cyan, red, magenta, brown, light-gray, dark-gray, light-blue, light-green, light-cyan, light-red, light-magenta, yellow e white.

E pronto, não é necessário rodar o comando update-grub, o arquivo será carregado automaticamente.

Colocar uma imagem no GRUB2

Essa é outra opção que a principio deveria ser configurada no script 05_debian_theme, mas pelo mesmo motivo anterior vou mostrar uma forma alternativa: No arquivo /etc/default/grub altere ou crie a seguinte linha e rode o comando update-grub:

GRUB_BACKGROUND=“coloque aqui o caminho até a imagem”

Uma boa fonte de imagens para o menu GRUB2 é o pacote GRUB2-splashimages, após a instalação, verifique o diretório /usr/share/images/grub/ ( para ver como instalar pacotes no Debian clique aqui )

Alterar a resolução do GRUB2:

Para configurar a resolução da tela do GRUB2 altere a seguinte linha no arquivo /etc/default/grub e rode o comando update-grub:

GRUB_GFXMODE=640×480

Essa configuração altera apenas a resolução da tela do GRUB2, não terá efeito no sistema. É interessante manter a resolução do menu igual a resolução do sistema.

Configurar o boot padrão:

Essa configuração especifica qual a entrada do menu que vai ser executada automaticamente se o usuário não especificar nenhuma até o final do tempo de espera. Para configurar o boot padrão, altere a seguinte linha no arquivo /etc/default/grub e rode o comando update-grub:

GRUB_DEFAULT=0

onde o 0(zero) é a primeira entrada do menu do GRUB2, 1 a segunda, 2 a terceira… Também é possível utilizar GRUB_DEFAULT=saved, assim, a entrada padrão será sempre a última que foi selecionada, ou seja, se na última vez o usuário selecionou a entrada 1, essa será opção padrão até que ele selecione outra.

Ajustar o tempo de espera:

Esse é o tempo que o GRUB2 vai esperar antes de chamar o boot padrão. Para configurar, altere a seguinte linha no arquivo /etc/default/grub e rode o comando update-grub:

GRUB_TIMEOUT=5

Incluir ou retirar o recovery mode:

Para configurar a entrada do recovery mode altere o valor da seguinte linha no arquivo /etc/default/grub e rode o comando update-grub:

GRUB_DISABLE_LINUX_RECOVERY=”true”

se o valor for true, o recovery mode não vai ter sua entrada no GRUB2, se for false vai ter.

Configurar a entrada do memtest:

Para retirar a opção de memtest do menu execute os seguintes comandos:

chmod -x /etc/grub.d/20_memtest86+; update-grub;

Para habilitar essa opção novamente rode os seguintes comandos:

chmod +x /etc/grub.d/20_memtest86+; update-grub;

Se quiser habilitar essa opção, mas o script 20_memtest86+ não estiver no diretório grub.d, instale o pacote memtest86+ .

Personalizar as entradas do menu

Para editar as entradas que estão no menu do GRUB2, é possível copiar essas entradas da configuração que já está pronta no arquivo /boot/grub/grub.cfg (afinal ela está funcionando normalmente) e depois colar no script 40_custom. As entradas do menu do GRUB2 são configuras pela palavra chave menuentry e são delimitadas por chaves {}, segue um exemplo:

menuentry “Titulo da opção” {

aqui ficam os comandos

}

O arquivo /boot/grub/grub.cfg é dividido por blocos BEGIN e END, cada bloco é gerado por um dos scripts do diretório /etc/grub.d/.

É importante guardar o nome dos scripts que geraram os blocos de onde estão as menuentry que serão copiadas. Cuidado, copie apenas as menuentry’s.

Com as entradas já coladas no script 40_custom faça as alterações necessárias e salve. Com isso, se o comando update-grub fosse rodado as entradas personalizadas já estariam no GRUB2, mas as entradas padrão também, ou seja, as entradas ficariam em dobro.

Para evitar isso, é necessário tirar a permissão de execução dos scripts que geram as entradas padrão(os scripts do diretorio grub.d), para isso, execute o comando a seguir para cada um desses scripts, faça somente naqueles que o nome aparecia em um bloco BEGIN e END de onde foram copiadas as menuentry’s, não tire a permissão dos outros…

cd /etc/grub.d/;
chmod -x nome_do_script

E por último rode o comando update-grub.

Criar uma nova entrada para o menu:

A principio dificilmente será necessário criar uma entrada manualmente para o menu do GRUB2, se por algum motivo um sistema não for reconhecido após o comando update-grub, instale o pacote os-prober e rode os comandos abaixo:

os-prober; update-grub;

O os-porber é capaz de localizar sistemas que não estejam sendo reconhecidos pelo GRUB2. Se ainda assim, o sistema não for reconhecido, é possível criar uma entrada no menu manualmente através do script 40_custom que está no diretório /etc/grub.d/. Para criar uma entrada para uma distribuição GNU/Linux insira o seguinte conteúdo no script 40_custom e execute o update-grub:

menuentry “Titulo do Sistema” {

set root=(hd0,1)
linux /boot/vmlinuz-versão_do_kernel
initrd /boot/initrd.img-versão_do_kernel
}

Esse é o mínimo para se criar uma entrada para um sistema GNU/Linux no GRUB2.
Em set root=(hd0,1) está sendo especificado que o sistema está no primeiro disco(hd0) e na primeira partição desse disco. Obs.: Os discos iniciam no zero( hd0, hd1, hd2… ), mas as partições iniciam no 1.

Onde diz “versão_do_kernel” substitua pela versão do kernel que o sistema utiliza. Se tiver acesso a esse sistema, é possível verificar qual a versão do kernel com o comando uname -r.

Para criar uma entrada no menu para um sistema Windows( xp, vista, 7 ) use:

menuentry “Titulo do Sistema” {

set root=(hd0,1)
chainloader +1
}

Mais sobre o GRUB2:
http://www.vivaolinux.com.br/dica/Personalizando-o-Grub-2
http://www.gnu.org/software/grub/
http://www.vivaolinux.com.br/dica/Colocando-senha-criptografada-no-GRUB-2

Programação em Shell Script

O Shell Script é uma linguagem de programação utilizada principalmente para automatizar tarefas administrativas em sistemas operacionais Unix, Linux, BSD… Existem vários interpretadores para os scripts em shell, o mais utilizado em distribuições linux é o Bash, além dele, também é possível utilizar o Sh , Csh e o Ksh . Nesse artigo vou utilizar o Bash, veja um exemplo de Shell Script com Bash:



#!/bin/bash
echo "ola $USER";

Esse script simplesmente cumprimenta o usuário. Nele utilizei o comando “echo”, que imprime na saída padrão ( nesse caso vai ser a tela do monitor ), e a variável de ambiente “$USER”, que guarda o usuário logado. A primeira linha desse Shell Script, “#!/bin/bash”, indica o interpretador que deve executar os comandos que estão no arquivo. é possível utilizar outro interpretador shell, por exemplo o “#!/bin/sh” ou um interpretador de outra linguagem como “#!/usr/bin/python”( seria possível usar até mesmo o PHP, veja um exemplo aqui ) ou não especificar nenhum interpretador, nesse ultimo caso, o sistema usa o interpretador que estiver na variável “$SHELL” ( interpretador padrão ).

Para testar esse script é necessário que ele tenha permissão de execução no sistema, para isso, supondo que o nome do arquivo seja “teste.sh” vou rodar no terminal o comando:



chmod +x teste.sh

e depois para executar o script vou usar o comando:



./teste.sh

Para executar o Shell Script coloquei o caminho completo do arquivo teste.sh ( o “./” representa o diretório atual ), isso foi necessário porquê quando é digitado um comando ( ou um Shell ) no terminal, sem especificar o caminho até o arquivo, o sistema busca por ele nos diretórios que aparecem no variável “$PATH”. Se não quiser especificar o caminho para executar seus scripts, você pode colocá-los em um dos diretórios que aparecem na “$PATH” ou configurar o diretório onde eles estão nessa variável ( exemplo de como fazer isso aqui ).

Assim como outras linguagens de programação, Shell Script possui estruturas de controle do tipo: if, case, while e for. A Sintaxe dessas estruturas é a seguinte:

If


#!/bin/bash
nome="paulo";
if [ $nome != "paulo" ] ; then

echo "vc não é o paulo!";
fi

Case


#!/bin/bash
i=1;
case $i in

1)
echo "é 1";
;;

2)
echo "é 2";
;;

*)
echo "não eh 1 nem 2";
;;
esac

While


#!/bin/bash
i=1;
while [ $i -le 10 ] ; do

echo $i;
i=$(( $i + 1 ));
done

For


#!/bin/bash
for i in $( seq 10 ) ; do

echo $i;
done

Em Shell Script os espaçamentos que normalmente são permitidos em outras linguagens causam erros, por exemplo quando é criada uma variável não deve haver espaços entre o nome da variável, o sinal de igual e o valor atribuído.


#!/bin/bash
i=1; # ok, vai funcionar
j = 2; # não vai funcionar

Obs. é possível utilizar o comando “read” para ler da entrada padrão( geralmente o teclado ) e criar variaveis especificadas pelo usuário. Veja mais sobre isso aqui

Outra particularidade do Shell Script é que operações matemáticas não são realizadas diretamente, é necessário utilizar algum comando para realizar o calculo, por exemplo:


#!/bin/bash
i=1;
j=$(( $i + 1 )); # ok
j=$( expr $i + 2 ); # ok
j=$i + 1; # não vai funcionar como esperado

Nesse exemplo foi utilizado o comando “$( expr $i + 2 )”, basicamente trata-se de um sub-shell, o que estiver dentro de “$( )” é executado à parte e o resultado( o que seria impresso na saída padrão) é atribuído para variável. Também seria possível utilizar o comando “` expr $i + 2 `” para ter o mesmo resultado.

Outro detalhe importante que foi visto nos exemplos anteriores são os operadores usados nas estruturas de controle dentro do comando “[ ]”, que na verdade é um açúcar sintático para o comando “test”, veja alguns exemplos de operadores:

Para Numeros
-lt É menor que (LessThan)
-gt É maior que (GreaterThan)
-le É menor ou igual (LessEqual)
-ge É maior ou igual (GreaterEqual)
-eq É igual (EQual)
-ne É diferente (NotEqual)
Para Strings
= É igual
!= É diferente
Testes logicos
! Negação
-a and ( geralmente && )
-o or( geralmente || )

O Shell Script também possui funções, elas tem a seguinte sintaxe:


#!/bin/bash

function somar() {

echo $(( $1 + $2 ));
}

somar 1 2

As funções em Shell Script são chamadas da mesma forma que um comando, elas recebem parâmetros sem a necessidade de especificá-los na declaração da função. Os parâmetros são recuperados através de variáveis especais, como a “$1” e a “$2” utilizadas no exemplo acima. Veja outras dessas variáveis especiais:

$0 O nome da função
$1 O primeiro parâmetro
$2 O segundo parâmetro
$numero O parâmetro da posição numero
$# A quantidade de parâmetros
$* Todos os parâmetros

O script anterior poderia ter sido escrito da forma abaixo para não limitar o número de parâmetros a ser somados:


#!/bin/bash

function somar() {

resultado=0;
for i in $* ; do

resultado=$(( $resultado + $i ));
done

echo $resultado;
}

somar 1 2 3 4 5

Uma observação importante sobre as funções em Shell Script é que apesar de possuir a instrução “return”, essa instrução é utilizada de uma forma diferente. Em Shell Script funções são como os comandos, os comandos tem um código de retorno que indica se o comando foi executado corretamente ou não( isso é testado com a variável “$?” ), portanto as funções também tem esse código de retorno, que é retornado com a instrução “return” 🙂

Para conseguir armazenar o retorno de função em uma variável costumo usar o sub-shell:


#!/bin/bash

function somar() {

resultado=0;
for i in $* ; do

resultado=$(( $resultado + $i ));
done

echo $resultado;
}

#usando o sub-shell é possível
#armazenar o retorno da função
total=$( somar 1 2 3 4 5 );

A grande utilidade das funções é que elas organizam e garantem a reutilização de código. Uma possibilidade interessante que o Shell Script permite( e a maior parte das linguagem de script também ) e incluir um arquivo dentro de outro ( parecido com o require e include do PHP). Por exemplo, posso criar varias funções que estejam relacionadas e coloca-las no mesmo arquivo e depois quando for necessário uso a instrução “source” para incluir essas funções em outro arquivo. Supondo que a função “somar” estivesse no arquivo matemática.sh posso usá-la da seguinte maneira:


#!/bin/bash

source "matematica.sh";

total=$( somar 1 2 3 4 5 );

Além de funções e estruturas de controle, Shell Script também possui arrays. Os arrays tem a seguinte sintaxe em Shell Script:


#!/bin/bash

dias=( "domingo" "segunda" "terca" "quarta" "quinta" "sexta" "sabado" );

echo ${dias[1]}; # imprime segunda

nomes[0]="paulo";
nomes[1]="ana";
nomes[2]="carlos";

echo ${nomes[1]};

# para retornar a quantidade de itens
echo ${#nomes[@]} # imprime 3

Vou terminar deixando um script com o que foi visto nesse artigo, se quiser saber mais sobre Shell Script veja os links mais abaixo. Até mais… 🙂


#!/bin/bash
function organiza() {

array=($@);
i=0;
while [ $i -lt ${#array[@]} ]; do

j=$(($i + 1));
while [ $j -lt ${#array[@]} ]; do

if [ ${array[$j]} -lt ${array[$i]} ]; then

aux=${array[$j]};
array[$j]=${array[$i]};
array[$i]=$aux;
fi
j=$(($j + 1));
done
i=$(($i + 1));
done

for n in ${array[@]}; do

echo "$n";
done
}

organiza 2 9 4 5 6 1

Mais Informações:
http://aurelio.net/shell/canivete/pdf/canivete-shell.pdf
http://thobias.org/doc/shell_bd.html
http://thobias.org/doc/cgi_shell.html
http://www.vivaolinux.com.br/dica/Utilizando-arrays-em-shell-script
http://lendscripts.blogspot.com.br/
http://victor-dba.blogspot.com.br/2012/02/10-dicas-para-programar-em-shell-script.html