Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
Ambos lados da revisão anterior Revisão anterior Próxima revisão | Revisão anterior | ||
unix:shell_scripts [2023/10/26 18:25] – [Condições] maziero | unix:shell_scripts [2023/11/23 18:33] (atual) – maziero | ||
---|---|---|---|
Linha 1: | Linha 1: | ||
+ | ====== UNIX: Shell scripts ====== | ||
+ | |||
+ | ===== Estrutura geral de um script ===== | ||
+ | |||
+ | Os arquivos de script permitem construir esquemas de execução complexos a partir dos comandos básicos do shell. A forma mais elementar de arquivo de script é apenas um conjunto de comandos em um arquivo texto, com permissões de execução habilitadas. O arquivo '' | ||
+ | |||
+ | <code bash backup.sh> | ||
+ | echo " | ||
+ | |||
+ | # montar o diretório do servidor de backup | ||
+ | mount fileserver.ufpr.br:/ | ||
+ | |||
+ | # efetuar o backup em um arquivo tar compactado | ||
+ | tar czf / | ||
+ | |||
+ | # desmontar o diretório do servidor de backup | ||
+ | umount /backup | ||
+ | |||
+ | echo " | ||
+ | </ | ||
+ | |||
+ | Quando o script backup for executado, os comandos do arquivo serão executados em sequência pelo shell corrente (de onde ele foi lançado). Assim, se o usuário estiver usando o shell bash, os comandos do script serão executados por esse shell. Como isso poderia gerar problemas em scripts usados por vários usuários, é possível forçar a execução do script com um shell específico (ou outro programa que interprete os comandos do arquivo). Para isso é necessário informar ao sistema operacional o programa a ser usado, na primeira linha do arquivo do script: | ||
+ | |||
+ | <code bash backup.sh> | ||
+ | #!/bin/bash --noprofile | ||
+ | |||
+ | # A opção --noprofile inibe a leitura dos arquivos de inicialização | ||
+ | # do shell, tornando o lançamento do script muito mais rápido. | ||
+ | # comandos de um script em Bash-Shell | ||
+ | |||
+ | server=fileserver.ufpr.br | ||
+ | backdir=/ | ||
+ | ... | ||
+ | exit 0 | ||
+ | </ | ||
+ | |||
+ | Com isso, será lançado um shell Bash separado (um novo processo), somente para interpretar as instruções do script. O novo processo será terminado pelo comando '' | ||
+ | |||
+ | <note tip> | ||
+ | Embora não seja obrigatório, | ||
+ | </ | ||
+ | |||
+ | ===== Parâmetros de entrada ===== | ||
+ | |||
+ | Os argumentos da linha de comando são passados para o shell através da variável local '' | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Eis um exemplo através do script '' | ||
+ | |||
+ | <code bash listaparams.sh> | ||
+ | # | ||
+ | # exemplo de uso dos parâmetros de entrada | ||
+ | echo "Nome do script : $0" | ||
+ | echo " | ||
+ | echo "Todos os parâmetros : $*" | ||
+ | echo " | ||
+ | echo " | ||
+ | exit 0 | ||
+ | </ | ||
+ | |||
+ | Chamando o script acima com alguns parâmetros se obtém a seguinte resposta: | ||
+ | |||
+ | < | ||
+ | $ listaparams.sh banana tomate pessego melao pera uva | ||
+ | Nome do script : listaparams | ||
+ | Primeiro parâmetro : banana | ||
+ | Todos os parâmetros : banana tomate pessego melao pera uva | ||
+ | Numero de parametros : 6 | ||
+ | Numero deste processo : 2215 | ||
+ | </ | ||
+ | |||
+ | ===== Controle de fluxo ===== | ||
+ | |||
+ | Existem diversos construtores de controle de fluxo que podem ser usados em scripts BASH. Os principais são descritos a seguir. | ||
+ | |||
+ | ==== Condições ==== | ||
+ | |||
+ | Como na maioria das linguagens, no shell Bash, testes de condições são realizados por estruturas do tipo // | ||
+ | |||
+ | <code bash> | ||
+ | if cmp $file1 $file2 >/ | ||
+ | then | ||
+ | echo "os arquivos são iguais" | ||
+ | else | ||
+ | echo "os arquivos são distintos" | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | Essa lógica "ao contrário" | ||
+ | |||
+ | <code bash> | ||
+ | if test $n1 -lt $n2 # $n1 é menor que $n2? | ||
+ | then | ||
+ | echo "$n1 é menor que $n2" | ||
+ | fi | ||
+ | |||
+ | # ou | ||
+ | |||
+ | if [ $n1 -lt $n2 ] # $n1 é menor que $n2? | ||
+ | then | ||
+ | echo "$n1 é menor que $n2" | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | Os principais operadores de teste disponíveis são: | ||
+ | |||
+ | Operador //if-then// | ||
+ | <code bash> | ||
+ | if comando | ||
+ | then | ||
+ | | ||
+ | fi | ||
+ | |||
+ | # testa o status do comando cmp | ||
+ | if cmp file1 file2 >/ | ||
+ | then | ||
+ | echo "Os arquivos são iguais" | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | Operador // | ||
+ | |||
+ | <code bash> | ||
+ | if comando | ||
+ | then | ||
+ | | ||
+ | else | ||
+ | ... | ||
+ | fi | ||
+ | |||
+ | # testa a existência de $file1 | ||
+ | if [ -e " | ||
+ | then | ||
+ | echo " | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | Operador // | ||
+ | |||
+ | <code bash> | ||
+ | if comando 1 | ||
+ | then | ||
+ | ... | ||
+ | elif comando 2 | ||
+ | then | ||
+ | ... | ||
+ | else | ||
+ | ... | ||
+ | fi | ||
+ | |||
+ | # compara as variáveis $n1 e $n2 | ||
+ | if [ $n1 -lt $n2 ] | ||
+ | then | ||
+ | echo "$n1 < $n2" | ||
+ | elif [ $n1 -gt $n2 ] | ||
+ | then | ||
+ | echo "$n1 > $n2" | ||
+ | else | ||
+ | echo "$n1 = $n2" | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | Operador //case// | ||
+ | |||
+ | <code bash> | ||
+ | case variável in | ||
+ | " | ||
+ | ... | ||
+ | break;; | ||
+ | " | ||
+ | ... | ||
+ | break;; | ||
+ | | ||
+ | ... | ||
+ | break;; | ||
+ | esac | ||
+ | |||
+ | case $opt in | ||
+ | " | ||
+ | | ||
+ | " | ||
+ | | ||
+ | | ||
+ | *) | ||
+ | echo " | ||
+ | exit 1 ;; | ||
+ | esac | ||
+ | </ | ||
+ | |||
+ | Os principais tipos de teste disponíveis são: | ||
+ | |||
+ | * Comparações entre números | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * Comparações entre strings usando '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * Comparações entre strings usando ''< | ||
+ | * ''< | ||
+ | * ''> | ||
+ | * Associações entre condições | ||
+ | * ''&&'' | ||
+ | * '' | ||
+ | |||
+ | Os operadores de teste em arquivos permitem verificar propriedades de entradas no sistema de arquivos. Eles são usados na forma '''' | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | Eis um exemplo de uso de testes em arquivos: | ||
+ | |||
+ | <code bash> | ||
+ | arquivo='/ | ||
+ | |||
+ | if [ -e $arquivo ] | ||
+ | then | ||
+ | if [ -f $arquivo ] | ||
+ | | ||
+ | if [ -r $arquivo ] | ||
+ | then | ||
+ | | ||
+ | else | ||
+ | echo "Nao posso ler o arquivo $arquivo" | ||
+ | fi | ||
+ | | ||
+ | echo " | ||
+ | | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | ==== Laços ==== | ||
+ | |||
+ | Laço //for// | ||
+ | |||
+ | <code bash> | ||
+ | for variável in lista de valores | ||
+ | do | ||
+ | | ||
+ | done | ||
+ | |||
+ | for i in *.c | ||
+ | do | ||
+ | echo " | ||
+ | cc -c $i | ||
+ | done | ||
+ | </ | ||
+ | |||
+ | Laço //while// | ||
+ | |||
+ | <code bash> | ||
+ | while condição | ||
+ | do | ||
+ | | ||
+ | done | ||
+ | |||
+ | i=0 | ||
+ | while [ $i -lt 10 ] | ||
+ | do | ||
+ | echo $i | ||
+ | let i++ | ||
+ | done | ||
+ | </ | ||
+ | |||
+ | Operador //select// | ||
+ | |||
+ | <code bash> | ||
+ | select variável in lista de valores | ||
+ | do | ||
+ | ... | ||
+ | done | ||
+ | |||
+ | select f in " | ||
+ | do | ||
+ | echo " | ||
+ | done | ||
+ | </ | ||
+ | |||
+ | Além das estruturas acima, algumas outras podem ser usadas para executar comandos em situações específicas: | ||
+ | |||
+ | * '' | ||
+ | |||
+ | <code bash> | ||
+ | arqs=`find /etc -type f -iname '???' | ||
+ | </ | ||
+ | |||
+ | * '' | ||
+ | |||
+ | |||
+ | ===== Operadores aritméticos ===== | ||
+ | |||
+ | Variáveis contendo números inteiros podem ser usadas em expressões aritméticas e lógicas. A atribuição do resultado de uma expressão aritmética a uma variável pode ser feita de diversas formas. Por exemplo, as três expressões a seguir têm o mesmo efeito: | ||
+ | |||
+ | <code bash> | ||
+ | i=$((j + k)) | ||
+ | |||
+ | let i=j+k | ||
+ | |||
+ | i=`expr $j + $k` | ||
+ | </ | ||
+ | |||
+ | Os principais operadores aritméticos disponíveis são: | ||
+ | |||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * ''<< | ||
+ | * ''<< | ||
+ | * ''& | ||
+ | * ''& | ||
+ | * '' | ||
+ | * '' | ||
+ | * ''&& | ||
+ | |||
+ | |||
+ | ===== Exercícios ===== | ||
+ | |||
+ | - Analise e descreva o que faz o script abaixo, passo a passo. Em seguida, copie-o no arquivo '' | ||
+ | #!/bin/bash --noprofile | ||
+ | | ||
+ | # testar se ha um so parametro de entrada | ||
+ | if [ $# != 1 ] | ||
+ | then | ||
+ | echo '' | ||
+ | echo '' | ||
+ | exit 1 | ||
+ | fi | ||
+ | | ||
+ | num=0 | ||
+ | | ||
+ | while [ $num -lt $1 ] | ||
+ | do | ||
+ | echo '' | ||
+ | mkdir dir$num | ||
+ | let num++ | ||
+ | done | ||
+ | | ||
+ | echo '' | ||
+ | |||
+ | exit 0 | ||
+ | </ | ||
+ | - Escreva um script chamado '' | ||
+ | - Escreva um script para criar diretórios com nome '' | ||
+ | - Escreva um conjunto de scripts para gerenciar o apagamento de arquivos. O script '' | ||
+ | - Funda os scripts do exercício anterior em um só script '' | ||
+ | - Escreva um script para verificar quais hosts de uma determinada rede IP estão ativos. Para testar se um host está ativo, use o comando '' | ||
+ | - Escreva um script que recebe o nome de um arquivo como parâmetro e o copia para o diretório ''/ | ||
+ | - Escreva um script que recebe 2 parâmetros. O primeiro é um diretório e o segundo um arquivo. O script deve mover o arquivo para o diretório. | ||
+ | - Escreva um script que utiliza o comando '' | ||
+ | - Veja o que faz o script abaixo: <code bash> | ||
+ | for i in *; do echo $i; done | ||
+ | </ | ||
+ | - Modifique o script acima para listar os atributos de todos os arquivos. | ||
+ | - Implemente o script abaixo passo a passo e descubra o que faz cada comando: <code bash> | ||
+ | #!/bin/bash | ||
+ | set -x | ||
+ | |||
+ | temph=`date | cut -c13-14` | ||
+ | dat=`date +"%A %d de %B de %Y (%r)"` | ||
+ | |||
+ | if [ $temph -lt 12 ]; then | ||
+ | | ||
+ | elif [ $temph -gt 12 -a $temph -le 18 ]; then | ||
+ | | ||
+ | elif [ $temph -gt 18 ]; then | ||
+ | | ||
+ | fi | ||
+ | echo -e " | ||
+ | </ | ||
+ | - Implemente o script abaixo passo a passo e descubra o que faz cada comando: <code bash> | ||
+ | #!/bin/bash | ||
+ | #set -x | ||
+ | |||
+ | # Esse script fornece informacoes sobre um arquivo. | ||
+ | |||
+ | FILENAME=" | ||
+ | |||
+ | echo " | ||
+ | |||
+ | if [ -f $FILENAME ]; then | ||
+ | echo " | ||
+ | echo "Tipo: $(file $FILENAME | cut -d":" | ||
+ | echo " | ||
+ | echo "$(df -h $FILENAME | grep -v Mounted | awk '{ print " | ||
+ | que esta montado como particao ", | ||
+ | else | ||
+ | echo " | ||
+ | fi | ||
+ | </ | ||
+ | - Escreva um script de backup que salve uma cópia de um diretório em outro diretório. O script deve verificar se ambos diretórios existem e criar o destino caso não exista. O nome do arquivo de backup deve conter a palavra “manha”, | ||
+ | - Escreva um script que pergunte a idade do usuário. Caso ele tenha mais que 18 anos, imprima uma mensagem informando que ele está autorizado a beber álcool. Caso ele tenha menos que 18 anos, informe-o quantos anos terá que aguardar até poder beber. | ||
+ | * Adicionalmente, | ||
+ | - Escreva um script que encontra todos arquivos com determinada extensão em um determinado diretório e, baseado nos parâmetros enviados, faça cópias dos arquivos com uma nova extensão, renomeie os arquivos para uma nova extensão, ou remova os arquivos. O script terá quatro parâmetros (três em caso de remoção): < | ||
+ | diretorio [ -c | -m | -r ] ext1 ext2 | ||
+ | </ | ||
+ | nome antigo => nome novo | ||
+ | </ | ||