Umleitung von stdin mit stdout in eine Datei

Umleitung von stdin mit stdout in eine Datei

Ich habe also ein Programm, das Benutzereingaben entgegennimmt und basierend auf der Eingabe Text ausgibt.

EDIT2: Ich möchte ein Skript erstellen, das eine ausführbare C-Datei ausführt und das C-Programm mit Eingaben aus einer Datei versorgt und die Ausgabe in eine andere Datei umleitet. Ich möchte jedoch auch die Eingaben ausdrucken, wenn eine Ausgabe für die Eingabe gedruckt wurde, also im Grunde die Eingabe und die Ausgabe miteinander kombinieren/zusammenführen. Ich füge also die Eingaben Zeile für Zeile in eine Datei ein und drucke dann die Ausgabe für jede Eingabe in eine Datei aus und mache das so weiter. Ich möchte das Programm nicht erneut ausführen. Ich möchte, dass das Programm weiterläuft, bis es das Ende der Eingabedatei erreicht oder bis ich ihm ein Kill-Signal vom Skript aus sende. (Ich versuche, ein Bewertungsskript für eine Klasse zu erstellen. Die Studenten reichen ihre Programme ein und ich führe dieses Skript aus und füge ihren Programmen Eingaben hinzu, aber ich möchte die Eingabe + Ausgabe zusammen im Auge behalten, damit es für mich einfacher ist, die Eingabe für jede ihrer Ausgaben im Auge zu behalten.) Ich kann selbst herausfinden, wie ich den Rest des Skripts erstellen kann, aber ich komme einfach nicht weiter, wenn es darum geht, Eingabe + Ausgabe zusammenzuführen.

Edit3: Ich glaube nicht, dass expect funktioniert, weil ich nicht wissen kann, was das Programm ausgeben wird. Ich weiß nur, was es aufnehmen soll. Beispielsweise könnte ein Programm für einen Studenten „Gib mir ein Zeichen:“ sagen, während ein anderer sagt „Gebe ein Zeichen ein-“, also weiß ich nicht, was ich von diesen Programmen erwarten soll.

(Hinweis: Ich werde viele verschiedene ausführbare Dateien haben, die unterschiedliche Formate haben, aber alle die gleiche Menge an Eingaben erfordern sollten.)

Eine der ausführbaren Dateien könnte beispielsweise folgende sein:

"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)

BEARBEITEN: Das Hauptziel meines Skripts besteht darin, das Programm auszuführen, indem es die Eingaben zeilenweise aus einer Datei aufnimmt. Für dieses Programm möchte ich beispielsweise, dass es die Datei „input“ als stdin aufnimmt, aber ich möchte auch den Überblick über die mit stdout zusammengeführte stdin behalten.

Ich weiß also, dass ./a.out < input > output ausgeben wird

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

Es fehlt jedoch die Eingabe, die ich ebenfalls einschließen möchte, sodass ich anhand der Ausgabe erkennen kann, was die Eingabe war, indem ich NUR die Ausgabedatei ansehe, da die Eingabe 7 8 N oder 5 10 N oder etwas in der Art sein könnte.

Antwort1

Wenn ich das richtig verstehe, möchten Sie erkennen, wann a.outDaten von der Standardeingabe gelesen werden und wann diese Daten gesendet werden und auch in dieselbe Protokolldatei schreiben, zu der stdout umgeleitet wird, um echobei interaktiver Ausführung die lokale Ausgabe auf dem Terminal zu simulieren?

Dann wäre eine Lösung (Bash-Syntax) vielleicht so etwas wie:

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

Die Idee besteht darin, strace(vorausgesetzt Sie verwenden Linux) die readSystemaufrufe zu verfolgen und immer, wenn ein readDateideskriptor mit der Zahl 0 vorliegt, jeweils ein Zeichen von einzugeben answers.txt.

Bearbeiten: wenn das Programm stdio oder etwas Ähnliches verwendet. Wenn die Ausgabe in eine normale Datei umgeleitet wird und kein Terminal mehr ist, passiert wahrscheinlich, dass alle ausgegebenen Eingabeaufforderungen gepuffert und erst am Ende gelöscht werden, wenn das Programm beendet wird.

Eine Problemumgehung wäre stdbuf, : ./a.outdurch zu ersetzen stdbuf -oL ./a.out. Dies würde der Anwendung (vorausgesetzt, es handelt sich um eine dynamisch verknüpfte Anwendung und die Pufferung erfolgt aufgrund von stdio) sagen, dass sie Zeilenpufferung auf stdout durchführen soll, als wäre es ein Terminal. Es würde jedoch immer noch nicht stdout leeren, wenn stdio von stdin liest, wie es normalerweise der Fall wäre, wenn stdin/stdout Terminals wären. So würde beispielsweise eine Eingabeaufforderung, die nicht durch ein Zeilenumbruchzeichen beendet wird, erst angezeigt, wenn ein explizites Zeichen fflushoder ein Zeilenumbruchzeichen geschrieben wird. Am besten wäre es also wahrscheinlich, stdbuf -o0die Pufferung vollständig zu deaktivieren.

Wenn a.outProzesse oder Threads verzweigt werden können, fügen Sie die -fOption hinzu strace.

Dieser Ansatz würde nicht funktionieren, wenn die Anwendung Systemaufrufe verwendet, selectum pollzu prüfen, ob auf stdin etwas zu lesen ist, bevor sie dies tatsächlich ausführt read. Nicht blockierende E/A kann auch dazu führen, dass wir Daten zu schnell senden.

Wie in den Kommentaren erwähnt. expectist das Tool zur Simulation der Benutzerinteraktion, es verwendet ein Pseudoterminal, so dass Sie automatisch das Eingabeecho erhalten und nicht diegepufferte AusgabeProblem. Als Alternative zu können Sie das mitgelieferte Skript stdbufverwenden, um ein Pseudoterminal einzubinden. In diesem Fall möchten Sie möglicherweise eine kleine Verzögerung zwischen dem Erkennen eines Lesevorgangs und dem Senden der Antwort einfügen, damit die Eingabeaufforderungen auf der Standardausgabe reproduziert werden können.unbuffera.outexpect

Antwort2

Verwenden Sie scriptes hierfür. Genau dafür wurde es gemacht.

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

Zum Beispiel:

>> 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

verwandte Informationen