Executando scripts na inicialização do Debian/Ubuntu


Muitas vezes desejamos executar algum comando ou iniciar serviços na inicialização do Sistema Operacional. É muito simples executar essa operação usando o Debian ou o Ubuntu.

Veja abaixo um passo-a-passo e um exemplo usando uma instalação manual do Servidor WEB Apache.

Todos os comandos precisam ser executados como root.

Primeiramente, vamos criar um script chamado meuScript em /etc/init.d com uma estrutura semelhante à abaixo:

#!/bin/bash
#
# /etc/init.d/meuScript
 
case "$1" in
    start)
        echo "Iniciando serviço..."
        # comando para iniciar o serviço
        ;;
 
    stop)
        echo "Parando serviço..."
        # comando para parar o serviço
        ;;
 
    restart)
        echo "Reiniciando serviço..."
        # comando para reiniciar o serviço
        ;;
 
    *)
        echo "Operação inválida"
        ;;
esac

Dê permissão de execução para o script:

# chmod +x meuScript

A partir desse momento você já pode executar os comandos abaixo:

# /etc/init.d/meuScript start
# /etc/init.d/meuScript stop
# /etc/init.d/meuScript restart

Para inserir o script na inicialização do sistema, usamos o comando update-rc.d da seguinte maneira:

# update-rc.d meuScript defaults

O “meuScript” é o nome do script em /etc/init.d, não o caminho completo a ele, ou seja, não importa em qual diretório você está, apenas coloque o nome do script.

O “defaults” indica que desejamos inserir o script nos runlevels padrões do sistema.

Ao executar esse comando, um warning será mostrado, apesar de o comando ter funcionado. Aparecerá uma mensagem como esta:

update-rc.d: warning: /etc/init.d/meuScript missing LSB information
update-rc.d: see <http://wiki.debian.org/LSBInitScripts>

Você pode ignorá-lo ou inserir as informações de LSB, o que é mostrado no link exibido no warning. É algo bem simples. =)

Para remover um script da inicialização:

# update-rc.d -f meuScript remove

Como prometi, vou mostrar um exemplo que uso para uma instalação manual do Apache:

#!/bin/bash
#
# /etc/init.d/apache2 
 
### BEGIN INIT INFO
# Provides:          apache2
# Required-Start:    $local_fs $syslog
# Required-Stop:     $local_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start Apache at boot
# Description:       Start Apache HTTP Server
### END INIT INFO
 
# Path to Apache controller
BIN=/usr/local/apache2/bin/apachectl
 
function startApache()
{
	echo "Starting Apache..."
	$BIN start
}
 
function stopApache()
{
	echo "Stopping Apache..."
	$BIN stop
}
 
case "$1" in
	start )
		startApache
		if [ $? -eq 0 ]
		then
			echo "OK."
		fi
 
		;;
 
 
	stop )
		stopApache
		if [ $? -eq 0 ]
		then
			echo "OK."
		fi
 
		;;
 
	restart )
		stopApache
		sleep 1
		startApache
		if [ $? -eq 0 ]
		then
			echo "OK."
		fi
 
		;;
 
 
	* )
		echo "Invalid option"
		;;
esac

The following two tabs change content below.
Graduado em Ciência da Computação, pela Universidade Federal do Paraná (UFPR), é desenvolvedor de software desde 2008, com foco em Desenvolvimento Web com PHP.
  • Alex

    E para executar o script após login? Preciso montar um compartilhamento wireless mas no fstab não rola pois a conexão só estabelece depois do login. Então eu queria colocar o script para montar a unidade após a conexão estabelecida.

  • @Alex

    Você pode inserir os comandos no arquivo ~/.bashrc ou ~/.profile do usuário. O primeiro é executado ao abrir um terminal; o segundo é executado logo após o login.

    Abraço,

    Beraldo

  • Pingback: Preparando o Ambiente de Desenvolvimento (parte 3 – O retorno do rei) « De Sobrinho a ZCE()

  • Miriam

    Olá,
    Muito bom o post, mas não resolveu uma dúvida que tenho e acho que é de muitos. Por exemplo, quando colocamos um script como este na inicializãção como o Linux sabe qual função será a que deve ser executada.
    Para ser mais clara, quando chamo via linha de comando, como vc fez, uso: meuScript start. Mas se colocamos o script meuScript na Inicialização como saberemos que a função a ser executada é start – neste exemplo?
    Muito Obrigada!!
    bjs, Miriam

  • Olá, @Miriam

    O “defaults” no comando insere o script na inicialização e no encerramento do Sistema Operacional. Isso está ligado aos runlevels do Linux.

    Conforme a man page de update-rc-d(8) (digite “man update-rc.d” no terminal):
    EXAMPLES
    Insert links using the defaults:
    update-rc.d foobar defaults
    Equivalent command using explicit argument sets:
    update-rc.d foobar start 20 2 3 4 5 . stop 20 0 1 6 .

    Veja mais detalhes sobre os runlavels aqui:
    http://pt.wikipedia.org/wiki/Runlevel
    http://en.wikipedia.org/wiki/Runlevel

    Note que o segundo comando exibido acima executa o “start” nos runlevels 2 3 4 5, que são runlevels que iniciam o Sistema Operacional e seus daemons. O comando também executa “stop” nos runlevels 0 1 6, que são, respectivamente, desligamento, modo single-user sem daemons e reboot do sistema.

    Portanto, o próprio Sistema Operacional executa start ou stop, conforme o runlevel corrente, desde que o script (ou um link simbólico a ele) esteja em /etc/rc$(NUMERO_DO_RUNLEVEL).d.

  • Miriam

    Querido Beraldo, bom dia!

    Se entendi direito a resposta – e levando em consideração um run level = 2 – é: o sistema operacional irá executar tudo que está em /etc/rc2.d, desde que um script que esteja neste diretório – e que tenha funções – tenha também uma linha – que é um comentário – dizendo: # Default-NomeDaFunção: 2 3 4 5. Claro que isso valeria para os níveis 2,4, e 5. É isso?

    Se o nome da função for FuncQualquerCoisa, basta termos a linha – que é um comentário –
    # Default-FuncQualquerCoisa: 2 3 4 5

    Assim, o sistema operacional, irá executar a função FuncQualquerCoisa, sem intervenção de ninguém. É isso? Desculpe a insistência, mas gostaria de ter certeza que entendeste minha pergunta e então exemplifiquei. Eu definitivamente não sabia disto e vou te contar, pouca gente sabe e muita gente tem vergonha de perguntar. Poderia me responder se estou no raciocínio certo?

    Obrigada!
    bjs e Feliz Ano Novo!

  • SixTenSixOne

    Olá tenho a mesma dúvida da Mirian, mas gostaria de colocar em outras palavras, pode ser:

    Como o Linux trabalha com arquivos de inicialização que contenham funções.

    Vejam, minha dúvida não é sobre runlevel, ok? Vou tentar explicitar: Suponha que eu tenha um script como seu arquivo acima:

    #!/bin/bash
    #
    # /etc/init.d/meuScript

    case “$1” in
    start)
    funcA
    ;;

    stop)
    funcB
    ;;

    restart)
    funcC
    ;;

    *)
    echo “Operação inválida”
    ;;
    esac

    Suponha que neste script existam as funções funcA, funcB, funcC.

    Vamos supor que eu queira que este script se inicie no runlevel 2, então basta eu colocar o script em /etc/rc2.d.

    Quanto a isto estou ok. Ou seja todas as vezes que o Linux se iniciar no nível 2, ele executará este script.

    Minha questão é: como ele sabe qual função deve ser executada em primeiro lugar?

    Da forma como fiz, caso eu chame meuscript com o parâmetro start, ele irá buscar o conteúdo que se encontra no case start.

    Como o sistema operacional irá fazer para executar o que está dentro do case start, quando se iniciar sozinho?

    Ele vai procurar por default pela string “start”?

    Caso o runlevel não seja 2 e seja um runlevel de parada do sistema, então ele vai procurar pela string de “stop”???

    Obrigado.
    Sixten

  • Olá, @Miriam

    O comentário não é obrigatório. É apenas um padrão, uma recomendação, segundo o padrão LSB. Veja mais informações aqui:
    http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/initscrcomconv.html

    Experimente colocar um script sem as informações de LSB. Ele funciona, apesar de aparecer um warning avisando que faltam essas informações.

    Até onde sei, o Sistema Operacional executa start ou stop conforme o runlevel corrente, não importando o que estiver escrito como comentário nas informações de LSB.

  • Olá, @SixTenSixOne

    Como eu postei anteriormente, em resposta à Miriam, o Linux executa os scripts /etc/rcX.d com o parâmetro start ou stop. A partir daí, o script é quem faz o trabalho de executar as funções. Você que deve garantir que sejam executadas as ações corretas ao se passarem os parâmetros start ou stop, tratando adequadamente o argumentos de linha de comando.

  • joelson

    Criei um script pensando em facilitar minha vida da seguinte forma: toda vez que o servidor (Debian) iniciar/reiniciar, um email é enviado para mim automaticamente. O script funciona perfeitamente qndo digito “./enviando_email.sh”. Coloquei este script em “/etc/init.d” e criei um link simbólico para o diretório “/etc/rc5.d” com o seguinte comando “#ln -s /etc/init.d/enviando_email.sh /etc/rc5.d/S90enviando_email”. Veja o link (http://www.hardware.com.br/comunidade/programa-fazer/969173/). Dei um “reboot” no sevidor, e nada aconteceu. Foi qndo fui pesquisar e encontrei este blog e tentei com o comando “update-rc.d enviando_email.sh defaults”(apareceu a seguinte msg: “update-rc.d: warning: /etc/init.d/meuScript missing LSB information
    update-rc.d: see
    System startup links for /etc/init.d/enviando_email.sh already exist.”),reiniciei, mais não recebi o email avisando sobre a reinicialização do servidor. O que estou fazendo de errado? Desde já agradeço!

  • Olá, Joelson.

    A mensagem diz que já há um link para esse script. Tente remover o link simbólico que você criou inicialmente. Faça um “remove” com update-rc.d e, em seguida, tente inserir novamente com update-rc.d “defaults”

  • Jorge

    “Beraldo15/08/2010 at 17:21 | Permalink
    @Alex

    Você pode inserir os comandos no arquivo ~/.bashrc ou ~/.profile do usuário. O primeiro é executado ao abrir um terminal; o segundo é executado logo após o login.”

    Esta opção do PROFILE foi exatamente o que eu precisava.
    Muito obrigado, Beraldo!

  • Rodrigo Minelli

    Olá Beraldo, parabéns pelo post.

    Tenho uma duvida como faço para passar várias variáveis para dentro da função.
    Veja o script (vmbox):
    #!/bin/bash
    #
    # /etc/init.d/vbox.sh

    ### BEGIN INIT INFO
    # Provides: VirtualBox
    # Description: Start VirtualBox Machine
    # $1 = Command
    # $2 = VM
    # $3 = Port RDP
    ### END INIT INFO

    # Path to VBoxManage & VBoxHeadless
    BIN=”/usr/bin/VBoxHeadless”
    BIN1=”/usr/bin/VBoxManage”

    function startVBoxM()
    {
    echo “Starting VBoxM ” $2 “…”
    $BIN “-startvm” $2 “-vrde on -e “TCP/Ports=$3″ &”
    # “/usr/bin/VBoxHeadless -startvm “$2″ -vrde on -e TCP/Ports=”$3″ &”
    }

    function stopVBoxM()
    {
    echo “Stopping VBoxM ” $2 “…”
    $BIN controlvm $2 poweroff
    }

    function listVBoxM()
    {
    echo “Listing VBoxM…”
    $BIN1 list vms
    }

    function listhddVBoxM()
    {
    echo “Listing HDD VBoxM…”
    $BIN1 list hdds
    }

    case “$1” in
    start )
    startVBoxM
    if [ $? -eq 0 ]
    then
    echo “OK.”
    fi

    ;;

    stop )
    stopVBoxM
    if [ $? -eq 0 ]
    then
    echo “OK.”
    fi

    ;;

    restart )
    stopVBoxM
    sleep 2
    startVBoxM
    if [ $? -eq 0 ]
    then
    echo “OK.”
    fi

    ;;

    listvm )
    listVBoxM
    if [ $? -eq 0 ]
    then
    echo “OK.”
    fi

    ;;

    listhd )
    listhddVBoxM
    if [ $? -eq 0 ]
    then
    echo “OK.”
    fi

    ;;

    * )
    echo “Invalid option”
    ;;
    esac

    Ai está o código o problema é que as funçõs não assumem $1, $2, $3 já fora das funções funciona normalmente.

    • Você está usando $2 dentro de uma função. Ou seja, o script está buscando pelo segundo parâmetro da função, não do script.

      Para pegar o segundo parâmetro do script e usar numa função, atribua o valor a uma variável global fora da função e a use dentro da função, da mesma forma como faz com $BIN

      • Rodrigo Minelli

        Obrigado Beraldo pela resposta efetuarei os testes e retorno o resultado.
        Desde já agradeço.

  • Gabriel

    Olá! Boa noite!

    Como faço para colocar em um script o comando para iniciar três programas distintos, sendo que quando abro o terminal, simplesmente digito:

    cd /home/mgeweb/SanNFe
    ./sannfe-service start

    Como fazer para no mesmo script abrir os programas em pastas distintas?

    Valeu!!

    • Nesse caso, não tem a ver com init.d, já que você executará o script manualmente. Você pode adicionar os três comandos no mesmo script, sem problemas:

      #!/bin/bash
      comando1
      comando2
      comando3

      Se quiser rodá-los em background, basta adicionar o E-Comercial (&) logo após cada um.

      Abraço

      • Gabriel

        Beraldo, muito agradecido pela ajuda.
        Só mais uma dúvida. Como já tenho o script rodando manualmente, posso simplesmente colocar assim?


        #!/bin/bash
        cd /home/mgeweb/SanNFe
        ./sannfe-service start &
        cd /home/mgeweb/Programa1
        ./teste1 start &
        cd /home/mgeweb/Programa2
        ./teste2 start &

        Poderia ser assim? Porque deste modo só está iniciando o primeiro programa, os outros dois não iniciam, nem executando o arquivo (após a permissão no arquivo).

        Valeu!

        • Estranho. Deveria funcionar corretamente.

          Tente tirar os cd’s e executar o script com o path completo:

          /home/user/programa start &

          Ao executar o script, também execute-o em background:

          ./inicia_servicos.sh &

          Veja se resolve

  • Aristides

    Beraldo…

    O Script abaixo é para iniciar o Oracle Database, lembrando que dei permissão de execução e inseri-o na inicialização; porém isso não ocorre.
    As variáveis do Oracle Database estão setadas, já verifiquei pois, manualmente no prompt do usuário oracle consigo iniciar ou ‘shutar’ o banco:
    $ dbstart
    ou
    $ dbshut

    O banco tá rodando beleza, só não consigo automatizar o ‘start’ / ‘shut’ do mesmo.
    Tem alguma idéia do que seja ?
    Estou usando o Debian Squeeze.
    Segue o código abaixo.

    #!/bin/sh
    #
    # /etc/init.d/dbora

    ### BEGIN INIT INFO
    # Provides: dbora
    # Required-Start: $local_fs $syslog
    # Required-Stop: $local_fs $syslog
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Short-Description: Oracle Database at boot time
    # Description: Enable Oracle Database
    ### END INIT INFO

    ORA_HOME=/u01/app/oracle/product/11.2.0/db_1
    ORA_OWNER=oracle

    if [ ! -f $ORA_HOME/bin/dbstart ]
    then
    echo “Oracle startup: cannot start”
    exit
    fi

    case “$1” in
    ‘start’)
    # Start the Oracle databases:
    # The following command assumes that the oracle login
    # will not prompt the user for any values
    su – $ORA_OWNER -c “$ORA_HOME/bin/dbstart $ORA_HOME”
    touch /var/lock/subsys/dbora
    ;;
    ‘stop’)
    # Stop the Oracle databases:
    # The following command assumes that the oracle login
    # will not prompt the user for any values
    su – $ORA_OWNER -c “$ORA_HOME/bin/dbshut $ORA_HOME”
    rm -f /var/lock/subsys/dbora
    ;;
    esac

    • Já tentou executar esse script manualmente para ver se funciona (/etc/init.d/seu_script)?

      Também coloque alguns echo’s, para saber o que está acontecendo e onde a execução está parando.

      • Aristides

        O arquivo ‘dbora’ esta em /etc/init.d/ porém esta apresentando a seguinte msg de erro:

        “bash: /etc/init.d/dbora: /bin/sh^M: bad interpreter: No such file or directory”

  • Veja o erro: ” /bin/sh^M” . A primeira linha está especificando um interpretador inválido. Aparentemente, há algum caractere inválido após o “sh” (note o ^M). Corrija isso e tente novamente.

    • Aristides

      Até reescrevi o início do arquivo ‘dbora’, e deu o mesmo erro.

      #!/bin/sh
      # /etc/init.d/dbora

      • Aristides

        Observei que quando da inicialização apresenta a seguinte msg:
        ” startpar: service(s) returned failure: dbora … failed !”

        • tente com /bin/bash

          • Aristides

            Tentei com
            #!/bin/bash
            e deu o mesmo erro.

            • isso é muito estranho: o script é executado, mas o erro ocorre no path do interpretador. Veja se há o sh e o bash no /bin e se estão com as devidas permissões de execução (755, owner=root).

              • Aristides

                Beraldo… o sh e o bash estão corretos !!!
                Resolvido o problema…
                É que eu tinha editado o arquivo ‘dbora’ no ‘notepad’ do window e dando um ‘cat’ a partir do linux para criá-lo, daí o erro apresentado.
                Criei o arquivo no linux através do ‘vim’; dei as pemissões; inseri na inicialização e deu tudo certo.
                Aprendi mais uma, arquivos editados no windows são diferentes no linux.
                Agradeço a ajuda.

  • Pingback: Executando scripts na inicialização raspberry pi | 0jln()

  • Pingback: Linux em notebook HP Pavilion x360 uma odisseia no shell (rascunho/Alpha) | RAREFECUNDO()

  • Monique Carleti

    Muito obrigada!
    Tinha encontrado informações semelhantes em outros blogs porém sem o detalhe do #!/bin/bash… no início do script e não conseguia que funcionasse. Agora deu certo!
    Valeu mesmo pela dica e pelo cuidado nos detalhes!
    Abraço!

  • Fladner

    amigo sei que seu post ja tem um tempo mas se puder ajudar, preciso fazer o inverso do seu tuto, quero rodar um script simples na hora de desligar o sistema.
    como proceder?