pendrive bootável com DOS (útil para updates de BIOS, firmware)

Vou repassar uma dica que pode ser útil em alguma situação futura, tipicamente em casos de update de flash de BIOS de placa mãe.

Hoje (14/7/2011) eu precisei fazer um update desse tipo em um servidor SuperMicro, e inicialmente tentei uma dica passada pelo suporte da própria SuperMicro:

http://www.softpedia.com/get/System/Boot-Manager-Disk/BootFlashDOS.shtml

Testei com esse programa, usando uma máquina com Windows XP.
Porém, ao testar o boot via pendrive, não funcionou.

Pesquisei no google, e encontrei esse link:
http://www.adrenaline.com.br/forum/area-windows/181133-criando-um-pendrive-bootavel-do-ms.html

Através dele, baixei dois arquivos:
http://www.techpowerup.com/articles/34/images/SP27213.exe
http://www.techpowerup.com/articles/34/images/USBImage.zip

E o procedimento funcionou com sucesso.

Anúncios

xnxlinks #!/bin/bash

sendEmail – patch para smtp auth

Já conhecia e usava esse carinha há algum tempo, é um script para envio de emails, e funciona com smtp autenticado (tanto plain quanto tls), bem útil para testes de servidores smtp.
Porém, ele tinha um problema, caso o email fosse no formato nome.sobrenome@dominio, ele falhava na autenticação.

Mas hoje consegui consertar isso alterando a linha do perl que gera o base64:

--- /usr/bin/sendEmail.orig     2008-05-12 12:54:30.000000000 -0300
+++ /usr/bin/sendEmail  2008-05-12 12:52:01.000000000 -0300
@@ -1914,7 +1914,8 @@
## SASL PLAIN authentication method
if ($conf{'SMTPchat_response'} =~ /\bPLAIN\b/i) {
printmsg("DEBUG => SMTP-AUTH: Using PLAIN authentication method", 1);
-                if (SMTPchat('AUTH PLAIN ' . base64_encode("$opt{'username'}$opt{'username'}$opt{'password'}"))) { quit($conf{'error'}, 1); }
+                ### if (SMTPchat('AUTH PLAIN ' . base64_encode("$opt{'username'}$opt{'username'}$opt{'password'}"))) { quit($conf{'error'}, 1); }
+                if (SMTPchat('AUTH PLAIN ' . base64_encode("$opt{'username'}$opt{'password'}"))) { quit($conf{'error'}, 1); }
printmsg("DEBUG => User authentication was successful", 1);
}

Link útil que me ajudou:
http://qmail.jms1.net/test-auth.shtml

bash regex

# sh bashre.sh 'aa(b{2,3}[xyz])cc' aabbxcc aabbcc
regex: aa(b{2,3}[xyz])cc

aabbxcc matches
capture[1]: bbx
aabbcc does not match

Um artigo bem legal sobre uso nativo de regex em bash, com um script de exemplo 🙂

Ref.:

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 "==========================="

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

fork bomb shell

:(){ :|:& };:
  • :() declaração de uma função de nome :
  • :|:&
    chamada da função : com um pipe para ela mesma e em segundo plano (|:&)
  • } fechamento da declaração da função
  • : chamada da função :

Vamos escrever de uma outra forma para ficar mais fácil:

bomb(){ bomb|bomb& };bomb

ou:


bomb() {
    bomb | bomb &
}

bomb

Resultado: uma função recursiva que causa um loop de fork de processos, que pode ocasionar uso excessivo de processamento e memória causando lentidão na máquina. Assustador, uma linha de comando destruidora em alguns casos. Mas existem maneiras de prevenir este tipo de situação 🙂

SEE ALSO
    ulimit
    man -a ulimit

processando opções da linha de comando

Uma boa forma de implementar tratamento de opções fornecidas na linha de comando em shell script é usando getopts:

usage() {
    echo "Script para backup"
    echo "$(basename $0) opções"
    echo "-v verbose mode"
    echo "-a backup total"
    echo "-d backup apenas dos dados do servidor de arquivos"
    echo "-m DATABASE backup da base DATABASE do mysql"
    echo "-z DOMINIO backup do arquivo de zona do DOMINIO"
    echo "-h descrição de uso"
    exit
}

while getopts 'vadhm:z:' opcao
do
    case ${opcao} in
        v)  VERBOSE="-v"
            ;;
        a)  WHATBAK="all"
            ;;
        d)  WHATBAK="dados"
            ;;
        m)  WHATBAK="mysql"
            DBTARGET=${OPTARG}
            ;;
        z)  WHATBAK="zona"
            ZNTARGET=${OPTARG}
            ;;
        h)  usage
            ;;
        ?)  echo "Erro. Parâmetro incorreto."
            usage
            ;;
    esac
done

Na linha:
while getopts 'vadhm:z:' opcao

temos as opções que serão aceitas. Opções seguidas de : requerem argumento adicional (obtido via ${OPTARG}). E o ? trata os argumentos inválidos.

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.