Redirigir stdin con stdout al archivo

Redirigir stdin con stdout al archivo

Entonces tengo un programa que toma la entrada del usuario y genera texto basado en la entrada.

EDITAR2: Quiero crear una secuencia de comandos que ejecute un ejecutable de C y la secuencia de comandos alimente la entrada del programa C desde un archivo y redirija la salida a otro archivo. SIN EMBARGO, también quiero imprimir la entrada cada vez que se imprimió una salida para la entrada, básicamente combinando/fusionando la entrada y la salida. Así que le doy entrada línea por línea en un archivo y luego imprimo la salida en un archivo para cada entrada y sigo haciendo esto. No quiero volver a ejecutar el programa. Quiero que el programa siga ejecutándose hasta que llegue al final del archivo de entrada o hasta que le envíe una señal de finalización desde el script. (Estoy tratando de crear un script de calificación para una clase. Los estudiantes envían sus programas y yo ejecuto este script y envío entradas a sus programas, pero quiero realizar un seguimiento de las entradas y salidas juntas para que me resulte más fácil realizar un seguimiento de la entrada para cada una de sus salidas) Puedo descubrir cómo crear el resto del script yo mismo, pero estoy atascado en combinar entrada + salida.

Edit3: No creo que expect funcione porque no tengo forma de saber qué generará el programa. Solo sé lo que se supone que debe asimilar. Por ejemplo, un estudiante podría tener un programa que diga "Dame un carácter:" mientras que otro dirá "Ingresa un carácter-", por lo que no sé qué esperar de estos programas.

(Nota: tendré muchos ejecutables diferentes que tendrán un formato diferente, pero todos deberían solicitar la misma cantidad de información)

Por ejemplo, uno de los ejecutables podría ser este:

"Enter a number: " (Wait for user input)
"Give another: "  (Wait for user input
"Total: " (Output based on input)
"Do you want to run again? "(Wait for user input)

EDITAR: El objetivo principal de mi script es ejecutar el programa tomando entradas de un archivo línea por línea. Por ejemplo, para este programa, querré que incluya el archivo "entrada" como entrada estándar, pero también quiero realizar un seguimiento de la entrada estándar fusionada con la salida estándar.

Entonces sé que la salida ./a.out <entrada> generará

Enter a number: 
Give another:  
Total:  15
Do you want to run again? 

Sin embargo, falta la entrada, que es lo que quiero incluir también para poder saber cuál fue la entrada en función de la salida simplemente mirando el archivo de salida SÓLO porque la entrada podría ser 7 8 N o 5 10 N o algo así.

Respuesta1

Si entiendo correctamente, ¿desea detectar cuándo a.outse leen datos de la entrada estándar y cuándo se envían esos datos y también se escriben en el mismo archivo de registro al que se redirige la salida estándar para simular el local echoal terminal cuando se ejecuta de forma interactiva?

Entonces tal vez una solución (sintaxis bash) sería algo como:

mkfifo strace.fifo
{
  while read -d, trace; do
    if [[ $trace = *"read(0" ]]; then
      IFS= read -rn1 answer <&3 || break
      answer=${answer:-$'\n'}
      printf %s "$answer" >&2
      printf %s "$answer"
    fi
  done < strace.fifo 3< answers.txt |
    strace -o strace.fifo -e read ./a.out
} > log 2>&1

La idea es usarlo strace(suponiendo que esté en Linux) para rastrear las readllamadas al sistema y siempre que haya un readdescriptor de archivo 0, introduzca un carácter a la vez desde answers.txt.

Editar: si el programa usa stdio o algo así. Lo que probablemente sucederá cuando la salida se redirija a un archivo normal y ya no sea una terminal es que todas las indicaciones que genera se almacenen en el búfer y solo se borrarán al final cuando se cierre el programa.

Una solución alternativa sería utilizar stdbuf: reemplazar ./a.outcon stdbuf -oL ./a.out. Eso le indicaría a la aplicación (suponiendo que sea una aplicación vinculada dinámicamente y el almacenamiento en búfer se debe a stdio) que realice el almacenamiento en búfer de línea en stdout como si fuera una terminal. Sin embargo, lo que aún no haría es vaciar stdout tras las lecturas de stdio desde stdin como lo haría normalmente si stdin/stdout fueran terminales. Entonces, por ejemplo, un mensaje que no termine con un carácter de nueva línea no se mostrará hasta que se escriba un carácter explícito fflusho hasta que finalmente se escriba un carácter de nueva línea. Así que probablemente lo mejor sería utilizarlo stdbuf -o0para desactivar el almacenamiento en búfer por completo.

Si a.outpuede bifurcar procesos o subprocesos, agregue la -fopción a strace.

Ese enfoque no funcionaría si la aplicación utiliza llamadas selectal pollsistema para verificar si hay algo que leer en la entrada estándar antes de realizar el archivo read. La E/S sin bloqueo también puede hacer que enviemos datos demasiado rápido.

Como se menciona en los comentarios. expectes la herramienta para simular la interacción del usuario, utiliza un pseudo terminal, por lo que automáticamente obtendría el eco de entrada y no tendría elsalida almacenada en bufferproblema. Como alternativa a stdbuf, puede utilizar el unbufferscript que viene con él para envolverlo a.outen una pseudo terminal. En ese caso, es posible que desee agregar un pequeño retraso entre la detección de una lectura y el envío de la respuesta para permitir expectreproducir las indicaciones en su salida estándar.

Respuesta2

Úselo scriptpara esto. Esto es exactamente para lo que fue hecho.

script /tmp/logfile -c 'your command here'

Por ejemplo:

>> script /tmp/log -c 'read -p "Value: " value; echo "value=$value"'
Script started, file is /tmp/log
Value: foo
value=foo
Script done, file is /tmp/log

>> cat /tmp/log
Script started on Wed 01 May 2013 01:16:34 PM EDT
Value: foo
value=foo

Script done on Wed 01 May 2013 01:16:35 PM EDT

información relacionada