Besoin d'aide - Script shell

Résolu
Bonjour, j'ai une question sur laquelle je bloque depuis quelques heures ...

Je dois écrire un script shell qui prend un paramètre, et grâce à l'historique des commandes il doit exécuter ce qui est dans cette ligne (chiffre passé en paramètre).

J'ai 2 soucis:
-impossible de créer l'historique ( la commande history fonctionne dans la console mais pas dans le script )
-j'arrive à afficher le résultat, mais comment faire pour que cela s'exécute?

J'ai écrit ceci:

#! bin/bash/

if [ $# -ne 1 ] || [ $1 -lt 1 ]
then
echo "erreur de paramètre"
else
history > essai.txt; # problème numero 1
grep "^ $1" essai.txt | cut -d\ -f4-99 |

fi
#fin
Merci d'avance,

4 réponses

Résumé de la discussion

Le point central est d'exécuter dans un script une commande préalablement historique en passant son numéro, tout en gérant l'absence d'historique dans un shell non interactif. La solution consiste à récupérer la ligne correspondante dans l'historique via history et grep, puis à isoler le texte de commande et à l'exécuter avec eval. Par exemple, on peut stocker dans une variable le résultat avec res=$(history | grep '^ [1-9]' | cut -d' ' -f3-99), puis évaluer cette commande avec eval "$res" pour l'exécuter. D'autres échanges soulignent que certaines lignes peuvent être vides ou hors contexte et recommandent de vérifier la présence de la commande avant l'évaluation, afin d'éviter des erreurs d'exécution.

Bobot (l’IA à votre service)
  1. Bonjour,
    Il ne faut pas utiliser #!/bin/bash retirez cette ligne car ça ouvre un nouveau shell avec un historique vide. Testez un .sh avec uniquement "history" dedans. src : http://unix.ittoolbox.com/groups/technical-functional/solaris-l/history-utility-in-bash-script-605752
    Pour exécuter une commande qui est contenue dans une variable utilisez "eval"
    exemple :

    var="echo hello world"
    eval $var

    Pouvez aussi utiliser "history -w monfichier" pour enregistrer l'historique dans un fichier en particulier, ou utiliser "history -a" pour ajouter les dernières commandes utilisées dans l'historique en cours et le récupérer avec un "cat ~/.bash_history"
    0
    1. merci ! je replonge dedans dès demain et je vous tiens au courant.
      0
    2. Modérateur
      Salut,

      Il ne faut pas utiliser #!/bin/bash retirez cette ligne car ça ouvre un nouveau shell avec un historique vide.
      Effectivement. Toutefois tu n'as pas lu le message jusqu'au bout.

      If you wish to execute stmts in a file from
      your current shell, then you will need to source it:

      $ . yourfile


      Ce qui veut dire que lorsqu'on utilise #!/bin/bash il faut lancer le script avec la commande
      . script.sh  


      lami20j@debian-acer:~$ cat hist.sh   
      #!/bin/bash  
      history  
      lami20j@debian-acer:~$ chmod -v +x hist.sh   
      le mode de « hist.sh » a été modifié en 0755 (rwxr-xr-x). 


      A lancer avec
      ./hist.sh

      et puis avec
      . hist.sh
      0
  2. J'y suis presque !

    if [ $# -ne 1 ] || [ $1 -lt 1 ]
    then
    echo "erreur de paramètre"
    else
    history > histo
    res=$(grep "^ $1" histo| cut -d\ -f3-999)
    eval $res
    fi

    en enlevant la ligne du shebang j'arrive donc à avoir mon historique,
    mais je n'arrive pas à exécuter cette variable resultat
    ( chmod ok, ./monscript.sh xxx ok, mais . monscript.sh xxx ne retourne rien )
    0
    1. Modérateur
      Salut,

      #!/bin/bash
      
      if [ $# -ne 1 ] || [ $1 -lt 1 ] 
      then 
        echo "erreur de paramètre" 
      else 
        history > histo 
        res=$(grep "^ $1" histo| cut -d\ -f3-999) 
        echo $res 
      # pas besoin du eval, puisque $(commande) est stocké dans res
      fi 

      chmod +x script.sh

      et tu lances le script avec la commande (attention au . et ESPACE au début)
      . /chemin/vers/script.sh
      0
    2. Contributeur
      Salut,

      # pas besoin du eval, puisque $(commande) est stocké dans res
      Ben si, si le but final est l'exécution de la commande, du moins c'est comme ça que je l'ai compris ;-\
      0
    3. Modérateur
      Salut,

      Ben si, si le but final est l'exécution de la commande,
      Tu as raison ;-)

      En ce cas il faudra peut être qu'il nous affiche ce que done la comamnde
      De toute façon il n'a pas besoin de history > histo
      On peut faire comme ça si je ne me trompe pas.

      #!/bin/bash  
      
      if [ $# -ne 1 ] || [ $1 -lt 1 ]   
      then   
        echo "erreur de paramètre"   
      else   
        history | grep "^ $1" | cut -d\ -f3-999  
      fi 


      Mais j'aurais plutôt penser à !NUMERO_DE_COMMANDE qu'à eval ;-)
      A voir comment on met ça dans le script

      #!/bin/bash  
      
      if [ $# -ne 1 ] || [ $1 -lt 1 ]   
      then   
        echo "erreur de paramètre"   
      else   
        !$1 # fait un test pour ça, merci ;-)  
      fi 
      0
    4. Contributeur
      Re-

      J'avais déjà testé ça hier soir et ça ne marchait pas ;-((

      Pour preuve au cas ou...

      $ vi foo.sh
      
      $ chmod u+x foo.sh
      
      $ ./foo.sh 118
      ./foo.sh: line 7: !118 : commande introuvable
      
      $ . /home/zipe/tmpfs/foo.sh 118
      -bash: !118 : commande introuvable
      
      $
      0
  3. Et bien ca ne retourne rien,

    #!/bin/bash
    if [ $# -ne 1 ] || [ $1 -lt 1 ]
    then
    echo "erreur de paramètre"
    else
    res=$(history | sed -n "s/^ *"$1" *\(.*\)/\1/p")
    echo $res # pour voir si la variable a changé, sinon il faut utiliser eval
    fi

    fab@Glou:~/Documents$ ./exec.sh 459

    fab@Glou:~$ ./Documents/exec.sh 987

    résultat : rien :(
    0
    1. si si ! j'y mets tout mon coeur , mais ca marche pas

      fab@Glou:~/Documents$ chmod 777 exec.sh
      fab@Glou:~/Documents$ ./exec.sh
      erreur de paramètre
      fab@Glou:~/Documents$ ./exec.sh 456

      fab@Glou:~/Documents$ . exec.sh 456
      0
    2. Modérateur
      Affiche le résultat de
      history | grep 456
      0
    3. le soucis doit venir du grep,

      avec ceci j'obtiens les lignes qui contiennent ce que j'ai passé en paramètre,

      res=$( history | grep $1 | cut -d\ -f2-99)
      echo $res

      mais ce que je veux c'est garder la ligne qui commence par ce numero ...
      0
    4. avec grep "^ $1" ca fonctionne, ... maintenant c'est le cut qui doit m'enlever le premier champs
      0
  4. if [ $# -ne 1 ] || [ $1 -lt 1 ]
    then
    echo "erreur de paramètre"
    else

    res=$( history | grep "^ $1" | cut -d\ -f3-99)
    eval $res
    fi

    ca fonctionne ! j'ai eus du mal à m'en rendre compte, car certaines lignes de mon historique ne renvoyait rien,

    Merci à tous pour votre aide.
    0
    1. Modérateur
      Ok, tant mieux.
      Tu peux mettre résolu alors ;-)
      0