Testez mon script (en toute sécurité, vous avez le code) Le sujet est résolu

Tout ce qui concerne la programmation.
Répondre
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

Bonjour à tous;

J'ai tenté avec difficulté car je maîtrise pas beaucoup le shell bash ( la syntaxe m'y apparaît compliquée entre les ', les ", les $ , les { et autre ! , etc... ). Bref, j'ai quand même avec l'aide diesel (merci à lui) réussi à faire tourner mon script. Mais il faudrait le tester : « C'est votre mission si vous l'acceptez ».

De quoi s'agit-il ?

C'est ce que j'appelle avec modestie un script pour compiler des scripts bash en exécutables directs. Bon, je n'ai rien inventé là, ça existe peut-être mais perso je le faisais à la main avant.

On a parfois le besoin de protéger des regards indiscrets nos scripts qui aident à la sécurisation, un exécutable compilé à partir du C bloquera la majorité sauf les gens aguerris à cette technique.

Donc mon script nommé "compil_moi" demande à l'utilisateur d'entrer le script qu'il veut compiler. Trois fichiers sont alors créés : le script avec l'extension .x, le script avec l'extension .x.c (ce qui nous intéresse pour la compilation du C) et enfin l'exécutable avec l'extension .e

Je n'ai pas pensé à supprimer les deux premiers quand l'exécutable est construit. je rajouterai plus tard quand les tests seront finis c'est à dire quand ce petit script, écrit à la truelle, aura été testé par quelques un(e)s d'entre-vous.

Donc si vous avez le temps et l'envie testez mon petit "compil_moi" dont le code suit :

Code : Tout sélectionner

#!/bin/bash
echo "Création d'un executable (extension .e) à partir d'un script bash de même nom."
echo "°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°"
echo ""

# Demander à l'utilisateur le fichier et son chemin complet à compiler avec shc
echo "Veuillez entrer le chemin du script à compiler (peut se faire par copier/coller à la souris) :"
read chemin_fichier

# Enlèver les ' au début et à la fin du chemein s'il y en a.
chemin_fichier=${chemin_fichier#\'}
chemin_fichier=${chemin_fichier%\'}

# Se positionner dans le dossier contenant le script à compiler
chemin=$(dirname "$chemin_fichier")

# Enlèver les ' au début et à la fin du chemein s'il y en a.
chemin=${chemin#\'}
chemin=${chemin%\'}

cd "$chemin"

# Effectuer la compilation avec shc
shc -v -f $chemin_fichier

# créer le fichier exécutable de même nom que le script mais avec l'extension .e
touch "${chemin_fichier%.*}.e"

 #compilation du code c obtenu avec shc 
 gcc *.c -o *.e

exit

Toutes vos critiques, toutes vos corrections, toutes vos améliorations seront les bienvenues et m'aideront à me familiariser avec le shell.

Bonne semaine à toutes et tous.
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

Bonjour,
Plutôt que de faire un read pour le nom complet du fichier, met le plutôt en argument de ta ligne de commande.

Code : Tout sélectionner

#!/bin/bash
echo "Création d'un executable (extension .e) à partir d'un script bash de même nom."
echo "°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°"
echo ""

# Demander à l'utilisateur le fichier et son chemin complet à compiler avec shc
echo "Veuillez entrer le chemin du script à compiler (peut se faire par copier/coller à la souris) :"
if [ -n "$1" ]; then
    chemin_fichier=$1
    if [ -d $chemin_fichier ]; then
.
.
reste de ton script
.
.
    else
        printf '%s\n' "Erreur: le chemin de fichier spécifié n'existe pas."
    fi
else
    printf '%s\n' "Erreur: pas de chemin de fichier spécifié."
fi
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

Bonjour,
Merci pour ta réponse.
Peux-tu svp m'expliquer ce que cela change ? (j'apprends)
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
diesel
Membre
Membre
Messages : 271
Inscription : 29 oct. 2022, 22:43
Status : Hors-ligne

Ben..., la suggestion de Zargos est bonne mais le bout de script qu'il donne n'est pas bon.

Avec ton script, tu fais :

Code : Tout sélectionner

Tu frappes le nom de ton application <ENTER>
affichage de la ligne "Veuillez entrer le chemin du script à compiler (peut se faire par copier/coller à la souris) :"
tu frappes le chemin du fichier à compiler <ENTER>
Ce que Zargos te suggère, c'est :

Code : Tout sélectionner

Tu frappes le nom de ton application suivi d'un espace puis du chemin de ton fichier à compiler <ENTER>
Le chemin de ton fichier à compiler est alors contenu dans la variable $1.

Dans ce cas, pas besoin du echo "veuillez..., ni besoin de transférer le contenu de la variable $1 dans la variable chemin_fichier. Autant travailler directement avec la variable $1.

Amicalement.

Jean-Marie
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

Ça ne change pas vraiment grand chose... Je préfère appeler mon application puis la laisser me demander ce que je dois faire.

En revanche, je ne sais si c'est possible mais une vraie simplification serait de n'avoir qu'à entrer le nom du script tout seul et que le code le recherche dans les fichiers.

Je remarque que je n'ai pas de contrôle sur la bonne marche, faut dire que j'ai fait dans le plus rapide et que ça ne s'adresse qu'à moi. C'est vrai qu'un utilisateur lambda doit être averti des erreurs potentielles.


Mais de tests, est-ce que certains en ont réalisé, quels sont les retours ?
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
diesel
Membre
Membre
Messages : 271
Inscription : 29 oct. 2022, 22:43
Status : Hors-ligne

D'abord, dans les bonnes pratiques, tu dois réaliser des contrôles sur les données entrées. Dans ton cas, hormis les éventuelles apostrophes à supprimer, tu devrais vérifier que le fichier existe et qu'il est lisible, puis éventuellement vérifier qu'il contient bien le shebang #!/bin/bash en tête de fichier. Tu devrais aussi vérifier que le chemin est bien un chemin valide et qu'il conduit bien à ton fichier.

Pour le compte rendu d'exécution, chaque application bien codée (c'est généralement le cas) envoie un code de retour qui te donne des informations sur son exécution. Il te suffit de récupérer ce code et d'afficher les messages correspondants.

Amicalement.

Jean-Marie
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

Je suis bien d'accord avec toi. Il faudrait que je me mette au travail sur les contrôles.

Pour le script en .sh à compiler, il faut considérer qu'il est fonctionnel sinon à quoi bon vouloir compiler un code non-fonctionnel ? L'utilisateur doit savoir où il en est.

Pour le contrôle de l'entrée, c'est vrai qu'un message serait de bon aloi pour spécifier une erreur de choix par exemple un fichier qui ne serait pas du type de script bash. Actuellement en cas d'erreur de saisie rien ne se passe, ce qui incite malgré tout à recommencer la saisie.

Sinon, je viens de le tester sur un script bash assez étoffé et miracle j'ai obtenu un beau petit exécutable. La journée s'annonce bonne :wink: ! Et je te la souhaite ainsi.
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

Je pourrais inclure ce qui suit après la saisie :

Code : Tout sélectionner

# Vérifier si le fichier existe
if [[ ! -f "$chemin_fichier" ]]; then
    echo "Le fichier du script n'existe pas ou le chemin n'est pas le bon !"
    sleep 10
    exit 1
fi

# Vérifier que le script est bien du type de bash attendu.
type=$(head -n 1 "$chemin_fichier")

# Vérifier si la première ligne est un shebang Bash
if [[ "type" == "#!/bin/bash" ]];  then
      
      # lancer le reste du script
     
else
  echo "$chemin_fichier" n'est pas un script bash. Veuillez recommencer votre saisie."
  sleep 20

fi
Tu en penses quoi ?

PS mon script s'auto-compile parfaitement .
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
piratebab
Site Admin
Site Admin
Messages : 5851
Inscription : 24 avr. 2016, 18:41
Localisation : sud ouest
Status : En ligne

Pense à bien numéroter tes codes d'erreurs, et à fournir un lexique.
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

Blanco a écrit : 30 sept. 2024, 15:39 Bonjour,
Merci pour ta réponse.
Peux-tu svp m'expliquer ce que cela change ? (j'apprends)
Le paramètre et le read ne prennent pas les entrée complètement pareil. Et de fait quand tu lances ta commande ensuite tu sais quel paramètre tu avais testé.
Je préfère autant que possible les paramètres au read (ca permet notamment de lancer facilement ton script à partir d'un autre script)
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

Blanco a écrit : 01 oct. 2024, 10:16 Je pourrais inclure ce qui suit après la saisie :

Code : Tout sélectionner

# Vérifier si le fichier existe
if [[ ! -f "$chemin_fichier" ]]; then
    echo "Le fichier du script n'existe pas ou le chemin n'est pas le bon !"
    sleep 10
    exit 1
fi

# Vérifier que le script est bien du type de bash attendu.
type=$(head -n 1 "$chemin_fichier")

# Vérifier si la première ligne est un shebang Bash
if [[ "type" == "#!/bin/bash" ]];  then
      
      # lancer le reste du script
     
else
  echo "$chemin_fichier" n'est pas un script bash. Veuillez recommencer votre saisie."
  sleep 20

fi
Tu en penses quoi ?
# lancer le reste du script

else
echo "Erreur : $chemin_fichier n'est pas un script bash. Veuillez recommencer votre saisie."
sleep 20
fi
Le sleep est inutile dans le test du chemin pour le message d"erreur. tu en met beaucoup trop et ca va ralentir le fonctionnement de ton script.
Il y avait un " en trop dans l'echo du message d'erreur.
pour le test du shebang, il t'aurait juste suffit de fait directement

Code : Tout sélectionner

if [ -n "`grep -E '^[#]!\/bin\/bash' $chemin_fichier`" ]; then
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

Merci pour tes réponses.

Pour le sleep 20, je pensais laisser le temps à l'utilisateur de lire le message mais c'est vrai que 20 secondes ça peut paraître long.

Je me regarde faire : je bricole (dans la douleur des erreurs successives, vu mon niveau) un script bash. Si je parviens à le rendre fonctionnel, je suis déjà satisfait. S'il me convient donc et que je veux en cacher le code pour des raisons de sécurité, je le compile avec mon autre script déjà compilé lui-même par lui-même (une espèce de mouvement perpétuel ?). En fait, je ne compile que si le script bash est fonctionnel donc ai-je besoin de contrôler qu'il est fonctionnel si je le sais déjà ?

Mais évidemment, s'il s'agit de produire un exécutable à distribuer, qui compile du bash , je dois mettre des contrôles d'erreurs. Et c'est intéressant pour mon apprentissage.
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

Blanco a écrit : 01 oct. 2024, 11:02 Merci pour tes réponses.

Pour le sleep 20, je pensais laisser le temps à l'utilisateur de lire le message mais c'est vrai que 20 secondes ça peut paraître long.

Je me regarde faire : je bricole (dans la douleur des erreurs successives, vu mon niveau) un script bash. Si je parviens à le rendre fonctionnel, je suis déjà satisfait. S'il me convient donc et que je veux en cacher le code pour des raisons de sécurité, je le compile avec mon autre script déjà compilé lui-même par lui-même (une espèce de mouvement perpétuel ?). En fait, je ne compile que si le script bash est fonctionnel donc ai-je besoin de contrôler qu'il est fonctionnel si je le sais déjà ?

Mais évidemment, s'il s'agit de produire un exécutable à distribuer, qui compile du bash , je dois mettre des contrôles d'erreurs. Et c'est intéressant pour mon apprentissage.
oui les contrôle d'erreur sont nécessaire.
comme ton script est utilisé dans une console, il y a toujours le temps de lire les messages.
C'est d'ailleurs mieux de l'executer dans une console, justement pour ça
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

C'est curieux bien que je lançais le script dans une console, lors de la mise au point je tombais sur des erreurs qui fermaient systématiquement la console sans que j'ai le temps de lire quelque message et j'étais obligé de parsemer mon code de sleep 10 là où je pensais que l'erreur arrivait.
Que faire pour que s'affiche systématiquement un message qui fige la console lors d'erreur ?
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

Comment lances-tu le script dans une console?
Noamelement tu ouvre une fenêtre xterm et tu tapes

Code : Tout sélectionner

. ./monscript.sh
si celui est avec les droits execution, ou bien

Code : Tout sélectionner

sh ./monscript.sh
voici un exemple de script avec paramètres et fonction.
les paramètres sont juste:
- Nom du fichier
- Les droits d'accès voulus en octal
- le user voulu
- le group voulu

Le script teste si les droits sont conformes avec le lancement:

Code : Tout sélectionner

. ./la_librairie.sh
f_access_check fichier 0750 user1 group1
avec un résultat
$ f_access_check _postinst/000-base-lib.postinst 0750 user1 group1
Checking access to _postinst/000-base-lib.postinst is configured with:
- access mode = 0750
- user name = user1
- group name = group1

- Check results:
- File: "_postinst/000-base-lib.postinst"
Mode: "0755" should be mode: "750" or more restrictive
Owned by: "toto" should be owned by "user1"
Owned by group "totog" should be group owned by: "group1"
Désolé c'est en anglais pour des raison de diffusion. Un jour quand j'aurais le temps, je le ferais en mode langue selective français/anglais mais pas le temps.
Ce script est issue d'une librairie de 5000 lignes environs :smile:

Avec le script bien sur:

Code : Tout sélectionner

#!/bin/bash
##################################################
# Base functions library
##################################################
#
f_access_check()
{
        if [ $# -ne 4 ]; then
                printf '%s\n' "Check failed: missing parameter. Should be: file access_mode user group"
        else
                l_file=$1
                l_access_mode=$2
                l_user_name=$3
                l_group_name=$4
                l_pmask="$( printf '%0*o' 3 $(( 0777 & ~$l_access_mode )) )"
                printf '%s\n' "Checking access to $l_file is configured with:"
                printf '%s\n' " - access mode = $l_access_mode" " - user name = $l_user_name" " - group name = $l_group_name"
                a_output=(); a_output2=(); 
                f_file_access()
                {                       
                        while IFS=: read -r l_file_mode l_file_owner l_file_group; do
                                a_out2=()
                                l_maxperm="$( printf '%0*o' 3 $(( 0777 & ~$l_pmask )) )"
                                if [ $(( $l_file_mode & $l_pmask )) -gt 0 ]; then
                                        a_out2+=("    Mode: \"$l_file_mode\" should be mode: \"$l_maxperm\" or more restrictive")
                                fi
                                if [ "$l_file_owner" != $l_user_name ]; then
                                        a_out2+=("    Owned by: \"$l_file_owner\" should be owned by \"$l_user_name\"")
                                fi
                                if [[ ! "$l_file_group" =~ $l_group_name ]]; then
                                        a_out2+=("    Owned by group \"$l_file_group\" should be group owned by: \"$l_group_name\"")
                                fi
                                if [ "${#a_out2[@]}" -gt "0" ]; then
                                        a_output2+=("  - File: \"$l_file\"" "${a_out2[@]}")
                                else
                                        a_output+=("  - File: \"$l_file\"" \
                                        "Correct: mode: \"$l_file_mode\", owner: \"$l_file_owner\", and group owner: \"$l_file_group\"")
                                fi
                        done < <(stat -Lc '%#a:%U:%G' "$l_file")
                }
                
                f_file_access
                if [ "${#a_output2[@]}" -le "0" ]; then
                        printf '%s\n' "" " - Accesses are as requested" ""
                else
                        printf '%s\n' "" " - Check results:" "${a_output2[@]}" ""
                fi
        fi
}       
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

Oui d'accord mais je lance mon script de façon simple : je le double-clic. À la demande du fichier, je le colle après l'avoir copié dans le gestionnaire de fichier.s
Je sais c'est simpliste mais c'est avant tout ce que je recherche. Je passe exclusivement par la souris.
Maintenant qu'il marche bien, ça me suffit. Je l'ai même compilé avec lui-même comme je l'ai dit ce matin.
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

dans ce cas met plutot une pause en fin de script qui attendra que tu tapes une touche pour passer à la suite et se terminer.
Blanco
Membre
Membre
Messages : 126
Inscription : 03 août 2023, 14:55
Status : Hors-ligne

C'est à dire que je me place dans Caja et j'utilise la souris comme tout reste dans le même dossier affiché à l'écran je vois tout de suite apparaître les fichiers de la compil. Je pourrais effacer les deux fichiers en .x et .x.c avec une commande dans le script mais comme j'ai la souris en main je je fais manuellement.

Fort de tous vos conseils pour lesquels je vous remercie, je ferai peut-être un exécutable bien propre avec contrôle des erreurs et tout et tout... Mais c'est sans compter sur la procrastination ! :wink:
Mini PC Geekom i5 / 16 giga Bookworm + Mate

Fidèle à Debian depuis la version 8, après Ubuntu.
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

pour info au fait:

Code : Tout sélectionner

# Vérifier si le fichier existe
if [[ ! -f "$chemin_fichier" ]]; then
    echo "Le fichier du script n'existe pas ou le chemin n'est pas le bon !"
    sleep 10
    exit 1
fi
C'est plutot [ ! -e, car :

-f ce fichier est un fichier normal (ni un répertoire ni un fichier de périphérique)
-e ce fichier existe

Par extension -f suppose l'existance (i.e.: -f implique -e)
Avatar de l’utilisateur
zargos
Membre
Membre
Messages : 197
Inscription : 07 juil. 2023, 13:34
Status : Hors-ligne

Blanco a écrit : 03 oct. 2024, 09:34 C'est à dire que je me place dans Caja et j'utilise la souris comme tout reste dans le même dossier affiché à l'écran je vois tout de suite apparaître les fichiers de la compil. Je pourrais effacer les deux fichiers en .x et .x.c avec une commande dans le script mais comme j'ai la souris en main je je fais manuellement.

Fort de tous vos conseils pour lesquels je vous remercie, je ferai peut-être un exécutable bien propre avec contrôle des erreurs et tout et tout... Mais c'est sans compter sur la procrastination ! :wink:
utilisant ta souris, ça implique que ton script doit déterminer le contexte et l'environnement d’exécution pour pouvoir fonctionner correctement.
Répondre