나는 이것을하는 데 익숙합니다.
someprogram >output.file
나는 프로그램에서 생성된 출력을 파일로 저장하고 싶을 때마다 이 작업을 수행합니다. 나는 또한 이것의 두 가지 변형을 알고 있습니다IO 리디렉션:
someprogram 2>output.of.stderr.file
(표준 오류의 경우)someprogram &>output.stderr.and.stdout.file
(stdout+stderr 조합의 경우)
오늘 나는 불가능하다고 생각했던 상황에 직면했다. 다음 명령을 사용하면 xinput test 10
예상대로 다음과 같은 결과가 나타납니다.
user@hostname:~$xinput 테스트 10 버튼 30 릴리스 키 30 버튼 40 키 릴리스 40 버튼 32 키 릴리스 32 버튼 65 키 릴리스 65 버튼 61 키 릴리스 61 버튼 31 ^C 사용자@호스트 이름:~$
나는 이 출력이 평소와 같이 파일에 저장되기를 기대했습니다. 예를 들어 .를 사용했지만 xinput test 10 > output.file
내 기대와는 달리 출력.파일 파일은 비어 있었습니다. 이는 또한 xinput test 10 &> output.file
stdout이나 stderr에서 뭔가를 놓치지 않도록 하기 위한 것입니다.
정말 혼란스럽습니다. xinput
출력이 리디렉션되는 것을 방지할 수 있는 방법이 있는지 여기에서 프로그램에 문의해 볼까요?
고쳐 쓰다
소스코드를 봤습니다. 이 코드에 의해 출력이 생성된 것 같습니다(아래 코드 조각 참조). 출력은 일반 printf에 의해 생성되는 것 같습니다.
//test.c 파일에서 정적 무효 print_events(*dpy 표시) { XEvent 이벤트; 그리고 (1){ XNextEvent(dpy,&이벤트); // [...몇 가지 다른 이벤트 유형이 여기에 나열되어 있습니다...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { 정수 루프; XDeviceKeyEvent *key = (XDeviceKeyEvent *) &Event; printf("key %s %d ", (Event.type == key_release_type) ? "release" : "눌림", key->keycode); for(loops=0;loopaxes_count;loop++){ printf("a[%d]=%d ", key->first_axis + loop, key->axis_data[loop]); } printf("\n"); } } }
stderr에서 출력 복사본을 얻을 수 있도록 소스 코드를 이것(아래의 다음 코드 조각 참조)으로 수정했습니다. 이 출력을 리디렉션할 수 있습니다.
//test.c 파일에서 정적 무효 print_events(*dpy 표시) { XEvent 이벤트; 그리고 (1){ XNextEvent(dpy,&이벤트); // [...몇 가지 다른 이벤트 유형이 여기에 나열되어 있습니다...] if ((Event.type == key_press_type) || (Event.type == key_release_type)) { 정수 루프; XDeviceKeyEvent *key = (XDeviceKeyEvent *) &Event; printf("key %s %d ", (Event.type == key_release_type) ? "release" : "눌림", key->keycode); fprintf(stderr,"key %s %d ", (Event.type == key_release_type) ? "release" : "press ", key->keycode); for(loops=0;loopaxes_count;loop++){ printf("a[%d]=%d ", key->first_axis + loop, key->axis_data[loop]); } printf("\n"); } } }
현재 내 생각은 리디렉션을 수행하면 프로그램이 주요 릴리스 이벤트를 모니터링하는 기능을 잃게 될 수 있다는 것입니다.
답변1
stdout이 터미널이 아닌 경우에만 출력이 버퍼링됩니다.
을 누르면 Ctrl-C해당 버퍼가 아직 기록되지 않았기 때문에 손실됩니다.
무엇이든 사용하면 동일한 동작을 얻을 수 있습니다 stdio
. 예를 들면 다음과 같습니다.
grep . > file
비어 있지 않은 줄을 입력하고 키를 누르면 Ctrl-C파일이 비어 있음을 알 수 있습니다.
반면에 다음을 입력하십시오.
xinput test 10 > file
그런 다음 키보드로 충분히 입력하세요.완충기전체(최소 4k 출력)를 얻으면 볼 수 있습니다.문서한 번에 4k씩 증가합니다.
를 사용하면 for를 입력하여 버퍼를 플러시한 후 정상적으로 종료 grep
할 수 있습니다 . 의 경우 에는 그런 옵션이 없다고 생각합니다.Ctrl-Dgrep
xinput
버퍼링 은 stderr
기본적으로 수행되지 않으므로 다른 동작이 발생하는 이유를 설명합니다.fprintf(stderr)
에 xinput.c
하나를 추가 하면, 즉 수신 시 정상적으로 종료하도록 signal(SIGINT, exit)
지시하면 더 이상 null이 아니라는 것을 알 수 있습니다 (신호 처리기에서 라이브러리 함수를 호출하는 것이 안전하다고 보장되지 않으므로 충돌하지 않는다고 가정). printf가 버퍼에 쓰는지 고려하십시오. 이는 신호가 영역에 들어갈 때 발생할 수 있습니다.xinput
SIGINT
file
가능한 경우 다음 stdbuf
명령을 사용하여 버퍼링 동작을 변경할 수 있습니다 stdio
.
stdbuf -oL xinput test 10 > file
가지다이 사이트에 질문이 많아요이 재정의는 비활성화됩니다.표준 입력 및 출력버퍼링을 입력하면 더 많은 대체 솔루션을 찾을 수 있습니다.
답변2
/dev/tty
일반적인 리디렉션이 발생하지 않도록 명령을 직접 작성할 수 있습니다 .
$ cat demo
#!/bin/ksh
LC_ALL=C TZ=Z date > /dev/tty
$ ./demo >demo.out 2>demo.err
Fri Dec 28 10:31:57 2012
$ ls -l demo*
-rwxr-xr-x 1 jlliagre jlliagre 41 2012-12-28 11:31 demo
-rw-r--r-- 1 jlliagre jlliagre 0 2012-12-28 11:31 demo.err
-rw-r--r-- 1 jlliagre jlliagre 0 2012-12-28 11:31 demo.out
답변3
xinput
파일 출력은 거부하지만 터미널 출력은 거부하는 것 같습니다 . 이를 달성하기 위해 xinput
시스템 호출을 사용할 수 있습니다.
int isatty(int fd)
열려는 파일 설명자가 터미널을 참조하는지 확인합니다.
얼마 전 나는 이라는 프로그램에서 같은 현상을 우연히 발견했습니다 dpic
. 소스 코드를 살펴보고 디버깅을 한 후 관련 줄을 제거하고 isatty
모든 것이 다시 예상대로 작동했습니다.
하지만 나는 당신의 말에 동의합니다. 이 경험은 매우 충격적입니다. ;)
답변4
예. 나는 파스칼로 프로그래밍하던 DOS 시절에도 이런 일을 했습니다. 나는 다음과 같은 원칙이 여전히 유효하다고 생각합니다.
- 표준 출력 닫기
- 콘솔로 표준 출력 다시 열기
- 표준 출력에 출력 쓰기
이는 실제로 모든 파이프라인을 중단시킵니다.