stdin 및 stdout을 파일로 리디렉션

stdin 및 stdout을 파일로 리디렉션

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

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)

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

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

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

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

답변1

내가 올바르게 이해했다면 a.outstdin에서 데이터를 읽는 시점과 해당 데이터가 동일한 로그 파일에 전송 및 기록되는 시점을 감지하고 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바꾸십시오 . 이는 마치 터미널인 것처럼 stdout에서 라인 버퍼링을 수행하도록 응용 프로그램에 지시합니다(동적으로 연결된 응용 프로그램이고 버퍼링이 stdio로 인해 발생한다고 가정). 그러나 여전히 수행하지 않는 작업은 stdin에서 stdio를 읽을 때 stdout을 플러시하는 것입니다. 이는 stdin/stdout이 터미널인 경우 일반적으로 수행됩니다. 예를 들어, 개행 문자로 끝나지 않는 프롬프트는 개행 문자가 명시적으로 또는 최종적으로 작성될 때까지 표시되지 않습니다. 따라서 가장 좋은 방법은 버퍼링을 완전히 비활성화하는 것입니다../a.outstdbuf -oL ./a.outfflushstdbuf -o0

a.out프로세스나 스레드를 분기할 수 있는 경우 이 -f옵션을 strace.

응용 프로그램이 select실제로 비차단 I/O를 poll수행하는 경우 read데이터를 너무 빨리 보낼 수도 있습니다.

댓글에서 언급했듯이. 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

관련 정보