6. Inicialização e desligamento de um daemon avançado

Vamos adicionar um pouco de carne aos ossos do script anterior e torná-lo mais complexo e cheio de funcionalidades. Os métodos padrões podem fazer um bom trabalho para nós, mas podemos precisar ajustar alguns dos seus aspectos. Agora vamos aprender como ajustar os métodos padrões para as nossas necessidades.

#!/bin/sh

. /etc/rc.subr

name=mumbled
rcvar=mumbled_enable

command="/usr/sbin/${name}"
command_args="mock arguments > /dev/null 2>&1"1

pidfile="/var/run/${name}.pid"2

required_files="/etc/${name}.conf /usr/share/misc/${name}.rules"3

sig_reload="USR1"4

start_precmd="${name}_prestart"5
stop_postcmd="echo Bye-bye"6

extra_commands="reload plugh xyzzy"7

plugh_cmd="mumbled_plugh"8
xyzzy_cmd="echo 'Nothing happens.'"

mumbled_prestart()
{
	if checkyesno mumbled_smart; then9
		rc_flags="-o smart ${rc_flags}"10
	fi
	case "$mumbled_mode" in
	foo)
		rc_flags="-frotz ${rc_flags}"
		;;
	bar)
		rc_flags="-baz ${rc_flags}"
		;;
	*)
		warn "Invalid value for mumbled_mode"11
		return 112
		;;
	esac
	run_rc_command xyzzy13
	return 0
}

mumbled_plugh()14
{
	echo 'A hollow voice says "plugh".'
}

load_rc_config $name
run_rc_command "$1"

1

Argumentos adicionais para $command podem ser passados em command_args. Eles serão adicionados a linha de comando após $mumbled_flags. Como a linha de comando final é passada para eval para sua execução real, os redirecionamentos de entrada e saída podem ser especificados em command_args.

Nota:

Nunca inclua opções tracejadas, como -X ou --foo, em command_args. O conteúdo de command_args aparecerá no final da linha de comando final, portanto é provável que eles sigam os argumentos presentes em ${name}_flags; mas a maioria dos comandos não reconhecerá opções tracejadas após argumentos comuns. Uma maneira melhor de passar opções adicionais para $command é adicioná-las ao início de ${name}_flags . Outra maneira é modificar rc_flags como mostrado posteriormente .

2

Um daemon de boas maneiras deve criar um pidfile para que seu processo possa ser encontrado com mais facilidade e confiabilidade. A variável pidfile, se configurada, informa ao rc.subr(8) onde pode encontrar o pidfile para seus métodos padrão possam usar.

Nota:

De fato, o rc.subr(8) também usará o pidfile para ver se o daemon já está em execução antes de iniciá-lo. Esta verificação pode ser ignorada usando o argumento faststart.

3

Se o daemon não puder ser executado a menos que existam certos arquivos, apenas liste-os em required_files, e rc.subr(8) irá verificar se esses arquivos existem antes de iniciar o daemon. Também existem required_dirs e required_vars para diretórios e variáveis de ambiente, respectivamente. Todos eles são descritos em detalhes em rc.subr(8).

Nota:

O método padrão de rc.subr(8) pode ser forçado a ignorar as verificações de pré-requisitos usando forcestart como o argumento para o script.

4

Podemos personalizar sinais para enviar para o daemon caso eles sejam diferentes dos mais conhecidos. Em particular, sig_reload especifica o sinal que faz o daemon recarregar sua configuração; é SIGHUP por padrão. Outro sinal é enviado para parar o processo do daemon; o padrão é SIGTERM, mas isso pode ser alterado definindo sig_stop apropriadamente.

Nota:

Os nomes dos sinais devem ser especificados para o rc.subr(8) sem o prefixo SIG, como é mostrado no exemplo. A versão do FreeBSD do kill(1) pode reconhecer o prefixo SIG, mas as versões de outros tipos de sistema operacional não.

5 6

Realizar tarefas adicionais antes ou depois dos métodos padrão é fácil. Para cada argumento de comando suportado pelo nosso script, podemos definir o argumento _precmd e _postcmd. Esses comandos no sh (1) são invocados antes e depois do respectivo método, como é evidente em seus nomes.

Nota:

Sobrescrever um método padrão com um argumento _cmd personalizado ainda não nos impede de fazer uso do argumento _precmd ou argumento _postcmd se precisarmos. Em particular, o primeiro é bom para verificar condições personalizadas e sofisticadas que devem ser atendidas antes de executar o comando em si. Usar o argumento _precmd junto com o argumento _cmd nos permite separar logicamente as verificações da ação.

Não se esqueça de que você pode amontoar qualquer expressão válida do sh(1) nos métodos, pré e pós-comandos definidos por você. Apenas invocar uma função que faz com que o trabalho real seja um bom estilo na maioria dos casos, mas nunca deixe o estilo limitar sua compreensão do que está acontecendo por trás da cortina.

7

Se quisermos implementar argumentos customizados, que também podem ser considerados como comandos para o nosso script, precisamos listá-los em extra_commands e fornecer métodos para manipulá-los.

Nota:

O comando reload é especial. Por um lado, tem um método predefinido em rc.subr(8). Por outro lado, reload não é oferecido por padrão. A razão é que nem todos os daemons usam o mesmo mecanismo de recarga e alguns não têm nada para recarregar. Portanto, precisamos solicitar explicitamente que a funcionalidade incorporada seja fornecida. Podemos fazer isso via extra_commands.

O que obtemos do método padrão para reload? Muitas vezes, os daemons recarregam sua configuração na recepção de um sinal - normalmente, SIGHUP. Portanto, o rc.subr(8) tenta recarregar o daemon enviando um sinal para ele. O sinal é predefinido para SIGHUP, mas pode ser personalizado via sig_reload, caso necessário.

8 14

Nosso script suporta dois comandos não padrão, plugh e xyzzy. Nós os vimos listados em extra_commands, e agora é hora de fornecer métodos para eles. O método para xyzzy é apenas embutido, enquanto que para plugh é implementado como a função mumbled_plugh.

Comandos não padrão não são chamados durante a inicialização ou o desligamento. Geralmente eles são para a conveniência do administrador do sistema. Eles também podem ser usados de outros subsistemas, por exemplo, devd(8) se especificado em devd.conf(5).

A lista completa de comandos disponíveis pode ser encontrada na linha de uso impressa por rc.subr(8) quando o script é invocado sem argumentos. Por exemplo, aqui está a linha de uso do script em estudo:

# /etc/rc.d/mumbled
Uso: /etc/rc.d/mumbled [fast|force|one](start|stop|restart|rcvar|reload|plugh|xyzzy|status|poll)

13

Um script pode invocar seus próprios comandos padrão ou não padrão, se necessário. Isto pode parecer semelhante as funções de chamada, mas sabemos que comandos e funções de shell nem sempre são a mesma coisa. Por exemplo, xyzzy não é implementado como uma função aqui. Além disso, pode haver um pré-comando e um pós-comando, que devem ser chamados ordenadamente. Portanto, a maneira correta de um script executar seu próprio comando é por meio de rc.subr(8), conforme mostrado no exemplo.

9

Uma função útil chamada checkyesno é fornecida por rc.subr(8). Ele usa um nome de variável como argumento e retorna um código de saída zero se, e somente se, a variável estiver configurada como YES, ou TRUE, ou ON, ou 1, sem distinção entre maiúsculas e minúsculas; um código de saída diferente de zero é retornado de outra forma. No último caso, a função testa a variável como sendo definida como NO,FALSE,OFFou0 insensível a maiúsculas e minúsculas; imprime uma mensagem de aviso se a variável contiver qualquer outra coisa, ou seja, lixo.

Tenha em mente que para o sh(1) um código de saída zero significa verdadeiro e um código de saída diferente de zero significa falso.

Importante:

A função checkyesno recebe um nome da variável. Não passe o valor expandido de uma variável para ele; não funcionará como esperado.

O uso correto de checkyesno é:

if checkyesno mumbled_enable; then
        foo
fi

Pelo contrário, chamar checkyesno como mostrado abaixo não funcionará - pelo menos não como esperado:

if checkyesno "${mumbled_enable}"; then
        foo
fi

10

Podemos afetar os sinalizadores a serem passados para $command modificando rc_flags em $start_precmd.

11

Em certos casos, podemos precisar emitir uma mensagem importante que também deve ser enviada para o syslog. Isto pode ser feito facilmente com as seguintes funções rc.subr(8): debug, info, warn e err. A última função, em seguida, sai do script com o código especificado.

12

Os códigos de saída dos métodos e seus pré-comandos não são apenas ignorados por padrão. Se o argumento _precmd retornar um código de saída diferente de zero, o método principal não será executado. Por sua vez, o argumento_postcmd não será invocado a menos que o método principal retorne um código de saída zero.

Nota:

No entanto, o rc.subr(8) pode ser instruído a partir da linha de comando para ignorar esses códigos de saída e invocar todos os comandos, prefixando um argumento com force, como em forcestart.

All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/

Questions that are not answered by the documentation may be sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.