Forum Linux.général impossible de modifier un exécutable lorsqu'il est en exécution

Posté par . Licence CC by-sa.
Tags : aucun
2
20
fév.
2019

Bonjour,

voila j'ai crée un script :
#!/bin/bash
echo "coucou"
sleep 100
exit 0

et pendant que le processus est endormi, je modifie le code :
#!/bin/bash
echo "coucou"
sleep 100
echo "script modifié pendant l'exécution"
exit 0
et je m'attend à une erreur et pourtant le terminal me retourne bien au bout de 100 secondes l'echo "script modifié pendant l'exécution".

Il me semblait qu'il était impossible sous linux de modifier le code d'un programme en cours d'exécution, principalement pour la sécurité (je ne vois aucune autre raison). Donc comment est ce possible de faire ce que je viens de faire.

Merci d'avance pour votre aide

  • # Pas chez moi

    Posté par (page perso) . Évalué à 2 (+0/-0).

    Je viens de tester, et j'ai le comportement attendu : le script lancé avant modification m'affiche le message de la version lancé, et non celui de la version postérieure au lancement. Fait avec GNU bash, version 4.4.23(1).

    • [^] # Re: Pas chez moi

      Posté par (page perso) . Évalué à 2 (+0/-0).

      Pour être certain qu'on se comprenne bien sur le modus operandi :

      anglade@lermat13 ~ $ ./test.sh &  cat test.sh ; vi test.sh
      [1] 10981
      #!/bin/bash
      echo "coucou"
      sleep 20
      echo "pas modifié"
      #echo "script modifié"
      exit 0
      
      
      coucou
      anglade@lermat13 ~ $ cat test.sh
      #!/bin/bash
      echo "coucou"
      sleep 20
      #echo "pas modifié"
      echo "script modifié"
      exit 0
      
      
      anglade@lermat13 ~ $ pas modifié
    • [^] # Re: Pas chez moi

      Posté par . Évalué à 1 (+0/-0). Dernière modification le 20/02/19 à 11:59.

      bizarre…j'ai la version :
      GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)

      comment est possible ? un fichier de conf a modifier ?

      PS: oui c'est bien ca, augmente peut etre le sleep a 100, peut etre que le noyau ne se comporte pas de la meme facon avec un delay plus long

      • [^] # Re: Pas chez moi

        Posté par (page perso) . Évalué à 2 (+0/-0).

        Pour le numéro de version, ça dépend de la distribution. Vu qu'il y a moins d'un an entre nos versions, il paraît improbable que ce soit la source de la différence de comportements.
        Par ailleurs, le test en augmentant la durée de sleep (à 120 s) me donne toujours le même résultat : « pas modifié. »

        • [^] # Re: Pas chez moi

          Posté par (page perso) . Évalué à 3 (+1/-0). Dernière modification le 20/02/19 à 17:33.

          Bizarre : sauf erreur de ma part, POSIX impose que le fichier soit lu au fur et à mesure. C'est une bizarerie de POSIX, les interprètes classiques plus modernes lisent et parsent tout le fichier d'un coup, c'est beaucoup plus logique. Donc a priori, ǝpɐןƃu∀ nǝıɥʇʇɐW-ǝɹɹǝıԀ, ton bash doit être dans un mode où il s'autorise des non-POSIXeries. Peut-être une variable POSIXLY_CORRECT bizarrement positionnée ou un truc qui ressemble. En tous cas moi j'ai bien le comportement où la modif en cours d'exécution est prise en compte.

          Sinon, si on veut être sûr que tout le fichier est lu au démarrage, l'astuce classique est de l'encapsuler dans une paire d'accolades :

          {
          ...
          tout le script
          ...
          }
          

          Et là le shell est obligé d'aller jusqu'au } fermant avant de démarrer l'exécution.

          Bon, tout ça de mémoire, je ne retrouve plus mes sources.

    • [^] # Ça dépend de l’éditeur

      Posté par . Évalué à 4 (+2/-0).

      Quand on sauvegarde avec un éditeur, il peut soit :

      1. réécrire le fichier en place, mais s’il y a un problème au moment de l’écriture, le fichier peut être incohérent ;
      2. écrire dans un nouveau fichier, puis une fois que celui-ci est complètement écrit sans erreur, remplacer l’ancien par lui.

      Je pense que la grande majorité des éditeurs récents font le deuxième choix.

      Si un éditeur fait le premier choix, le fichier sera changé en cours d’exécution par un interpréteur qui le lit ligne par ligne.
      En éditant le fichier avec vi, j’obtiens le même comportement que cosmoff. Ce qui m’étonne, ce n’est pas tant que bash ligne le fichier ligne par ligne (il conserve des caractéristiques du Bourne shell, qui date d’une autre époque ; enfin c’est quand même déjà étonnant), que le fait qu’il ne verrouille même pas le fichier avec interdiction d’écriture pendant qu’il l’exécute !

      Si un éditeur fait le deuxième choix, bash continue de lire le fchier d’origine (même s’il est supprimé du système de fichiers et plus visible dans le répertoire, il est maintenu tant qu’un processus le garde ouvert).
      Si j’édite le fichier avec vim, l’exécution n’est pas modifiée.

      Peut-être certaines distributions ont-elles un lien sur vim à la place de vi, et dans ce cas toujours le comportement comme si le fichier n’avait pas été modifié en cours d’exécution.

      Cela dit, je n’avais jamais remarqué cette caractéristique de bash, probablement parce que j’évite d’utiliser vi (celui d’origine) et que je n’utilise probablement pas régulièrement autre chose qui ait le même comportement.

      ¯ : macron (typographie), petit signe diacritique, qui prétend ne pencher ni à gauche ni à droite, mais se place nettement au dessus des vraies lettres, qu’il considère avec mépris.

  • # script != binaire

    Posté par (page perso) . Évalué à 7 (+5/-0).

    Il me semblait qu'il était impossible sous linux de modifier le code d'un programme en cours d'exécution,

    Oui, mais uniquement les binaires compilés, et pas les langages interprétés, tel que les scripts écrits en bash. Quand tu vas lancer ton script, bash va lire le fichier, et va commencer à l'interpréter à partir de ce qu'il a en mémoire, et n'a donc plus besoin du code source. Ceci dit, modifier un script bash en cours d'exécution est une mauvaise idée, car bash va parfois le relire à partir d'un 'certain' offset. Si il est modifié, l'offset n'est plus bon, et paf.

    Un binaire, par contre n'est parfois pas entièrement lu en mémoire, voire même peut en être viré si le kernel a besoin de place. C'est (en gros) les fautes de pages sur une partie du prog absente qui permettent de 'remapper' le binaire en mémoire afin de continuer l'exécution. Pour éviter que le fichier disque soit modifié, il est verrouillé par le système. Voir le man de open(2) et chercher l'erreur ETXTBSY.

    * Ils vendront Usenet^W les boites noires quand on aura fini de les remplir.

    • [^] # Re: script != binaire

      Posté par . Évalué à 2 (+1/-0).

      merci pour ta reponse,

      donc le bash ne vas pas récupérer tout le script en mémoire RAM mais uniquement 1 ligne ? puis il va relire une ligne qui se trouve sur le disque ?

      • [^] # Re: script != binaire

        Posté par . Évalué à 5 (+3/-0).

        Je pense que ce comportement n'est volontairement pas défini, et il faut s'attendre à des résultats différents selon les version de bash, voir selon la libc à laquelle il est lié.

        Modifier un script en cours d'exécution est généralement une mauvaise idée.
        Si tu dois absolument faire ta modification avant que l'exécution précédente soit terminée, il vaut mieux faire une copie et travailler sur celle-là pendant que l'exécution précédente se termine.

  • # Surpris

    Posté par . Évalué à 3 (+2/-0).

    Je suis très surpris d'apprendre cela.
    Je pensais qu'un programme (compilé ou interprété) était entièrement chargé en mémoire avant exécution.
    Pour un script à temps d'exécution long (contenant une boucle par exemple), ça paraît terriblement inefficace d'avoir un accès disque à chaque ligne.

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.