Cómo redirigir stderr a un archivo

Al usar nohup para poner un comando para que se ejecute en segundo plano, parte del contenido aparece en la terminal.

cp: error reading ‘/mnt/tt/file.txt’: Input/output errorcp: failed to extend ‘/mnt/tt/file.txt’: Input/output error

Quiero guardar ese contenido en un archivo.

Hay dos flujos de salida principales en Linux( y otros sistemas operativos), salida estándar (stdout) y error estándar (stderr). Los mensajes de error, como los que muestra, se imprimen en error estándar. El operador de redirección clásico (command > file) solo redirige la salida estándar, por lo que el error estándar aún se muestra en el terminal. Para redirigir stderr también, tiene algunas opciones:

  1. Redirigir stdout a un archivo y stderr a otro archivo:

    command > out 2>error
  2. Redirigir la salida estándar a un archivo (>out), y luego redirigir stderr a stdout (2>&1):

    command >out 2>&1
  3. Redirigir ambos a un archivo (esto no es compatible con todos los shells, bash y zsh apoyo, por ejemplo, pero sh y ksh no):

    command &> out

Para obtener más información sobre los distintos operadores de control y redirección, consulte aqui.

Lo primero a tener en cuenta es que hay un par de formas dependiendo de su propósito y shell, por lo tanto, esto requiere una ligera comprensión de múltiples aspectos. Además, ciertos comandos como time y strace escriba la salida en stderr de forma predeterminada, y puede o no proporcionar un método de redirección específico para ese comando

La teoría básica detrás de la redirección es que un proceso generado por shell (suponiendo que sea un comando externo y no un shell incorporado) se crea a través de fork() y execve() llamadas al sistema, y antes de que eso suceda, otra llamada al sistema dup2() realiza las redirecciones necesarias antes de execve() suceder. En ese sentido, las redirecciones se heredan del shell padre. El m&>n y m>n.txt informar al shell sobre cómo realizar open() y dup2() syscall (véase también Cómo funciona la redirección de entradas, Cuál es la diferencia entre redirección y canalización, y Qué significa & exactamente en la redirección de salida )

Redirecciones de Shell

Lo más típico es a través de 2> en Conchas parecidas a Bourne, tales como dash (que está enlazado simbólicamente a /bin/sh) y bash; el primero es el shell predeterminado y compatible con POSIX y el otro es el que la mayoría de los usuarios utilizan para la sesión interactiva. Difieren en sintaxis y características, pero afortunadamente para nosotros, la redirección de secuencias de errores funciona de la misma manera (excepto la &> no estándar). En el caso de csh y sus derivados, la redirección stderr no funciona del todo allí.

Volvamos a 2> parte. Dos cosas clave a tener en cuenta: > significa operador de redirección, donde abrimos un archivo y 2 integer significa descriptor de archivo stderr; de hecho, así es exactamente como el estándar POSIX para lenguaje de shell define la redirección en sección 2.7:

[n]redir-op word

Por simple > redirección, el 1 el entero está implícito para stdout, es decir, echo Hello World > /dev/null es lo mismo que echo Hello World 1>/dev/null. Tenga en cuenta que el entero o el operador de redirección no se pueden citar, de lo contrario, shell no los reconoce como tales y, en su lugar, los trata como una cadena de texto literal. En cuanto al espaciado, es importante que el entero esté justo al lado del operador de redirección, pero el archivo puede estar al lado del operador de redirección o no, es decir, command 2>/dev/null y command 2> /dev/null funcionará bien.

La sintaxis algo simplificada para un comando típico en el shell sería

 command [arg1] [arg2]  2> /dev/null

El truco aquí es que la redirección puede aparecer en cualquier lugar. Eso es a la vez 2> command [arg1] y command 2> [arg1] son válidos. Tenga en cuenta que para bash shell, ahí existe &> es una forma de redirigir los flujos stdout y stderr al mismo tiempo, pero de nuevo, es específico de bash y si está buscando la portabilidad de los scripts, puede que no funcione. Véase también Ubuntu Wiki y >>¿Cuál es la diferencia entre & y 2&1.

Nota: El > operador de redirección truncar un archivo y lo sobrescribe, si el archivo existe. El 2>> se puede utilizar para anexar stderr file.

Si puede notar, > está destinado a un solo comando. Para los scripts, podemos redirigir el flujo stderr de todo el script desde el exterior como en myscript.sh 2> /dev/null o podemos hacer uso de ejecutivo incorporado. El ejecutivo incorporado tiene el poder de volver a cablear la transmisión para toda la sesión de shell, por así decirlo, ya sea de forma interactiva o mediante un script. Algo así como

#!/bin/shexec 2> ./my_log_file.txtstat /etc/non_existing_file

En este ejemplo, el archivo de registro debería mostrar stat: cannot stat '/etc/non_existing_file': No such file or directory.

Otra forma es a través de funciones. Como ceniciento como se señaló en su respuesta, podemos escribir una declaración de función con una redirección ya adjunta, es decir

some_function(){    command1    command2} 2> my_log_file.txt

Comandos que escriben en stderr exclusivamente

Comandos como time y strace escriba su salida en stderr de forma predeterminada. En caso de time comando, la única alternativa viable es redirigir la salida de todo el comando , es decir

time echo foo 2>&1 > file.txt

alternativamente, la lista síncrona o la subcapa podrían redirigirse si desea separar la salida ( como se muestra en post relacionado ):

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

Otros comandos, como strace o dialog proporcionar medios para redirigir stderr. strace tener -o <filename.txt> opción que permite especificar el nombre de archivo donde se debe escribir la salida. También hay una opción para escribir un archivo de texto para cada subproceso que strace ver. El dialog el comando escribe la interfaz de usuario de texto en stdout pero la salida en stderr, por lo que para guarde su salida en variable ( porque var=$(...) y pipelines solo recibe stderr) necesitamos intercambiar los descriptores de archivo

result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);

pero, además, hay --output-fd bandera, que también podemos utilizar. También existe el método de tuberías con nombre. Recomiendo leer el post enlazado sobre el dialog comando para una descripción detallada de lo que está sucediendo.

@terdon Esta es una pregunta más específica, y aparece correctamente en la búsqueda de Google de la pregunta más específica, lo cual es bueno.

@nroose sí, y seguirá apareciendo, eso no cambiará. Pero cualquier respuesta nueva debe ir a la pregunta más general.