Ca marche bien mais pas avec Crontab

Bonjour.

J’ai bien avancé sur mon projet de « domotique » (contrôle de sorties GPIO à distance) mais un problème me tiens en échec depuis plusieurs semaines.
J’ai fait plein de recherches, plein d’essais mais rien n’y fait.

J’ai développé un petit serveur en JavaScript qui est lancé par nodejs.

Si je tape « node /var/www/html/serveur.js » en mode console avec Putty, tout fonctionne bien.
Que je soit logué avec « pi » ou en « root ».

Par contre, quand j’ajoute exactement la même commande « @reboot node /var/www/html/serveur.js » avec « sudo crontab -e » ça ne marche pas !

Je suis sur un Pi3b avec Bullseye light 32bits.
Installation très standard, j’ai juste ajouté nodejs et WiringPi.

La moindre idée ou piste de recherche serait la bienvenue.
Merci.

hello,

de mémoire :roll_eyes: Il me semble qu il faut indiquer le path de l exécutable
@reboot /??/???/node /var/www/html/serveur.js

Merci pour l’aide.
Donc se serai /usr/bin/node …
J’essaie…
et beh non, c’est pas mieux.
Merci quand même.

Bonjour,

J’ai pas tout bien compris, ne connaissant pas node. Mais je pense que c’est une piste

Edit: autre approche aller dans le répertoire du fichier js avant de lancer node

@reboot cd /var/www/html && node serveur.js

/!\ je ne sais pas si @reboot fonctionne avec le user pi. Essayer avec et sans le chemin de l’executable node.

A+

Merci car j’ai appris quelque chose.
C’est tout bête mais je ne connaissait pas cette syntaxe « && » qui permet d’enchainer plusieurs commandes sur une seule ligne.
J’avais contourné le problème en indiquant à chaque fois le chemin complet « /var/www/html/xxxxx.xx » dans le programme, ce qui est nul pour la portabilité du projet.

NodeJS (node) est une fonctionnalité qui permet d’exécuter un programme JavaScript de manière autonome, sans avoir à l’appeler par le html.
Donc bien pratique pour réaliser un petit serveur sans avoir à apprendre un nouveau langage.

Sinon, j’ai quand même un peu avancé.
Le problème est bien dans le programme serveur.js
J’ai retrouvé une ancienne version qui, elle, fonctionne parfaitement.
Il faut donc que je piste les modifications qui ont été faites après cette version qui marche, que je les passe en commentaire, puis je décommente ligne après ligne pour voir à quel moment ça foire.

Evidemment, je mettrai le projet en ligne quand il sera complètement fonctionnel.

Bon week-end.

Perso, pour éviter les erreur et faciliter l’édition, je conseil de faire un script bash (.sh). et de mettre les commandes que tu ferais manuellement dans ce dernier.

Tu auras qu’a lancer le script via cette commande dans le cron;

/chemin/du/script.sh &

Le « & » a la fin fait que le script sera lancé sans rester parent du process cron, ceci évite que le process enfant empêche cron de continuer de travailler sur cette commande (redo quand c’est répété) ou d’autres (continuer la liste).

Le process Cron peut être bloquer dans l’attente de la fin de travail d’un processus enfant, ce qui empêche au cron de faire la suite avec les autres entrées.

Merci pour l’aide.
J’avais déjà tenté de mettre ça dans un fichier .sh lancé par cron, mais ça n’a pas résolu le problème.
Le truc du « $ » à la fin est bon à savoir.

Bon, je tiens déjà un truc.
J’utilise la bibliothèque « child_process » qui permet d’exécuter des commandes système par le javascript.

const cp = require ("child_process");

Puis j’utilise cet bibliothèque pour lancer une commande wiringpi.

cp.execSync("gpio mode 21 out");

Cette simple ligne fonctionne bien quand je lance le script en console mais plante quand il est lancé par crontab.

[EDIT]
Croyez le ou pas !
J’ai résolu le problème en ajoutant un sudo dans le crontab

@reboot cd /var/www/html && sudo node serveur.js &

Je continue mes recherches

J’ai également remarqué une différence dans le traitement de certaines commandes avec cron.

Même en définissant un utilisateur, certaines commandes passe (très) mal. Le sudo est en effet une solution viable si bien utilisé.

Je crois que le problème est que l’utilisateur dans lequel exécute la commande via cron permet d’associer en effet l’environnement a cet utilisateur, mais que lors de manipulation avec les PID (pkill, kill, …), certaines application passe leur vérification utilisateur autrement et détecte celui de cron au lieu de celui que cron exécute, et bloque la commande. Dans le cas de sudo, il traite également la commande autrement, ce qui fait que le processus reconnais un autre utilisateur, ce n’est pas pour rien qu’y existe un paramètre pour charger l’environnement du terminal qui lance la commande que ceux de sudo. (c’est un peu dur à comprendre, je sais)

De mémoire (car utilisé que dans un seul cas), c’est sudo - commande, le « - » fait en sorte que des variables par exemple sont chargé. Si tu défini une $VAR dans ton terminal, il sera alors partagé avec sudo. Dans le cas normal, sudo charge des variables et autres choses de manière indépendante pour exécuter la commande. Consulter la documentation pour plus de détails et confirmer sur ce point.

J’ai rencontré ce problème sur un setup de camera IP, je démarre avec ffmpeg la lecture et transmission sans problème, mais en commande cron ou même init.d, j’ai un accès refusé, la commande sudo marche, mais ce n’est pas safe. Alors j’ai plutot opté pour un démarrage du script via le fichier ~/.profile, qui lui est démarré par l’utilisateur lui-même proprement.

Bien sur, ce n’est pas un usage efficace pour toutes les situations.


En « visuel »

cron process : user cron
 '-run cron pour user défini : user défini
   '-commande : user défini

Dans l’exemple, la commande s’exécute, l’application peut détecter le user en ce basant sur le parent, soit le process cron. Alors ce n’est pas le « user défini » mais « cron ».

cron process : user cron
 '-run cron pour user défini : user défini
   '-sudo commande : user défini
sudo commande : user défini
 '-commande : user défini

La avec sudo, par exemple, le process est lancé dans un autre processus, le parent est sudo, il lance la commande, l’utilisateur détecté sera celui de sudo, et il a été lancé et défini par « user défini ». Alors la commande s’effectue, malheureusement, avec le pouvoir root.


Après une légère réflexion, je crois que l’usage de screen pourrais résoudre le problème. Lancer un script qui démarre screen, devrais déjà détacher le screen du script de lancement (avec le paramètre pour démarrer détaché) et il sera sous le nom utilisateur du lanceur de script, fournis par le cron. Et cette solution te permet au besoin d’interagir ou de voir l’application exécuter. Et est l’option pour mes radio shoutcast.

Merci levelKro.

Bon, je dois dire que j’ai pas compris grand chose.
Ou plutôt si, j’ai compris que le problème venait de mon ignorance sur toutes ces histoires de compte, d’utilisateur, d’environnement, de log etc…
Un de ces jours, il faudra que je me documente sérieusement sur ce sujet.
Comme je suis un peu faignasse et que j’ai trouvé une solution qui fonctionne (même si je comprends pas vraiment pourquoi, ce qui est bête) je vais remettre à plus tard mes recherches et la lecture détaillée de ta réponse.

Quoi qu’il en soit, mon projet fonctionne.
Pour l’instant encore sur breadboard avec des LEDs.
Je vais laisser tourner quelques jours et faire divers essais avant de transférer en câblage définitif.

Après ça, j’envisage de le publier mais ça, je ne sais pas encore comment faire.