Saída de log do script em segundo plano ou de inicialização

10

Eu tenho um script curto que é executado por um daemon do sistema para eventos específicos. Sei que o evento está ocorrendo e o script está sendo executado, mas não faz o que pretendo. Estranhamente, quando o executo manualmente, estou muito confuso.

Como posso descobrir o que está acontecendo? O script é basicamente uma série de comandos como este:

/bin/foo on 3
sudo bar a
Cachinhos Dourados
fonte
Eu entendo que isso pretende ser um tutorial sobre a depuração de scripts do sistema, mas também é um pouco U&L. Eu interpretei mal o título e sugeriria que "Registrar a saída de um script do sistema para depuração" tornaria o objetivo mais claro. Além disso, meu cérebro congela quando leio esses foo barexemplos; prefiro algo que parece mais real. Estou relutante em editar qualquer postagem, por isso deixarei isso para você, se você acha que pode ser melhorado.
Milliways
11
@ Milliways Você está certo, "script do sistema" era meio que inadequado, então eu mudei o título. Eu discordo da coisa foobar - as pessoas precisam aprender a reconhecer jargões / coloquialismos comuns da mesma forma que em qualquer cultura. Também ainda é uma boa risadinha quando você junta os dois.
goldilocks

Respostas:

8

Primeiro, se o script for executado por um daemon do sistema e esse daemon estiver em execução com privilégios de root, você não precisará usá-lo sudo. Isso inclui init(e systemd), o que inclui rc.local. Se esse daemon não estiver sendo executado com privilégios de root, ele sudonão funcionará, a menos que /etc/sudoersesteja configurado para permitir isso (e sem uma senha). Os usuários do Raspbian podem ficar confusos com isso, já que o piusuário pode fazer qualquer coisa por padrão (e se você olhar /etc/sudoers, verá como isso é feito).

Em seguida, você pode capturar a saída de qualquer bashscript ou qualquer conjunto de comandos dentro de um script bash, executando-os em uma subshell como esta: 1

(
    /bin/foo on 3
    sudo bar a
) &> /var/log/myTestLog.txt

O ()indica um subshell . Toda a saída de qualquer coisa dentro disso está sendo redirecionada para um /var/log/myTestLog.txtarquivo. Algumas notas:

  • &>é um basismo , portanto, se o script for executado através de um shebang na primeira linha, deve ser #!/bin/bash, não apenas /bin/sh. "Bashisms" funcionam apenas no bashshell.

    Isso inclui /etc/rc.local, que por padrão usa /bin/sh(ou seja, sim, você pode alterar isso com segurança /bin/bash).

  • /var/logrequer privilégios de root para gravar. Se o processo não tiver, use ou crie um diretório que você sabe que pode. Em caso de dúvida, se você puder testar isso sem precisar desligar ou reiniciar o sistema, use /tmp, que é gravável mundialmente (ou seja, por qualquer pessoa). No entanto /tmp, não persiste entre as botas. Também é uma pequena partição baseada em RAM, portanto, não grave gigs de dados nela. Não é o seu cartão SD [na verdade, nas versões atuais do Raspbian, mas não conte com isso na prática] .

  • &>sobrescreverá qualquer coisa myTestLog.txt. Se você deseja anexar a um log existente, o que pode ser uma boa ideia para fins de depuração, use &>>. Você pode então adicionar um comando ao início desse subshell assim:

    echo Starting $(date)

    Para separar as informações de cada execução. Se você não tiver certeza do que isso faz, tente na linha de comando.

Este último ponto é uma boa ilustração de algo que você pode fazer com relação aos comandos que não produzem nada - mas a maioria deles faz se você incluir, por exemplo, -v"verboso". Cuidado com alguns comandos -vsignifica "informações sobre a versão impressa". Dê uma olhada na página de manual para saber se o comando e como isso funcionará (alguns comandos também usam uma opção diferente -v).

Por convenção, os comandos também retornam um valor 0 quando concluídos. Às vezes, isso é chamado de "status de saída" e você normalmente não o vê, mas o shell mostrará a você echo $?. Tentar

 ls /
 echo $?
 ls /nonexistantdir
 echo $?

Você receberá 0 e 2. Se você procurar na página de manual lsem "Status de saída", verá o enigmático bastante inespecífico:

2      if serious trouble (e.g., cannot access command-line argument).

O que pode ou não ser melhor que nada, mas lá vai você.

No mínimo, isso indica que o comando falhou por algum motivo. O status de saída também permite que você faça coisas como estas:

/bin/foo && sudo bar

A &&neste meio de caso "se o primeiro comando for bem-sucedido", presumindo que o primeiro comando usa a convenção de retornar 0 (que é por isso que eles costumam fazer). Se /bin/foonão funcionar, não puder ser encontrado, etc., sudo barnunca acontecerá.

O uso de uma combinação de mensagens de log e execução condicional ( &&) deve levá-lo muito mais perto de descobrir o problema ou, pelo menos, obter informações que possam ser úteis para outras pessoas para ajudá-lo a resolver o problema. Sem isso, o máximo que qualquer outra pessoa pode fazer é adivinhar.


1. Você pode realizar o mesmo redirecionamento de saída para um script inteiro de dentro usando:

exec &> /var/log/myTestLog.txt

No topo (ou em qualquer lugar, e isso se aplicará a tudo subsequente).

Cachinhos Dourados
fonte
2

Um aspecto importante que as pessoas tendem a esquecer ao executar scripts como daemons é o ambiente de shell e a $PATHvariável em particular. No seu exemplo, a segunda linha conta com $PATH: o nome completo de sudoé /usr/bin/sudoe o shell do usuário sabe disso apenas porque foi instruído a pesquisar /usr/binao procurar por executáveis. O mesmo vale para bar.

Considerando que sudonão é necessário ao executar scripts como daemons, sua segunda linha deve se parecer com:

/path/to/bar a
Dmitry Grigoryev
fonte