stdout을 사용하여 stdin을 파일로 리디렉션

stdout을 사용하여 stdin을 파일로 리디렉션

그래서 저는 사용자 입력을 받아서 입력에 따라 텍스트를 출력하는 프로그램을 가지고 있습니다.

EDIT2: C 실행 파일을 실행하는 스크립트를 만들고 싶습니다. 스크립트는 파일에서 C 프로그램 입력을 공급하고 출력을 다른 파일로 리디렉션합니다. 그러나 기본적으로 입력과 출력을 함께 결합/병합하는 입력에 대해 출력이 인쇄될 때마다 입력도 인쇄하고 싶습니다. 그래서 나는 파일의 한 줄씩 입력을 제공하고 모든 입력에 대해 출력을 파일로 인쇄하며 계속 이 작업을 수행합니다. 프로그램을 다시 실행하고 싶지 않습니다. 입력 파일의 끝에 도달하거나 스크립트에서 종료 신호를 보낼 때까지 프로그램이 계속 실행되기를 원합니다. (수업에 대한 채점 스크립트를 만들려고 합니다. 학생들이 프로그램을 제출하면 이 스크립트를 실행하고 프로그램에 입력을 제공하지만 입력 + 출력을 함께 추적하여 더 쉽게 작업할 수 있도록 하고 싶습니다. 각 출력에 대한 입력을 추적합니다.) 나머지 스크립트를 직접 만드는 방법을 알아낼 수 있지만 입력 + 출력을 함께 결합하는 데 어려움을 겪고 있습니다.

Edit3: 프로그램이 무엇을 출력할지 알 수 없기 때문에 기대가 작동하지 않을 것이라고 생각합니다. 나는 그것이 무엇을 받아들여야 하는지만 알고 있습니다. 예를 들어 한 학생은 "문자를 입력하세요:"라고 말하는 프로그램을 가지고 있는 반면 다른 학생은 "문자를 입력하세요-"라고 말할 수 있으므로 이 프로그램에서 무엇을 기대할 수 있는지 알 수 없습니다.

(참고: 형식은 다르지만 모두 동일한 양의 입력을 요구해야 하는 다양한 실행 파일이 있습니다.)

예를 들어 실행 파일 중 하나는 다음과 같습니다.

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

편집: 내 스크립트의 주요 목표는 파일에서 한 줄씩 입력을 받아 프로그램을 실행하는 것입니다. 예를 들어 이 프로그램의 경우 "input" 파일을 stdin으로 가져오길 원하지만 stdout과 병합된 stdin도 추적하고 싶습니다.

그래서 나는 ./a.out < input > 출력이 출력된다는 것을 알고 있습니다.

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

그러나 내가 포함하고 싶은 입력이 누락되어 입력이 7 8 N 또는 5 10 N 또는 그와 유사한 것일 수 있기 때문에 출력 파일만 보면 출력을 기반으로 입력이 무엇인지 알 수 있습니다.

답변1

a.out내가 올바르게 이해했다면 표준 입력에서 데이터를 읽는 시기와 해당 데이터를 보내는 시기 및 해당 데이터를 동일한 로그 파일에 기록하는 시기를 감지하고 싶습니까 echo? stdout은 대화형으로 실행될 때 로컬을 터미널로 시뮬레이션하기 위해 리디렉션됩니다.

그렇다면 솔루션(bash 구문)은 다음과 같을 것입니다.

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

아이디어는 strace(Linux를 사용한다고 가정) read시스템 호출을 추적하고 파일 설명자 0이 있을 때마다 read에서 한 번에 한 문자씩 공급하는 것입니다 answers.txt.

편집하다: 프로그램이 stdio 또는 이와 유사한 것을 사용하는 경우. 출력이 일반 파일로 리디렉션되고 더 이상 터미널이 아니기 때문에 발생할 수 있는 일은 출력되는 모든 프롬프트가 버퍼링되어 프로그램이 종료될 때 마지막에만 플러시된다는 것입니다.

해결 방법은 stdbuf다음 ./a.out을 사용하는 것입니다 stdbuf -oL ./a.out. 이는 응용 프로그램(동적으로 연결된 응용 프로그램이고 버퍼링이 stdio로 인한 것이라고 가정)이 마치 터미널인 것처럼 stdout에서 라인 버퍼링을 수행하도록 지시합니다. 그러나 여전히 수행되지 않는 작업은 stdin/stdout이 터미널인 경우 일반적으로 수행되는 것처럼 stdio가 stdin에서 읽을 때 stdout을 플러시하는 것입니다. 예를 들어 개행 문자로 끝나지 않는 프롬프트는 명시적이 fflush거나 개행 문자가 최종적으로 작성될 때까지 표시되지 않습니다. 따라서 stdbuf -o0버퍼링을 완전히 비활성화 하는 것이 가장 좋습니다 .

a.out프로세스나 스레드를 분기할 수 있는 경우 -f옵션을 에 추가합니다 strace.

select실제로 .pollread​비차단 I/O로 인해 데이터가 너무 빨리 전송될 수도 있습니다.

댓글에서 언급했듯이. expect사용자 상호 작용을 시뮬레이션하는 도구이며 의사 터미널을 사용하므로 자동으로 입력 에코를 얻을 수 있지만버퍼링된 출력문제. 의 대안으로 함께 제공되는 스크립트를 stdbuf사용하여 의사 터미널을 래핑할 수 있습니다. 이 경우 표준 출력에서 ​​프롬프트를 재현할 수 있도록 읽기 감지와 답변 전송 사이에 약간의 지연을 추가할 수 있습니다 .unbuffera.outexpect

답변2

script이것을 위해 사용하십시오 . 이것이 바로 그것이 만들어진 이유입니다.

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

예를 들어:

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

관련 정보