J'essaie de créer un script bash qui enregistrera l'historique du terminal dans un fichier appelé hist.txt. Utiliser history > hist.txt
ne semble pas fonctionner dans le script bash, mais fonctionne correctement lorsqu'il est exécuté dans la ligne de commande.
Toute orientation est grandement appréciée.
Merci Judy
Exécutez le script avec source
ou .
:
source ./script_name.sh
ou
. ./script_name.sh
Ce dernier est légèrement plus compatible entre différents obus.
Cette question met en évidence un point important, à savoir que les scripts Shell sont exécutés dans leur propre contexte. Pour voir ce que cela signifie, considérons le script Shell suivant:
#!/bin/bash
cd /
ls
Si vous exécutez ceci, vous obtiendrez une sortie semblable à ceci:
bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
Mais vous remarquerez qu'après avoir exécuté le script, vous êtes toujours dans le répertoire dans lequel vous vous trouviez avant de l'exécuter: le cd /
du script n'a pas réellement affecté votre session, mais uniquement le contexte dans lequel le script était exécuté, créé pour l'exécution du script et détruit à son retour.
La commande source
"lira et exécutera les commandes à partir de l'argument filename dans le contexte actuel du shell". Par conséquent, toutes les commandes telles que cd
auront une incidence sur votre session en cours. Si vous deviez exécuter le script ci-dessus en le passant à source
, vous découvririez que vous vous retrouviez dans le répertoire racine après son exécution.
Dans ce cas, le problème est que la commande history
vous donne l'historique du contexte Shell en cours. le contexte Shell dans lequel votre script s'exécute sans utiliser __nom_variable__ n'a pas d'historique et n'écrit donc rien dans le fichier de sortie. Si vous utilisez source
, il s'exécutera dans le contexte approprié et fonctionnera comme prévu.
NB: source
est un shell intégré, pas un programme en soi - dans Bash, source
est synonyme de .
, mais dans certains shells, seul .
fonctionnera - j'ai utilisé source
, mais dans cette réponse, j'ai utilisé source
c'est plus facile à lire que .
, mais pour une compatibilité maximale, .
devrait être utilisé.
Tout d'abord, notez que votre historique est déjà dans un fichier. Si vous utilisez bash, son nom est généralement ~/.bash_history
. Plus précisément, il s’agit de ce que vous avez défini pour la variable HISTFILE
name__. Si vous voulez le copier dans un autre fichier, lancez simplement cat "$HISTFILE" > hist.txt
Maintenant, pour savoir pourquoi la commande history
ne fonctionne pas dans un script shell bash, c'est parce que les scripts sont exécutés dans un shell enfant non interactif de votre session Shell actuelle. Les shells enfants n'héritent pas de tout l'environnement du parent (donc pas de toutes les variables définies), mais uniquement des variables exportées. À titre d’illustration, le script ci-dessous reprendra la valeur de la variable $var
:
#!/bin/bash
echo "$var"
Maintenant, définissez $var
sur quelque chose et exécutez le script:
$ var="foo"
$ foo.sh
VAR:
Ensuite, exportez d'abord la variable:
$ var="foo"
$ export var
$ foo.sh
VAR: foo
Comme vous pouvez le constater, lorsque la variable a été exportée, elle est disponible pour les shells enfants.
Comme je l'ai déjà mentionné, l'historique est stocké dans le fichier désigné par la variable $HISTFILENAME
. Parce que cela n’est pas exporté par défaut, il n’est pas défini lors de l’exécution d’un script:
$ cat foo.sh
#!/bin/bash
echo "HISTFILE: $HISTFILE"
$ ./foo.sh
HISTFILE:
$ echo $HISTFILE
/home/terdon/.bash_history
Comme vous pouvez le voir dans l'exemple ci-dessus, la variable HISTFILE
est définie dans ma session Shell normale, mais est vide lors de l'exécution du script.
Donc, pour avoir l'historique, vous avez quelques options:
La valeur par défaut HISTFILE
est $HOME/.bash_history
. Si vous n'avez pas changé cela, vous pouvez simplement exécuter cette commande dans votre script:
cat "$HOME/.bash_history" > history
Vous pouvez transmettre la variable $HISTFILE
à votre script et cat
qui:
#!/bin/bash
cat "$1" > history
Enregistrez ce qui précède sous foo.sh
et exécutez-le comme ceci:
./foo.sh "$HISTORY"
Assurez-vous que la variable est exportée. Ajoutez cette ligne à vos fichiers ~/.bash_profile
(s’il existe) ou ~/.profile
(si ~/.bash_profile
n'existe pas):
export HISTFILE
Ensuite, déconnectez-vous et reconnectez-vous et vous devriez pouvoir exécuter history > hist.txt
à partir d'un script comme prévu. En effet, export VAR
signifie "rendre $ VAR disponible pour les shells enfants". Concrètement, cela signifie que la valeur de HISTFILE
sera héritée par le shell non interactif que vous utilisez pour exécuter votre script.
Désormais, alors que HISTFILE
sera défini, il n’a pas été lu par le shell qui exécute le script. Donc, pour que cela fonctionne, vous devez d'abord le lire avec history -r
. Le script entier ressemblerait à ceci:
$!/bin/bash
history -r
history > hist.txt
Vous pouvez également l'exporter manuellement avant d'exécuter le script:
$ export HISTFILE
Mais vous aurez toujours besoin de history -r
dans le script.
Vous pouvez source
le suggérer par la réponse de @ p0llard .