À des fins de documentation, je veux dire rediriger vers le fichier stdout et stderr à partir d'une commande que j'exécute.
Par exemple, je lancerais (ma commande est moins triviale que l'alias ll
mais cela n'a probablement pas d'importance):
$ ll > out-err.dat 2>&1
$ cat out-err.dat
drwxr-xr-x 39 us00001 us00001 4096 jul 31 14:57 ./
drwxr-xr-x 3 root root 4096 feb 2 06:06 ../
-rw------- 1 us00001 us00001 62226 jul 31 11:56 .bash_history
...
Également à des fins de documentation, je souhaite stocker dans le même fichier de sortie la ligne de commande que j'ai utilisée.
Le comportement et la sortie prévus sont
$ [NEW COMMAND LINE]?
$ cat out-err.dat
[NEW COMMAND LINE] <- This first line would contain the command line used
drwxr-xr-x 39 us00001 us00001 4096 jul 31 14:57 ./
drwxr-xr-x 3 root root 4096 feb 2 06:06 ../
-rw------- 1 us00001 us00001 62226 jul 31 11:56 .bash_history
...
Comment cela peut-il être fait ?
Je sais que je pourrais écrire un script bash et l'exécuter, de sorte que la commande resterait documentée séparément.
Je pourrais en outre écrire un script pour faire écho à la ligne de commande dans le fichier, puis l'exécuter avec une redirection vers le même file.
Je recherche une solution possible sans script.
MODIFIER :
Feedback sur une belle réponse.
Cela ne correspondrait pas à un commentaire.
J'ai testé avec la commande echo_command ll echo_command.sh ../dir > out-err.dat 2>&1
.
Script echo_command.sh
, dont je source
, contient les définitions des fonctions.
../dir
est un répertoire inexistant, pour forcer une sortie vers stderr
.
Méthode 1 :
Fonctionne bien, sauf pour deux problèmes :
-
Il ne comprend pas les alias (
ll
dans ce cas; lors du remplacement parls
ça a marché). -
Il n'enregistre pas la partie de redirection.
Méthode 2 :
Ça ne marche pas très bien. Maintenant, la partie de redirection est également imprimée, mais la ligne de commande est imprimée à l'écran au lieu d'être redirigée vers le fichier.
MODIFIER :
Retour sur un commentaire posté, à propos d'un script
utilitaire.
Il est assez polyvalent, encore plus avec scriptreplay
.
script
peut être appelé seul, ce qui produit un shell interactif (il ne conserverait pas l'historique récent du shell parent)
Il peut également être appelé comme script -c <command> <logfile>
. Cette dernière forme correspond à l'objectif de l'OP, mais elle ne stocke pas la commande elle-même dans le fichier journal. Il produit (au moins dans les cas de base) la même sortie que <command> > <logfile> 2>&1
.
Il semble donc que cela ne soit pas utile ici.
Réponse acceptée :
Vous pouvez utiliser une fonction comme celle-ci :
echo_command() { printf '%sn' "${*}"; "${@}"; }
Exemple :
$ echo_command echo foo bar baz
echo foo bar baz
foo bar baz
$ echo_command uname
uname
Linux
Comme l'a dit Tim Kennedy, il y a aussi un script
très utile commande :
$ script session.log
Script started, file is session.log
$ echo foo
foo
$ echo bar
bar
$ echo baz
baz
$ exit
exit
Script done, file is session.log
$ cat session.log
Script started on 2018-07-31 16:30:31-0500
$ echo foo
foo
$ echo bar
bar
$ echo baz
baz
$ exit
exit
Script done on 2018-07-31 16:30:43-0500
Mettre à jour
Si vous avez également besoin de consigner les redirections et essentiellement chaque syntaxe shell (notez que j'ai ajouté une petite Command line:
message pour identifier facilement la commande en cours d'exécution) :
echo_command() {
local arg
for arg; do
printf 'Command line: %sn' "${arg}"
eval "${arg}"
done
}
Tenez simplement compte du fait que vous devez être très prudent avec la citation comme eval
est utilisé :
$ echo_command 'echo foo > "file 2"; cat "file 2"'
Command line: echo foo > "file 2"; cat "file 2"
foo
Il accepte également plusieurs commandes à la fois au lieu d'une seule :
$ echo_command 'echo foo' 'echo bar' 'echo baz'
Command line: echo foo
foo
Command line: echo bar
bar
Command line: echo baz
baz