Férias + TCC

Finalmente consegui pegar 2 semanas de folga do trabalho, pena não poder folgar de verdade como gostaria, pois estou aproveitando para finalizar o meu artigo de TCC. E a versão final deve ser entregue na próxima segunda-feira, espero que corra tudo bem 🙂

Por ora essa é a vista que me acompanha nesses dias:
Ambiente de testes de HA

Anúncios

bkp.sh

Especificação do trabalho:

TRABALHO DE SHELL SCRIPTS
GRUPO DE TRABALHO
Trabalho grupo de três alunos.

       DESCRIÇÃO
       =========

Implementar um sistema de gerenciamento de backup.
O sistema consiste em um arquivo de configuraço (/etc/bkp.conf) e um
arquivo de shell script (/usr/local/bin/bkp.sh).
O arquivo de shell script deverá ser dividido em funções que executam
atividades especificas, esta divisão ficará sob a responsabilidade da
equipe.
Não será aceito scripts que sejam escritos em um único módulo (lingüiça).
O script deverá ler o arquivo de configuração configuração e iniciar a
execução do backup.
O script deverá ser agendado via crontab (o horário de execução será
agendado no momento da defesa).
Somente arquivos que foram modificados a menos de 24 horas ser
selecionados pela operação de backup (além de obedecerem a extensão
definido pelo usuário).
O shell deverá executar as seguintes funções:
* ler arquivo de configuração
* validar cada usuario
* realizar o backup
* limpar arquivos de backup que estão além do período de retenção

Cada sessão de backup deverá gerar um arquivo no formato:

   usuario.DDMMAA.HHMM.tar.gz

       ARQUIVO DE CONFIGURAÇÃO
       =======================

 usuário:frequencia:retenço:extenses:caminho

* usuário - usuário cadastrado no arquivo /etc/passwd
* frequencia - frequencia com que o backup é realizado.Os valores estão
 padronizados em
 1 (domingo), 2 (segunda), 3(terça), 4(quarta), 5(quinta), 6(sexta),
 7(sábado), *(todos os dias).
 Se o usuário quiser backup todos os dias ento será informado (*).
 Um intervalo pode ser defindo através de um traço, 24, corresponde aos
 dias segunda,terça e quarta. * retenço ­ define quantos dias o backup será
 retido, ultrapassado o número de dias o backup deverá ser excluído.
 O valor padronizado é de 1-15.
* extensão - Indica o padrão dos arquivos que devem ser copiados.
* caminho ­ indica o caminho onde o backup deve ser armazenado.
 Exemplo: /var/bkp.

       EXEMPLOS
       ========

Exemplo 1 - O usuário airton que fazer backup com a seguinte frequencia
segunda, quarta e sexta. Todos arquivos que pertencem a ele deverão ser
copiados na operaço de backup. É necessitar que os backups fiquem
armazenados na pasta /var/backup/airton com 4 dias de retenção.

       airton:2,4,6:4:*:/var/backup/airton

Exemplo 2 -Idem acima, porém a frequencia do backup deve ser todos os dias.

       Airton:*:4:*:/var/backup/airton

Exemplo 3 - O usuário airton que fazer backup com a seguinte frequencia
segunda,terça,quarta,quinta. Somente os arquivos que possuam o padro *.c,
*.doc e *.txt deverão ser copiados na operação de backup. É necessitar que os
backups fiquem armazenados na pasta /var/backup/airton com 4 dias de
retenção.

       Airton:2-5:4:*.c,*.doc,*.txt:/var/backup/airton

Se o usuário quiser backup segunda, quarta e sexta então será informado
2,4,6. Se o usuário quiser backup segunda,terça,quarta e quinta então
podemos utilizar 2-5.

       PREMISSAS DO TRABALHO
       =====================

* O arquivo de configuração deve ser editado através de um editor de texto
* O arquivo de configuração deve estar permanentemente ordenado pela
 primeira coluna, isto é, o nome do usuário.
* O caracter separador de campo é (:)
* Utilizar as aplicações tar e find para realizar o backup
* Utilizar o para cron disparar o backup

Script implementado:

#!/bin/bash
# vim:ts=8
#=====================================================================
#       ARQUIVO:  bkp.sh
#           USO:  bkp.sh
#     DESCRIÇÃO:  Script para gerenciamento de backup
#        OPÇÕES:  ---
#    REQUISITOS:  /etc/bkp.conf
#                 bash >= 2.04
#                 tar
#                 gzip
#                 mktemp
#          BUGS:  ---
#         NOTAS:
#       AUTORIA:  Marcelo Beckmann,
#                 Rubens Hilcko, 
#                 Fabrício Carrico
#        VERSÃO:  1.0
#       REVISÃO:  6
#=====================================================================

#=====================================================================
# 			Variáveis globais
#=====================================================================
# Arquivo de configuração
BKPCONF="/etc/bkp.conf"

# Arquivo de log do backup
LOGFILE="/tmp/logbkp.log"

# Variável para controlar log de mensagens de debug
# Setar para 1 para gerar mensagens de debug
DEBUG=0

#=====================================================================
# 			Declaração de funções
#=====================================================================
# Função para logar mensagens no arquivo de log
# Mensagem a ser logada é passada como parâmetro para a função
loga() {
	# Variável local para gerar padrão de data-hora no log
	local DATALOGPATTERN=`date +"%Y%m%d-%H:%M:%S"`
	echo "${DATALOGPATTERN} ${@}" >>${LOGFILE}
}

# Função para manter ordenado o arquivo de configuração (BKPCONF)
# Além de ordenar, também limpa linhas em branco e com comentários
ordena_conf() {
	# Testa se o arquivo de configuração BKPCONF existe e se é
	# possível abri-lo. Se não conseguir, aborta e loga o erro
	if [ ! -w ${BKPCONF} ]
	then
		loga "  ==> ERRO: Arquivo de configuração não pode ser lido"
		return 1
	fi
	# Cria arquivo temporário para reordenação
	local TMPFILE=`mktemp /tmp/bkp.sh-XXXXXX`
	# Remove linhas em branco ou com comentários (egrep -v)
	# Ordena arquivo pelo primeiro campo (sort -k1)
	# Remove espaços em branco (sed)
	cat ${BKPCONF} | egrep -v "(^$|^#)" | sort -k 1 -t : | sed -e 's, ,,g' >${TMPFILE}
	# Reescreve arquivo de configuração
	cat ${TMPFILE} >${BKPCONF}
	# Apaga arquivo temporário
	rm ${TMPFILE}
	return 0
}

# Função para logar mensagens em modo debug
# Mensagem a ser logada é passada como parâmetro
ifdebug() {
	# Testa se variável DEBUG está definida
        if [ ! -z "${DEBUG}" ]
	then
		# Testa se debug está ativo (DEBUG=1)
		if [ ${DEBUG} -eq 1 ]
		then
			loga "  DEBUG: ${@}"
		fi
	fi
}

# Obtem código numérico do dia de hoje pelo função date
# Código deve ser:
# 1 (domingo), 2 (segunda), 3(terça), 4(quarta), 5(quinta), 6(sexta),
# 7 (sábado)
dia_sem_hoje() {
	# Utilizada opção %w do date:
	# %w     day of week (0..6); 0 is Sunday
	local DIASEM=`date +"%w"`
	# O date considera Domingo = 0
	# Precisamos somar 1 para ajustar isso a nossa codificação
	BKPDIAHOJE=$[${DIASEM}+1]
}

#=====================================================================
# 	Funções de validação do arquivo de configuração
#
# * Validam cada campo do arquivo de configuração
# * Obtém os valores para as variáveis necessárias para o backup
# * Variável line corresponde a linha atual lida do arquvio de config
# * Valores de retorno:
#	0 ==> OK
#	1 ==> ERRO
#=====================================================================

# Conta quantos separadores de campo (:) há na linha
# Usa o sed para trocar o ":"  por quebras de linha, e usa o wc -l para
# contar quantas linhas resultam. Assim, obtém-se o número de ":"
# Se não tiver exatamente 4 ":", rejeita a linha (linha inválida)
valida_ncampos() {
	if [ `echo -n "${line}" | sed -e 's,:,\n,g' | wc -l` -eq 4 ]
	then
		# total de campos ok
		return 0
	else
		loga "  ==> ERRO: Quantidade de campos (:) inválida"
		return 1
	fi
}

# Testa se o usuário existe no sistema
# Obtém as variáveis:
# BKPHOME: o diretório HOME do usuário
# BKPUSUARIO: nome do usuário
valida_usuario() {
	# Obtém nome do usuário da linha do arquivo de configuração bkp.conf
	BKPUSUARIO=`echo "${line}" | cut -d: -f1`
	# Testa se o usuário existe no /etc/passwd
	if cat /etc/passwd | cut -d: -f1 | grep -w -q ${BKPUSUARIO}
	then
		# Ok, usuário existe no sistema
		# Obtém diretório home do usuário
		BKPHOME="`cut -d: -f1,6 /etc/passwd | egrep -w "^${BKPUSUARIO}" | cut -d: -f2`"
		return 0
	else
		# Erro, usuário não existe no /etc/passwd
		loga "  ==> ERRO: Usuário ${BKPUSUARIO} não existe no sistema"
		return 1
	fi
}

# Valida se o campo de frequencia está bem formatado
# Obtém a variável string BKPFREQ com os dias de backup
# Exemplo: se tivermos a programação 2-5, então BKPFREQ="2345"
valida_frequencia() {
	# Obtém o campo de frequencia (campo 2 da linha de config)
	local TMPFREQ="`echo "${line}" | cut -d: -f2`"
	# Por segurança, apaga valores anteriores de BKPFREQ
	unset BKPFREQ

	# Utiliza expressões regulares para validar o campo
	# usa echo e egrep para verificar casamento com a expressão
	# O campo pode ser:
	# Apenas um *
	if echo "${TMPFREQ}" | egrep -q "^\*$"
	then
		# Seta string de frequencia para todos os dias
		BKPFREQ="1234567"
		ifdebug "valida_frequencia - casou asterisco"
		ifdebug "BKPFREQ=${BKPFREQ}"
		return 0
	fi
	# O campo pode ser:
	# Apenas um número, no intervalo de 1 a 7
	if echo "${TMPFREQ}" | egrep -q "^[1-7]$"
	then
		# Seta string de frequencia apenas para o dia
		BKPFREQ="${TMPFREQ}"
		ifdebug "valida_frequencia - casou um único número"
		ifdebug "BKPFREQ=${BKPFREQ}"
		return 0
	fi
	# O campo pode ser:
	# Um número [1-7], seguido de um - e um número [1-7]
	# ex.: 2-5
	if echo "${TMPFREQ}" | egrep -q "^[1-7]-[1-7]$"
	then
		# Campo é no formato DIAINICIAL-DIAFINAL
		# Variáveis temporárias para obter dia inicio e dia fim
		local TMPFREQ1=`echo "${TMPFREQ}" | cut -d- -f1`
		local TMPFREQ2=`echo "${TMPFREQ}" | cut -d- -f2`
		# condição inválida, dia inicial maior ou igual ao dia final
		if [ ${TMPFREQ1} -ge ${TMPFREQ2} ]
		then
			loga "  ==> ERRO: Dia inicial ${TMPFREQ1} maior ou igual a dia final ${TMPFREQ2}"
			return 1
		fi
		# Preenche string de frequencia com os dias do intervalo
		for local1 in `seq ${TMPFREQ1} ${TMPFREQ2}`
		do
			BKPFREQ="${BKPFREQ}${local1}"
		done
		ifdebug "valida_frequencia - casou inicio-fim"
		ifdebug "BKPFREQ=${BKPFREQ}"
		return 0
	fi
	# O campo pode ser:
	# Um número [1-7], seguido uma ou mais vezes de
	# uma , e um número [1-7]
	# ex.: 2,4,5
	if echo "${TMPFREQ}" | egrep -q "^[1-7](,[1-7])+$"
	then
		BKPFREQ="`echo "${TMPFREQ}" | sed -e 's/,//g'`"
		ifdebug "valida_frequencia - casou numero[,numero]+"
		ifdebug "BKPFREQ=${BKPFREQ}"
		return 0
	fi
	# Se chegou até aqui e não casou com nenhum dos casos possíveis
	# Então há alguma inconsistência na configuração desta opção
	# retorna erro
	loga "  ==> ERRO: campo frequencia mal especificado"
	return 1
}

# Valida se o campo retenção está entre 1 e 15
# Obtém a variável BKPRET: número de dias para retenção
valida_retencao() {
	# Obtém o campo de retenção (campo 3 da linha de config)
	local TMPRET="`echo "${line}" | cut -d: -f3`"
	# Utiliza expressão regular para validar se é
	# um número [1-9] seguido 0 ou 1 vez de
	# um número [0-5]
	if echo "${TMPRET}" | egrep -q "^[1-9][0-5]?$"
	then
		# Ok, casou com a expressão regular, portanto é um número
		# Teste para ver se está entre 1 e 15
		if [ ${TMPRET} -ge 1 -a ${TMPRET} -le 15 ]
		then
			# Valor de retenção válido!
			BKPRET=${TMPRET}
			ifdebug "BKPRET=${BKPRET}"
			return 0
		else
			loga "  ==> ERRO: Valor de retenção (${BKPRET}) fora da faixa permitida (1-15)"
			return 1
		fi
	else
		# Se não casou com a regex, então campo retenção
		# está mal especificado
		loga "  ==> ERRO: campo retenção mal especificado"
		return 1
	fi
}

# Função para processar a lista de extensões
# Obtem a string BKPEXT com a lista de extensões separadas por espaços
valida_extensoes() {
	# este campo pode ter apenas uma única extensão (ou *)
	# ou pode ter mais de uma extensão separadas por ,
	# podemos simplesmente aplicar um sed para substituir as
	# possíveis virgulas por espaços e jogar numa variável
	# a qual será usada depois em um loop com tar + find

	# Obtém campo 4 da linha de config, e troca "," por " "
	BKPEXT="`echo "${line}" | cut -d: -f4 | sed -e 's/,/ /g'`"
	ifdebug "BKPEXT=${BKPEXT}"
	return 0
}

# Valida o caminho no qual será salvo o backup
valida_caminho() {
	# Obtém o campo do caminho (campo 5 da linha de config)
	BKPPATH="`echo "${line}" | cut -d: -f5`"
	ifdebug "BKPPATH=${BKPPATH}"
	# Testa se o caminho já existe e se é um diretório
	if [ -d ${BKPPATH} ]
	then
		return 0
	else
		# Tenta criar o diretório
		mkdir -p ${BKPPATH}
		if [ $? -eq 0 ]
		then
			# OK, conseguiu criar
			return 0
		else
			# ERRO, não conseguiu criar
			loga "  ==> ERRO: Impossível criar caminho ${BKPPATH}"
			return 1
		fi
	fi
}

# Função para validar a linha lida do arquivo de configuração
# Usa várias outras funções para fazer testes específicos
# Formato padrão da linha do arquivo de configuração:
# usuário:frequencia:retenção:extensões:caminho
# Valores de retorno:
# 	0 ==> Ok, arquivo validado e campos necessários obtidos
# 	1 ==> Alguma verficação de validade falhou
valida_linha() {
	# Valida quantidade de separadores de campo (:) da linha
	valida_ncampos || return 1
	# Valida se o usuário existe no sistema
	valida_usuario || return 1
	# Valida campo de frequencia
	valida_frequencia || return 1
	# Valida campo de retenção
	valida_retencao || return 1
	# Valida campo de extensões
	valida_extensoes || return 1
	# Valida campo do caminho
	valida_caminho || return 1
	# Se chegou até aqui, então a linha de configuração é válida
	# gera log com os parâmetros encontrados
	ifdebug "Linha de configuração validada!"
	loga "  Parâmetros encontrados para o backup:"
	loga "   Usuário (BKPUSUARIO): ${BKPUSUARIO}"
	loga "    Dir Home do usuário: ${BKPHOME}"
	loga "   Frequencia (BKPFREQ): ${BKPFREQ}"
	loga "      Retenção (BKPRET): ${BKPRET}"
	loga "     Extensões (BKPEXT): ${BKPEXT}"
	loga "      Caminho (BKPPATH): ${BKPPATH}"
	return 0
}

# Testa se no dia de hoje deve ser feito backup
# Verifica se o código do dia atual consta na string com os dias agendados
# Valores de retorno:
#	0 ==> OK, deve fazer backup hoje
#	1 ==> não deve fazer backup hoje
valida_bkp_hoje() {
	if echo "${BKPFREQ}" | grep -q ${BKPDIAHOJE}
	then
		return 0
	else
		return 1
	fi
}

# Gera nome de arquivo no formato padronizado para o backup:
# usuario.DDMMAA.HHMM.tar.gz
gera_nomes() {
	# Gera um padrão de data e hora com o comando date
	local DATATARPATTERN="`date +"%d%m%y.%H%M"`"
	# Nomeia arquivo para o tar.gz
	BKPTARGZ="${BKPPATH}/${BKPUSUARIO}.${DATATARPATTERN}.tar.gz"
	# Nomeia arquivo que conterá a lista de arquivos para backup
	BKPLIST="${BKPPATH}/${BKPUSUARIO}.${DATATARPATTERN}.lst"
	# Se já existir os arquivos, apaga
	[ -f ${BKPTARGZ} ] && rm ${BKPTARGZ}
	[ -f ${BKPLIST} ] && rm ${BKPLIST}
}

#=====================================================================
# 		Início do processamento
#=====================================================================
loga "=========================="
loga "Iniciando sessão de backup"

# Obtém codigo numérico do dia da semana
dia_sem_hoje
loga "Dia da semana atual: ${BKPDIAHOJE}"

# Cria diretório temporário de trabalho
# Para prevenir expansão de *.ext caso haja algum *.ext no diretório atual
WORKDIR=`mktemp -d /tmp/bkp.sh-dir-XXXXXX`
cd ${WORKDIR}

# Ordena arquivo de configuração
loga "Ordenando arquivo de configuração"
if ! ordena_conf
then
	# Arquivo de configuração não pode ser lido ou gravado, aborta
	loga "Abortando backup"
	loga "--------------------------------"
	exit 1
fi

# Loop para processar linha a linha do arquivo de configuração
loga "Iniciando processamento do arquivo de configuração"

# Inicializa contador de linhas processadas
NLINHA="0"
for line in `cat ${BKPCONF}`
do
	# Leu uma linha, então incrementa contador de linhas
	NLINHA=$[${NLINHA}+1]
	loga "Iniciando processamento linha ${NLINHA}:"
	loga "${line}"
	# Valida linha lida do arquivo de configuração
	# Se a linha for inválida por algum motivo, pula o processamento
	# para a próxima linha
	if ! valida_linha
	then
		loga "--------------------------------"
		continue
	fi

	# Ok, arquivo validado
	#
	# Processa retenções
	# Apaga arquivos mais antigos que BKPRET dias
	loga "  ==> Removendo retenções mais antigas que ${BKPRET} dias"
	find ${BKPPATH} -type f -mtime +${BKPRET} -name ${BKPUSUARIO}.* -exec rm -v {} \; >> ${LOGFILE} 2>/dev/null
	if [ $? -ne 0 ]
	then
		loga "  ==> ERRO"
	fi

	# Testa se deve executar backup hoje
	if ! valida_bkp_hoje
	then
		loga "  ==> Dia de hoje (${BKPDIAHOJE}) não coincide com agendamento (${BKPFREQ})"
		loga "--------------------------------"
		continue
	fi

	# Ok, fará backup hoje
	# Gera nomes de arquivos para efetuar o backup
	gera_nomes
	loga "  ====> gerando ${BKPLIST}"

	# Processa extensões para montar arquivo de listagem
	for exten in ${BKPEXT}
	do
		loga "  ======> ${exten}"
		# Somente arquivos que foram modificados a menos de 24 horas
		# ser selecionados pela operação de backup (além de obedecerem
		# a extensão definido pelo usuário).
		# Para pegar apenas os modificados a menos de 24h, usamos
		# a opção "-mtime -1" do find
		find ${BKPHOME} -type f -mtime -1 -name ${exten} >> ${BKPLIST}
		# Gera log com quantidade de arquivos encontrados
		loga "  ======> [`wc -l ${BKPLIST} | cut -d" " -f1`] arquivos selecionados"
	done

	# Verifica se foi selecionado algum arquivo para backup
	# checando o número de linhas de BKPLIST
	if [ `wc -l ${BKPLIST} | cut -d" " -f1` -eq 0 ]
	then
		rm ${BKPLIST}
		loga "  ====> Nenhum arquivo selecionado para backup"
		loga "--------------------------------"
		continue
	fi

	# Se passou pela verificação anterior, então existem arquivos
	# selecionados para backup
	# Executa o backup em tar.gz
	loga "  ====> gerando ${BKPTARGZ}"
	# Faz o tar lendo a lista de arquivos gerada previamente
	tar -T ${BKPLIST} -czf ${BKPTARGZ} >/dev/null 2>&1
	if [ $? -eq 0 ]
	then
		# Sucesso na execução do tar
		# Apaga lista
		rm ${BKPLIST}
		loga "  ==> Backup executado com sucesso!"
	else
		# Houve algum problema
		loga "  ==> ERRO na geração de ${BKPTARGZ}"
	fi
	# Gera linha no log para sinalizar fim do processamento da linha
	loga "--------------------------------"
done

# Apaga diretório temporário
cd /tmp
rm -Rf ${WORKDIR}

loga "Terminando processamento do arquivo de configuração"
loga "Terminando sessão de backup"
loga "==========================="

Redirect Host(New nexthop: …)

Neste link temos um texto que explica a mensagem ICMP de redirect.

Trecho que interessa, traduzido:
====
É hora de um exemplo mais complexo. Vamos adicionar um gateway para um destino o qual na verdade está diretamente conectado:

netadm@alisa:~ # ip route add 193.233.7.98 via 193.233.7.254
netadm@alisa:~ # ip route get 193.233.7.98
193.233.7.98 via 193.233.7.254 dev eth0 src 193.233.7.90
cache mtu 1500 rtt 3072
netadm@alisa:~ #

e testamos com o ping:

netadm@alisa:~ # ping -n 193.233.7.98
PING 193.233.7.98 (193.233.7.98) from 193.233.7.90 : 56 data bytes
>From 193.233.7.254: Redirect Host(New nexthop: 193.233.7.98)
64 bytes from 193.233.7.98: icmp_seq=0 ttl=255 time=3.5 ms
>From 193.233.7.254: Redirect Host(New nexthop: 193.233.7.98)
64 bytes from 193.233.7.98: icmp_seq=1 ttl=255 time=2.2 ms
64 bytes from 193.233.7.98: icmp_seq=2 ttl=255 time=0.4 ms
64 bytes from 193.233.7.98: icmp_seq=3 ttl=255 time=0.4 ms
64 bytes from 193.233.7.98: icmp_seq=4 ttl=255 time=0.4 ms
^C
--- 193.233.7.98 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 0.4/1.3/3.5 ms
netadm@alisa:~ #

O que aconteceu? O roteador 193.233.7.254 entendeu que nós temos um caminho melhor para o destino e enviou uma mensagem ICMP de redirecionamento (redirect). Podemos usar novamente “ip route get” para ver o que temos na tabela de roteamento agora:

netadm@alisa:~ # ip route get 193.233.7.98
193.233.7.98 dev eth0 src 193.233.7.90
cache mtu 1500 rtt 3072
netadm@alisa:~ #

====

É possível, ainda, evitar a geração desse tipo de mensagem:

echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects

owl

Algum tempo atrás tinha visto um link com livros na lista do freebsd:
https://feradsl.cjb.net/owl-0.90/browse.php

Achei interessante a interface.
Mais além, nas aulas de comunicação de dados corporativa das
sextas-feiras, entramos no tema de web 2.0, web semântica, xml, owl,
rdf… nisso lembrei do link, e achei a página do Owl

http://owl.sourceforge.net/

What is Owl?
Owl is a multi user document repository (knowledgebase) system written
in PHP4 for publishing files/documents onto the web for a corporation,
small business, group of people, or just for yourself.

mtr

DESCRIPTION
mtr combines the functionality of the traceroute and ping programs in a
single network diagnostic tool.

As mtr starts, it investigates the network connection between the host
mtr runs on and HOSTNAME. by sending packets with purposly low TTLs.
It continues to send packets with low TTL, noting the response time of
the intervening routers. This allows mtr to print the response per-
centage and response times of the internet route to HOSTNAME. A sudden
increase in packetloss or response time is often an indication of a bad
(or simply overloaded) link.

prova de hoje

#!/bin/bash

echo "início"

while /bin/true
do
        echo "--------"
        echo "Valor de A: "
        read A
        if [ $A -eq 0 ] ; then
                echo "Fim de programa"
                exit
        fi
        echo "Valor de B: "
        read B
        echo "Valor de C: "
        read C
        # rejeita se for string nula
        if [ -z "$A" -o -z "$B" -o -z "$C" ] ; then
                echo "Valor inválido, nulo"
                continue
        fi
        # rejeita se valores forem iguais
        if [ $A -eq $B -a $B -eq $C ] ; then
                echo "Valores iguais não permitidos"
                continue
        fi
        # ordena
        if [ $B -gt $A ] ; then
                SWAP=$A
                A=$B
                B=$SWAP
        fi
        if [ $C -gt $B ] ; then
                SWAP=$B
                B=$C
                C=$SWAP
        fi
        if [ $B -gt $A ] ; then
                SWAP=$A
                A=$B
                B=$SWAP
        fi

        echo "Valores ordenados"
        echo "A: $A"
        echo "B: $B"
        echo "C: $C"
        echo "--------"
done

lab de redes

Excelente a aula de hoje. Protocolos ppp, x25, hdlc, lcp, ncp, cdp, configuração dos roteadores na camada 1, 2 e 3, troubleshotting para discovery da rede, opções avançadas do ping, explanação sobre problemas comuns na prática, problemas de fragmentação, TOS, …
Até passou um pouco do horário a aula, mas aulas desse nível valem a pena.

aula jaguara

Aula de Sistemas Operacionais II, sobre shell script. O professor poderia melhorar um pouco em alguns aspectos. Por um lado, em certas horas, tenta motivar ou mexer com a turma, para que o pessoal participe mais. Muito louvável. Porém, em outras horas usa de palavreado inadequado, que foge a seriedade que deveria ter. Também é comum ele dar bolas foras, falar coisa errada, e não parece muito receptivo a comentários.

Exemplos:

  • V="
  • A variável V teria um valor nulo. Mas da forma como passou no quadro, ficou parecendo que se usou apenas uma “aspas duplas”, ou seja, daria erro de sintaxe.

  • V="um quadrado com uma / atravessada"
  • Alguma dose de imaginação é requerida, para imaginar que isso ai seria um espaço em branco.

  • código ASCII do espaço
  • Segundo o professor, não saber de cor o código ASCII de certo caracter == ser pedreiro. Falou que o código era 20, mas se esqueceu de falar que era 20 em hexadecimal.

  • valores de retorno em shell
  • Pelo menos no bash, sempre soube que um valor de retorno 0 corresponde a true, e um valor diferente disso significa false. Mas na aula o professor falou que quando era true retornava 1

  • pentelho
  • A distância entre a cabeça de leitura/gravação e o prato de um HD é de “pentelhésimos”, ou menor que a largura de um pentelho.

  • udev
  • É, parece que algumas distribuições começaram a usar udev né?

  • alunos == jaguaras
  • Falou que tava tendo problemas de fechamento do horário e turmas das aulas, devido aos alunos “jaguaras” que não tinham resolvido a matricula. Na verdade, a matéria seria dividida originalmente em duas turmas. Só que a instuição de ensino com muita seriedade e competência havia escalado um professor sem domínio da matéria para uma das turmas. O professor, sabiamente, declinou em lecionar a matéria, o que forçou a união da turma em uma única. Na ausência de uma definição de horário, e sem uma declaração oficial da instituição seríssima de ensino, o aluno que não conseguir ligar sua bola de cristal e adivinhar o que está acontecendo é tratado solenemente como “jaguara”.

crase x acento grave

Crase é uma palavra grega que significa fusão. No caso, a fusão de um “a” com outro “a”. Comumente, da preposição “a” com o artigo “a”. Assim, crase é o fenômeno da língua, o fenômeno da fusão, que é assinalado com o acento grave.

Portanto a “crase“, tecnicamente, NÃO É o nome do acento. Na verdade, o acento chama-se grave.

Acento grave

Crase
Acento grave

Em aulas sobre shell script tem se o costume de se referir ao acento ` como crase, quando na verdade, tecnicamente, trata-se do acento grave.

pastas

“Diretório é do sistema
Pasta é do usuário”

« Older entries