Automatisation Twitter bot
Afin de pouvoir construire un bot automatisé Twitter qui Tweete à chaque intervalle de temps, il faut que nous installions une tâche récurrente dite « Cron ».
Ques ce qu’est cron ?
Un « daemon » est un processus qui est en exécution en arrière-plan au niveau du système d’exploitation.
Cron est un daemon offrant la possibilité d’exécuter du code informatique à des moments explicites et généralement de manière récurrente, et ce, réglé antérieurement.
Cron est en quelque sorte le planificateur, par contre crontab est un programme permettant la lecture, la modification et la suppression des tâches Cron préalablement initialisées. De plus, Crontab permet d'ajouter des tâches Cron.
Crontab vient des mots « chronos » venant du grec et voulant dire temps et du mot « table » de l'anglais voulant dire tableau.
Grâce à Cron, nous allons exécuter un script bash tous les six heures. Ce dernier sera le déclencheur du code informatique responsable de formuler le contenu et de « tweeter » le tweet. La génération de tweets se fera grâce à de l'intelligence artificielle. Nous verrons dans les articles prochains comment utiliser l'API d'open AI afin d'y parvenir.
Afin de connaître les raisons pourquoi je documente ce projet et de l'intérêt, veuillez lire cet article : liens pour créer un bot Twitter personnalisé IA.
Le bash script d’extention .sh
Comme première étape, il nous faut un fichier d’extension .sh avec du code informatique écrit dessus.
Ce code sera utilisé pour effectuer des tests dans le but de vérifier le fonctionnement de cron.
De surcroît, nous allons utiliser ce script test afin de vérifier si notre configuration de visualisation des logs qui sont issus :
- du code initié par la commande « echo » et, ou
- d’erreur(s) d’exécution du script fonctionnent comme prévu.
Creation du fichier
Connectez à votre serveur distant par SSH, soit par l’intermédiaire d’un terminal ou programme client.
Créer un fichier finissant avec l’extension .sh.
touch cron-poc-1.sh
Personnellement, j'ai créé ce fichier sous ~/scripts/, mais vous êtes libre de le créer où il vous semble logique. Assurez-vous d’exécuter la commande pwd afin de connaître le chemin absolu de votre script.
pwd
Code du fichier d’extention .sh
Maintenant, utilisez votre éditeur de texte préféré afin d’intégrer le code qui sera exécuté aux moments que vous auriez configurés par cron.
Dans mon cas, j’utilise nano comme éditeur, car simple et efficace. N’oubliez pas d’inclure sudo avant la commande. Sudo permet d’exécuter des commandes en tant que « super user do » (utilisateur super exécute). Sudo permet d’avoir les permissions pour exécuter une commande.
La commande ci-bas vous invitera à entrer votre mot de passe que vous avez configuré lorsque vous avez créé votre utilisateur machine.
sudo nano cron-poc-1.sh
Puis copier-coller le code suivant :
#!/bin/bash
echo "Running script as user: $(whoami)"
echo "PATH is: $PATH"
echo "Home directory is: $HOME"
echo "Current working directory is: $(pwd)"
echo "CRON POC 1, 123 testing." >> /home/[utilisateur]/scripts/logs/cron-poc-1.txt
Explication du code
#!/bin/bash
- # est appelé « shebang ». Il sert à dicter au système que ce script doit être exécuté en bash. Bash est un « shell » typique des systèmes de type Unix. Son « path » (chemin) se trouve dans /bin/bash
echo "Running script as user: $(whoami)"
- Echo est une commande utilisée pour afficher (« print ») des lignes de texte en « standard output » (sortie standard).
- Dans les scripts Bash, la syntaxe $() permet d'exécuter une commande à l’intérieur d’une autre commande. Elle permet de placer une commande imbriquée transformée en sa sortie (« output ») littérale et exécutable. La commande imbriquée est donc exécutée avant la commande externe pour que cela fonctionne. Cette syntaxe est aussi souvent utilisée lors d’attribution (« assignation ») d’une variable. Il s'agit d'une fonctionnalité puissante des scripts shell, permettant l'incorporation des résultats de commandes dans une commande externe.
$(whoami) illustre le concept. $(whoami) est dite une « command substitution » (substitution de commande). Elle permet d’exécuter la command whoami et puis de remplacer sa sortie (« output ») à l’intérieur du fil littéral (« string literal »). whoami sort (« outputs ») le nom d'utilisateur de la session. La commande externe (echo "Running script as user: $(whoami)") est exécutée en remplaçant $(whoami) avec ce qu’il a préalablement sorti (« output »).
echo "PATH is: $PATH"
- $PATH est une variable de l’environnement qui contient un fil literal (« string literal ») ; des chemins se trouvent les fichiers d’exécutables, séparés par deux points.
echo "Home directory is: $HOME"
- Cette ligne utilise echo pour imprimer un message.
- « Le répertoire personnel est : " est la partie littérale du message.
- $HOME est une variable d'environnement qui contient le chemin d'accès au répertoire personnel de l'utilisateur actuel. Cette ligne imprime le répertoire personnel de l'utilisateur exécutant le script.
echo "Current working directory is: $(pwd)"
- Pwd imprime le répertoire de travail actuel.
echo "CRON POC 1, 123 testing." >> /home/[utilisateur]/scripts/logs/cron-pocc-1.txt
- Cette ligne echo « CRON POC 1, 123 testing. ».
- >> est un opérateur de redirection qui ajoute la sortie de la commande à gauche de l’opérateur au fichier spécifié par son chemin à droite de l’opérateur. Si le fichier n'existe pas, il sera créé.
- Ici, on place « CRON POC 1, 123 testing. » dans le fichier nouvellement créé cron-pocc-1.txt
Pour résumer, ce script imprime des informations sur l'environnement de l'utilisateur qui l'exécute et du système, puis enregistre un message dans un fichier.
Remarque
Un chemin (« path ») relatif empêche le script de fonctionner. Si un chemin (« path ») relatif est dans le script, cela va induire une erreur.
J’avais expérimenté en mettant un chemin relatif et cela avait produit un message d’erreur.
Exemple de chemin absolu :
/home/[utilisateur]/scripts/logs/cron-poc-1.txt
Exemple de chemin relatif :
./logs/cron-poc-1.txt
Lorsque nous mettons un chemin relatif dans le script, voilà l’erreur que nous récoltons. Cela a lieu lorsque la tâche cron s'exécute et le message d’erreur s'enregistre dans le fichier : cron-poc-1.txt.
/home/[utilisateur]/scripts/cron-poc-1.sh: line 6: ./logs/cron-poc-1.txt: No such file or directory
Configuration des permissions du script
Maintenant que notre script a été écrit et sauvegardé. Il est temps de s’assurer que nos permissions sont configurées de façon à ce que le script puisse être exécuté par cron.
D’abord, vérifions les permissions actuelles et identifions ce qui doit changer. Pour ce faire, on lance la commande ls -la afin de voir les permissions du fichier : cron-poc-1.sh
ls -la
-rw-r—r— 1 root root 208 Dec 30 11:41 cron-poc-1.sh
On doit changer le propriétaire du fichier de root à [utilisateur] et le groupe de root à [utilisateur]. Ensuite, on doit ajouter la permission d'exécuter au propriétaire
On exécute ces commandes pour le faire :
sudo chown [utilisateur]:[utilisateur] /home/[utilisateur]/scripts/cron-poc-1.sh
chmod 744 /home/[utilisateur]/scripts/cron-poc-1.sh
Cela rend les permissions du fichier à ce qui suit :
-rwxr--r-- 1 [utilisateur] [utilisateur] 269 Jan 4 19:03 cron-poc-1.sh
L'utilisateur dispose de la permission de pouvoir exécuter le fichier.
chown est une commande utilisée pour changer le propriétaire et/ou le groupe d'un fichier ou d'un répertoire dans les systèmes Unix et Linux. Le nom chown vient de l'anglais et signifie "change owner" (changer de propriétaire).
chmod est la commande qui permet de modifier les permissions. Chmod vient de l’anglais et veut dire changer de mode (« change mode »). Le 7 signifie qu'on configure le propriétaire (l'utilisateur) pour obtenir les permissions de lire, écrire et d’exécuter le fichier. 44 donne la permission de lire au groupe et aux autres.
Remarque 1
Une tâche cron exécute un script sous le compte utilisateur qui a créé la tâche cron.
Chaque utilisateur sur un système de type Unix, y compris root, peut avoir sa propre crontab (table cron) pour gérer ses tâches cron individuelles.
Remarque 2
J’avais expérimenté en omettant de modifier les permissions et lors de l’exécution du script, j'obtenais ce message d’erreur :
cat cron-poc-1.txt
/bin/sh: 1: /home/[utilisateur]/scripts/cron-poc-1.sh: Permission denied
Nous allons voir comment configurer le système afin de pouvoir visualiser les logs d’impressions de commandes « echo » et des messages d’erreurs générés lors de l’exécution du script.
Remarque 3
On aurait pu juste modifier les permissions avec cette commande :
chmod +x /home/[utilisateur]/scripts/cron-poc-1.sh
Mais cela aurait résulté en cela :
-rwxr-xr-x 1 [utilisateur] [utilisateur] 208 Dec 30 11:41 cron-poc-1.sh
On attribue en trop la permission d'exécution au groupe et aux autres. Cela n'est pas nécessaire, mais reste valide pour exécuter le script bash.
On essaye de respecter le principe du moindre privilège (« principle of least privilege »).
Ou mettre les littérales d’echo et les messages d’erreurs échéant ?
Tous les logs générer par la commande echo du script sh on besoin d’être imprimer quelque part. On cree une fichier logs sous le ficher scripts.
Ce fichier enregistra également les message d’erreurs de l’execution du script le cas échéant.
Creation du repertoire logs
mkdir logs
Remarque
Le fichier lui-même « cron-poc-1.txt » ne nécessite pas d’être créé.
Le fait qu’il soit déclaré par le script qui sera exécuté ou dans le crontab (que nous abordons plus tard) impliquera ca creation automatiquement.
Explications des taches Cron et configuration
Le script est prêt. Le fichier de réception des logs est prêt. On s’apprête maintenant à configurer cron pour exécuter le script tous les six heures.
Quelles sont les possibilités Cron ?
À la base, on définit une tâche cron sous le format suivant :
* * * * * [le chemin absolu vers le script d’extension .sh]
Les 5 Astérix peuvent être réglés en un chiffre. Chaque position des astérisques correspond à une unité de temps. En allant de gauche à droite, nous avons :
- L'unité minute (0 - 59)
- L'unité heure (0 - 23, où 0 correspond à minuit)
- L'unité jour du mois (1 - 31)
- L'unité mois (1 - 12)
- L'unité jour de la semaine (0 à 7, où 0 et 7 représentent le dimanche)
Chaque position représente une contrainte de moments d’exécution.
Chaque position est une contrainte relative par rapport à l’unité de temps de sa position.
En laissant l’astérisque par défaut, on implique que la contrainte d’exécution se fait à chaque unité de temps de la position.
On écrit les contraintes une à une par rapport à chaque position.
On fait l’inclusion des contraintes pour obtenir les moments d’exécution du script.
Si vous voulez mieux comprendre, veuillez lire les exemples au lien suivant : des exemples cron.
Le sujet de cet article n’est pas la syntaxe cron mais la configuration d’une tâche récurrente.
Configuration de notre planificateur de tache a execution récurent Cron ?
Notre projet nécessite par exemple que le nôtre compte Twitter tweete tous les jours.
Pour ce faire, nous exécutons la commande suivante :
crontab -e
Cela va ouvrir votre crontab. Dessus, vous pouvez écrire votre commande à syntaxe cron. Dans mon cas :
0 0 * * * /home/[utilisateur]/scripts/cron-poc-1.sh
La minute 0 équivaut à la contrainte : à la minute 00.
Heure 0 équivaut à la contrainte : à l’heure 00, c'est-à-dire l'heure 24 :00 H
L’inclusion des contraintes est donc à la première minute, à tous les 24H à minuit, de chaque jour, de chaque mois, de chaque jour de semaine.
Tous les jours, à minuit, le script s’exécute.
Remarque 1: mettre les messages d’erreurs et les logs dans le meme text
Nous modifions la tâche cron à la commande suivante :
0 0 * * * /home/[utilisateur]/scripts/cron-poc-1.sh >> /home/[utilisateur]/scripts/logs/cron-poc-1.txt 2>&1
Cela permet de mettre les messages d’erreurs issus d’une exécution erronée du script au même emplacement texte que les sorties générées par le script. On parle des commandes echo du script en l’occurrence.
Cette partie :
/home/[utilisateur]/scripts/cron-poc-1.sh >> /home/[utilisateur]/scripts/logs/cron-poc-1.txt
Le >> est un opérateur des systèmes d’exploitation Linux de redirection (« redirect »). En l'occurrence, tout le contenu issu de l’exécution du script est redirigé. Ce type de redirection ajoute (« appends ») la sortie (« outputs ») de l’exécution au fichier : cron-poc-1.txt.
Cette partie :
2>&1
Dans les systèmes d'exploitation Linux, il y a 2 types de sorties (« outputs ») :
- Les sorties standards (« standard output » nommé stdout) : Elles sont invoquées par ce qu’on appelle un descripteur de fichier 1.
- Les sorties d’erreurs (« standard error » nommé stderr : elles sont invoquées par ce qu’on appelle un descripteur de fichier 2.
Avec 2>&1 on fait une redirection des sorties d’erreurs vers le même emplacement où sont redirigées les sorties standards.
Appendice de commandes utiles
cat /home/[utilisateur]/scripts/logs/cron-poc-1.txt
sudo nano /home/[utilisateur]/scripts/cron-poc-1.sh
crontab -e
Voir les 5 lignes les plus récentes
tail -n 5 /home/[utilisateur]/scripts/logs/cron-poc-1.txt
Effacez le contenu du fichier journal :
> /home/[utilisateur]/scripts/logs/cron-poc-1.txt
Remarque 2 : redirection .sh ou redirection cron?
Si vous n'avez pas remarqué, il y a deux types de redirections pour assurer l'impression des sorties standards. Celles issues du script .sh et celles issues du cron.
Redirection .sh
sudo nano cron-poc-1.sh
>> ./logs/cron-poc-1.txt
Redirection cron
crontab -e
>> /home/[utilisateur]/scripts/logs/cron-poc-1.txt
J'ai fait des tests pour comprendre le comportement et si les redirections ont effet ou pas. Il y a quatre cas possibles :
- Redirection .sh et pas de redirection cron donnent une impression de la ligne concernée par le « echo "CRON POC 1, 123 testing." >> ./logs/cron-poc-1.txt »
- Pas de redirection .sh et redirection cron donnent une impression de tous les échos.
- Redirection .sh et redirection cron donnent une impression de tous les échos (priorité à la redirection cron et redirection .sh est omis).
- Redirection .sh et pas de redirection cron ne donnent pas d'impressions du tout.
Prochaines étapes
Maintenant que notre serveur dispose de la capacité d’exécuter du code à chaque intervalle de temps, il faut que l’on configure le script pour faire déclencher un point de terminaison HTTP(S) (« HTTP(S) endpoint »).
Ce point de terminaison HTTP(S) sera programmé en JavaScript avec NGINX, Node.js et express. Le point de terminaison se chargera de formuler le tweet et de le tweeter.
Pour voir l'implémentation concrète et la suite de cette série d'articles : la meilleure conception : cron, node js, express et ubuntu
Conclusion
Dans cet article, nous avons appris comment configurer une tâche récurrente sur un serveur. On a configuré la tâche sous crontab en spécifiant que les logs d’erreurs et standards se dirigent vers le même fichier.
Sur le script d’extention .sh on a listé une série de commandes pour générer en sorties des informations basiques.