Consigner la sortie de l'arrière-plan ou du script de démarrage

10

J'ai un court script qui est exécuté par un démon système pour des événements particuliers. Je sais que l'événement se produit et que le script est en cours d'exécution, mais il ne fait pas ce que je souhaite. Étrangement, il le fait lorsque je l'exécute manuellement, donc je suis très confus.

Comment savoir ce qui se passe? Le script est essentiellement une série de commandes comme celle-ci:

/bin/foo on 3
sudo bar a
Boucles d'or
la source
Je comprends que cela est destiné à être un tutoriel sur le débogage des scripts système, mais c'est un peu trop U&L. J'ai mal lu le titre et suggérerais que "Consigner la sortie d'un script système pour le débogage" rendrait le but plus clair. De plus, mon cerveau se fige lorsque je lis ces foo barexemples, je préfère quelque chose qui ressemble plus au monde réel. Je suis réticent à modifier un article, alors je vous laisse le soin de penser que cela peut être amélioré.
Milliways
1
@ Milliways Vous avez raison, le "script système" était de toute façon un terme impropre, j'ai donc changé le titre. Je ne suis pas d'accord sur le truc du foobar - les gens doivent apprendre à reconnaître le jargon / les expressions familières communes comme ils le pourraient dans n'importe quelle culture. De plus, c'est toujours un bon rire une fois que vous avez réuni les deux.
goldilocks

Réponses:

8

Tout d'abord, si le script est exécuté par un démon système et que ce démon s'exécute avec les privilèges root, vous n'avez pas besoin de l'utiliser sudo. Cela inclut init(et systemd), ce qui inclut rc.local. Si ce démon ne s'exécute pas avec les privilèges root, il sudone fonctionnera pas à moins qu'il ne /etc/sudoerssoit configuré pour autoriser cela (et sans mot de passe). Les utilisateurs de Raspbian peuvent être déroutés par cela car l' piutilisateur est autorisé à faire quoi que ce soit par défaut (et si vous regardez dedans, /etc/sudoersvous verrez comment cela est accompli).

Ensuite, vous pouvez capturer la sortie de n'importe quel bashscript, ou de tout ensemble de commandes à l'intérieur d'un script bash, en les exécutant dans un sous-shell comme ceci: 1

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

Le ()indique un sous-shell . Toutes les sorties de tout ce qui se trouve à l'intérieur sont redirigées vers un /var/log/myTestLog.txtfichier. Quelques notes:

  • &>est un bashisme , donc si le script est exécuté via un shebang sur la première ligne, il devrait l'être #!/bin/bash, pas seulement /bin/sh. Les «bashismes» ne fonctionnent que dans la bashcoquille.

    Cela inclut /etc/rc.local, qui par défaut utilise /bin/sh(c'est-à-dire, oui, vous pouvez le changer en toute sécurité /bin/bash).

  • /var/lognécessite des privilèges root pour écrire. Si le processus n'en a pas, utilisez ou créez un répertoire que vous savez qu'il peut. En cas de doute, si vous pouvez tester cela sans avoir à arrêter ou redémarrer le système, utilisez /tmp, qui est accessible en écriture (c'est-à-dire par n'importe qui). Cependant, /tmpne persiste pas entre les bottes. Il s'agit également d'une petite partition basée sur la RAM, donc n'y écrivez pas de données. Ce n'est pas votre carte SD [en fait sur les versions actuelles de Raspbian, mais ne comptez pas sur cela dans la pratique] .

  • &>remplacera quoi que ce soit myTestLog.txt. Si vous souhaitez ajouter à un journal existant, ce qui peut être une bonne idée à des fins de débogage, utilisez &>>. Vous pouvez ensuite ajouter une commande au début de ce sous-shell comme ceci:

    echo Starting $(date)

    Pour séparer les informations de chaque exécution. Si vous n'êtes pas sûr de ce que cela fait, essayez sur la ligne de commande.

Ce dernier point est une bonne illustration de quelque chose que vous pouvez faire en ce qui concerne les commandes qui ne produisent rien - mais la plupart le font si vous incluez, par exemple, -vpour "verbeux". Attention à certaines commandes -vsignifie "imprimer les informations de version". Jetez un œil dans la page de manuel de la commande pour être sûr si et comment cela fonctionnera (certaines commandes utilisent également un commutateur différent de -v).

Par convention, les commandes renvoient également une valeur de 0 une fois terminées. Ceci est parfois appelé le "statut de sortie" et vous ne le voyez pas normalement, mais le shell vous le montrera echo $?. Essayer

 ls /
 echo $?
 ls /nonexistantdir
 echo $?

Vous obtiendrez 0 et 2. Si vous recherchez ensuite dans la page de manuel lssous "État de sortie", vous verrez le cryptique plutôt non spécifique:

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

Ce qui peut ou non être mieux que rien, mais voilà.

À tout le moins, cela indique que la commande a échoué pour une raison quelconque. Le statut de sortie vous permet également de faire des choses comme ceci:

/bin/foo && sudo bar

Dans &&ce cas, le signifie "si la première commande réussit", en supposant que la première commande utilise la convention de retour de 0 (c'est pourquoi ils le font généralement). Si /bin/foocela ne fonctionne pas, est introuvable, etc., sudo barcela ne se produira jamais.

L'utilisation d'une combinaison de messages de journalisation et d'exécution conditionnelle ( &&) devrait vous permettre de comprendre le problème beaucoup plus près, ou au moins d'obtenir des informations qui pourraient être utiles à d'autres pour vous aider à résoudre le problème. Sans cela, le plus que quiconque puisse faire est de deviner.


1. Vous pouvez effectuer la même redirection de sortie pour un script entier de l'intérieur en utilisant:

exec &> /var/log/myTestLog.txt

En haut (ou n'importe où, et cela s'appliquera à tout ce qui suit).

Boucles d'or
la source
2

Un aspect important que les gens ont tendance à oublier lors de l'exécution de scripts en tant que démons est l'environnement shell, et $PATHvariable en particulier. Dans votre exemple, la deuxième ligne repose sur $PATH: le nom complet de sudois /usr/bin/sudo, et votre shell utilisateur ne le sait que parce qu'il lui a été demandé de rechercher /usr/binlors de la recherche d'exécutables. Il en va de même pour bar.

Étant donné que cela sudon'est pas nécessaire lors de l'exécution de scripts en tant que démons, votre deuxième ligne devrait ressembler à:

/path/to/bar a
Dmitry Grigoryev
la source