Lors de l'utilisation de Nohup pour mettre une commande à exécuter en arrière-plan, certains contenus apparaissent dans le terminal.
cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error
Je veux enregistrer ce contenu dans un fichier.
Il existe deux principaux flux de sortie sous Linux (et les autres systèmes d’exploitation), la sortie standard (stdout) et l’erreur standard (stderr). Les messages d'erreur, comme ceux que vous affichez, sont imprimés avec l'erreur standard. L'opérateur de redirection classique (command > file
) ne redirige que la sortie standard. Par conséquent, l'erreur standard est toujours affichée sur le terminal. Pour rediriger stderr également, vous avez plusieurs choix:
Rediriger stdout vers un fichier et stderr vers un autre fichier:
command > out 2>error
Transférez stderr vers stdout (&1
), puis redirigez stdout vers un fichier:
command >out 2>&1
Redirige les deux vers un fichier (par exemple, ce n'est pas pris en charge par tous les shells, par exemple, bash
et zsh
, mais sh
et ksh
ne le supportent pas):
command &> out
Pour plus d'informations sur les différents opérateurs de contrôle et de redirection, voir here .
La première chose à noter est qu'il y a plusieurs façons selon votre objectif et Shell. Par conséquent, cela nécessite une légère compréhension de plusieurs aspects. De plus, certaines commandes telles que time
et strace
écrivent une sortie sur stderr par défaut et peuvent ou non fournir une méthode de redirection spécifique à cette commande.
Selon la théorie de base de la redirection, un processus généré par Shell (en supposant qu'il s'agisse d'une commande externe et non de celle intégrée à Shell) est créé via fork()
et execve()
syscalls, et avant que cela se produise, un autre syscall dup2()
effectue les redirections nécessaires avant que execve()
ne se produise. En ce sens, les redirections sont héritées du shell parent. m&>n
et m>n.txt
informent le shell de la procédure à suivre pour exécuter open()
et dup2()
syscall (voir aussi Fonctionnement de la redirection d'entrée , Quelle est la différence entre redirection et pipe et Que signifie exactement dans la redirection de sortie )
Le plus typique est via 2>
dans shells Bourne-like , tel que dash
(qui est lié symboliquement à /bin/sh
) et bash
; Le premier est le shell par défaut compatible avec POSIX et le second est celui que la plupart des utilisateurs utilisent pour les sessions interactives. Ils diffèrent par leur syntaxe et leurs fonctionnalités, mais heureusement pour nous, la redirection de flux d’erreur fonctionne de la même manière (à l’exception de la &>
non standard). Dans le cas de csh et ses dérivés, la redirection stderr ne fonctionne pas très bien là.
Revenons à la partie 2>
. Deux points essentiels à noter: >
signifie opérateur de redirection, dans lequel nous ouvrons un fichier et 2
entier représente le descripteur de fichier stderr; En fait, c’est exactement comment le standard POSIX pour le langage Shell définit la redirection dans section 2.7 :
[n]redir-op Word
Pour une redirection >
simple, le nombre entier 1
est impliqué pour stdout
, c.-à-d. echo Hello World > /dev/null
est identique à echo Hello World 1>/dev/null
. Notez que l'opérateur entier ou l'opérateur de redirection ne peut pas être cité, sinon Shell ne les reconnaît pas comme tels et les considère plutôt comme une chaîne de texte littérale. En ce qui concerne l'espacement, il est important que l'entier se trouve juste à côté de l'opérateur de redirection, mais que le fichier peut l'être ou non de l'opérateur de redirection, c.-à-d. command 2>/dev/null
et command 2> /dev/null
fonctionneront très bien.
La syntaxe quelque peu simplifiée pour une commande typique dans Shell serait
command [arg1] [arg2] 2> /dev/null
L'astuce ici est que la redirection peut apparaître n'importe où. C'est-à-dire que 2> command [arg1]
et command 2> [arg1]
sont valides. Notez que pour bash
Shell, il existe &>
moyen de rediriger les flux stdout et stderr en même temps, mais là encore - il est spécifique à bash et si vous recherchez la portabilité des scripts, cela risque de ne pas fonctionner. Voir aussi Wiki Ubunt et Quelle est la différence entre &> et 2> & 1 .
Remarque: L'opérateur de redirection >
tronque un fichier et le remplace si le fichier existe. Le 2>>
peut être utilisé pour ajouter stderr
au fichier.
Si vous le remarquez, >
est destiné à une seule commande. Pour les scripts, nous pouvons rediriger le flux stderr de l'intégralité du script depuis l'extérieur comme dans myscript.sh 2> /dev/null
ou nous pouvons utiliser exec intégré . Le module d'exécution intégré a le pouvoir de recâbler le flux pour l'ensemble de la session Shell, pour ainsi dire, de manière interactive ou via un script. Quelque chose comme
#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file
Dans cet exemple, le fichier journal devrait indiquer stat: cannot stat '/etc/non_existing_file': No such file or directory
.
Une autre méthode consiste à utiliser des fonctions. Comme kopciuszek indiqué dans sa réponse, nous pouvons écrire une déclaration de fonction avec une redirection déjà attachée, c'est-à-dire
some_function(){
command1
command2
} 2> my_log_file.txt
Les commandes telles que time
et strace
écrivent leur sortie sur stderr par défaut. Dans le cas de la commande time
, la seule alternative viable consiste à rediriger la sortie de la commande entière, c'est-à-dire
time echo foo 2>&1 > file.txt
sinon, liste synchrone ou sous-shell peuvent être redirigés si vous souhaitez séparer la sortie (comme indiqué dans related post ):
{ time sleep 1 2> sleep.stderr ; } 2> time.txt
D'autres commandes, telles que strace
ou dialog
, permettent de rediriger stderr. strace
a l'option -o <filename.txt>
qui permet de spécifier le nom du fichier dans lequel la sortie doit être écrite. Il existe également une option pour écrire un fichier texte pour chaque sous-processus visible par strace
. La commande dialog
écrit l'interface utilisateur textuelle sur stdout mais la sortie sur stderr, donc pour enregistrer sa sortie dans une variable (car var=$(...)
et les pipelines ne reçoivent que stderr), nous devons échanger les descripteurs de fichier.
result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);
mais en plus, il y a le drapeau --output-fd
, que nous pouvons également utiliser. Il y a aussi la méthode des tubes nommés. Je vous recommande de lire l'article lié sur la commande dialog
pour une description détaillée de ce qui se passe.