Registra l'output dello script in background o di avvio


10

Ho un breve script che viene eseguito da un demone di sistema per eventi particolari. So che l'evento si sta verificando e lo script è in esecuzione, ma non fa ciò che intendo. Stranamente, lo fa quando lo eseguo manualmente, quindi sono molto confuso.

Come posso capire cosa sta succedendo? Lo script è sostanzialmente una serie di comandi come questo:

/bin/foo on 3
sudo bar a

Capisco che questo debba essere un tutorial sugli script di sistema di debug, ma lo è anche un po ' U&L. Ho letto male il titolo e suggerirei che "Registrare l'output di uno script di sistema per il debug" renderebbe più chiaro lo scopo. Anche il mio cervello si blocca quando leggo questi foo baresempi, preferisco qualcosa che sembra più mondo reale. Sono riluttante a modificare qualsiasi post, quindi ti lascerò questo se pensi che possa essere migliorato.
Milliways,

1
@Milliways Hai ragione, "script di sistema" era in qualche modo un termine improprio, quindi ho cambiato il titolo. Non sono d'accordo sulla cosa foobar - le persone hanno bisogno di imparare a riconoscere il gergo / colloquiali comuni proprio come potrebbero fare in qualsiasi cultura. Inoltre è ancora una buona risatina una volta messi insieme i due.
Riccioli d'oro

Risposte:


8

Innanzitutto, se lo script è eseguito da un demone di sistema e quel daemon è in esecuzione con privilegi di root, non è necessario utilizzarlo sudo. Questo include init(e systemd), che include rc.local. Se quel demone non è in esecuzione con i privilegi di root, allora sudonon funzionerà se non /etc/sudoersè configurato per consentire tale (e senza una password). Gli utenti di Raspbian possono essere confusi da ciò poiché l' piutente è autorizzato a fare qualsiasi cosa per impostazione predefinita (e se guardi dentro /etc/sudoersvedrai come ciò viene realizzato).

Successivamente, è possibile acquisire l'output da qualsiasi bashscript o da qualsiasi set di comandi all'interno di uno script bash, eseguendoli in una subshell come questa: 1

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

Il ()indica una subshell . Tutto l'output da qualsiasi cosa all'interno di questo viene reindirizzato a un /var/log/myTestLog.txtfile. Alcune note:

  • &>è un bashismo , quindi se la sceneggiatura viene eseguita tramite uno shebang sulla prima riga, dovrebbe essere #!/bin/bash, non solo /bin/sh. I "bashismi" funzionano solo nella bashshell.

    Ciò include /etc/rc.local, che per impostazione predefinita utilizza /bin/sh(ovvero, sì, è possibile modificarlo in modo sicuro /bin/bash).

  • /var/logrichiede i privilegi di root su cui scrivere. Se il processo non ha tale, utilizzare o creare una directory che si sa che può. In caso di dubbio, se è possibile verificarlo senza dover arrestare o riavviare il sistema, utilizzare /tmp, che è scrivibile dal mondo (cioè da chiunque). Tuttavia /tmp, non persiste su tutti gli stivali. È anche una piccola partizione basata su RAM, quindi non scrivere concerti di dati su di essa. Non è la tua scheda SD [in realtà lo è sulle versioni correnti di Raspbian, ma in pratica non conta su questo] .

  • &>sovrascriverà qualsiasi cosa in myTestLog.txt. Se invece si desidera aggiungere a un registro esistente, che potrebbe essere una buona idea per scopi di debug, utilizzare &>>. È quindi possibile aggiungere un comando all'inizio di quella subshell in questo modo:

    echo Starting $(date)

    Per separare le informazioni da ogni corsa. Se non sei sicuro di cosa faccia, prova dalla riga di comando.

Quest'ultimo punto è una buona illustrazione di qualcosa che puoi fare riguardo ai comandi che non generano nulla - ma la maggior parte di essi lo fa se includi, ad esempio, -v"verboso". Attenzione per alcuni comandi -vsignifica "informazioni sulla versione di stampa". Dai un'occhiata nella pagina man per il comando per essere sicuro se e come funzionerà (alcuni comandi usano anche un interruttore diverso da -v).

Per convenzione, i comandi restituiscono anche un valore pari a 0 al termine. Questo a volte viene chiamato "stato di uscita" e normalmente non lo vedi, ma la shell ti mostrerà con echo $?. Provare

 ls /
 echo $?
 ls /nonexistantdir
 echo $?

Otterrai 0 e 2. Se cerchi nella pagina man lssotto "Stato di uscita", vedrai il criptico piuttosto aspro:

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

Quale può essere o non essere migliore di niente, ma il gioco è fatto.

Per lo meno, questo indica che il comando non è riuscito per qualche motivo. Lo stato di uscita ti consente anche di fare cose del genere:

/bin/foo && sudo bar

In &&questo caso significa "se il primo comando ha esito positivo", presumendo che il primo comando utilizzi la convenzione di restituire 0 (motivo per cui di solito lo fanno). Se /bin/foonon funziona, non può essere trovato, ecc., sudo barNon accadrà mai.

L'uso di una combinazione di messaggi di log ed esecuzione condizionale ( &&) dovrebbe avvicinarti molto più a capire il problema, o almeno ottenere informazioni che potrebbero essere utili agli altri per aiutarti a risolverlo. Senza di ciò, la maggior parte degli altri spesso può fare è indovinare.


1. È possibile ottenere lo stesso reindirizzamento dell'output per un intero script dall'interno utilizzando:

exec &> /var/log/myTestLog.txt

Nella parte superiore (o ovunque, e si applicherà a tutto il successivo).


2

Un aspetto importante che le persone tendono a dimenticare quando eseguono script come daemon è l'ambiente shell e $PATHin particolare le variabili. Nel tuo esempio, la seconda riga si basa su $PATH: il nome completo di sudoè /usr/bin/sudo, e la tua shell utente lo sa solo perché gli è stato detto di cercare /usr/binquando si cercano eseguibili. Lo stesso vale per bar.

Considerando che sudonon è necessario quando si eseguono script come daemon, la seconda riga dovrebbe apparire come:

/path/to/bar a
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.