나는 이것을하는 데 너무 익숙해졌습니다.
someprogram >output.file
프로그램이 생성하는 출력을 파일에 저장하려고 할 때마다 수행합니다. 또한이 IO 리디렉션 의 두 가지 변형을 알고 있습니다 .
someprogram 2>output.of.stderr.file
(stderr 용)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 user @ hostname : ~ $
이 출력은 평소처럼을 사용하여 파일에 저장할 수있을 것으로 기대했습니다 xinput test 10 > output.file
. 그러나 내 기대와 달리 파일 output.file은 비어 있습니다. 이것은 xinput test 10 &> output.file
stdout 또는 stderr에서 무언가를 놓치지 않도록하기 위해서도 마찬가지입니다 .
나는 정말로 혼란 스러우므로 xinput
프로그램이 출력을 리디렉션하지 않는 방법이 있는지 물어보십시오 .
최신 정보
나는 출처를 보았다. 이 코드에 의해 출력이 생성되는 것 같습니다 (아래 스 니펫 참조). 출력이 일반 printf에 의해 생성되는 것처럼 보입니다.
// 파일 test.c에서 static void print_events (디스플레이 * dpy) { XEvent 이벤트; while (1) { XNextEvent (dpy, & Event); // [... 다른 이벤트 유형은 여기에서 생략됩니다 ...] if ((Event.type == key_press_type) || (Event.type == key_release_type) { int 루프; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ( "key % s % d", (Event.type == key_release_type)? "release": "press", 키-> 키 코드); for (loop = 0; loopaxes_count; 루프 ++) { printf ( "a [% d] = % d", 키-> first_axis + 루프, 키-> axis_data [loop]); } printf ( "\ n"); } } }
소스를 이것으로 수정했습니다 (아래 스 니펫 참조). stderr에 출력 사본을 가질 수 있습니다. 이 출력은 리디렉션 할 수 있습니다.
// 파일 test.c에서 static void print_events (디스플레이 * dpy) { XEvent 이벤트; while (1) { XNextEvent (dpy, & Event); // [... 다른 이벤트 유형은 여기에서 생략됩니다 ...] if ((Event.type == key_press_type) || (Event.type == key_release_type) { int 루프; XDeviceKeyEvent * key = (XDeviceKeyEvent *) & Event; printf ( "key % s % d", (Event.type == key_release_type)? "release": "press", 키-> 키 코드); fprintf (stderr, "key % s % d", (Event.type == key_release_type)? "release": "press", 키-> 키 코드); for (loop = 0; loopaxes_count; 루프 ++) { printf ( "a [% d] = % d", 키-> first_axis + 루프, 키-> axis_data [loop]); } printf ( "\ n"); } } }
현재 내 생각은 리디렉션을 수행하면 프로그램이 키 누름 키 릴리스 이벤트를 모니터링하는 기능을 잃어 버릴 수 있다는 것입니다.
답변
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)
, 그 말씀이다 xinput
는 수신 정상적으로 때 종료 SIGINT
당신이 볼 수없는 것, file
무엇을 고려 : 안전이 보장되지는 신호 처리기에서 라이브러리 함수를 호출로 (이 충돌하지 않는 가정이 더 이상 비어 printf가 버퍼에 쓰는 동안 신호가 들어 오면 발생할 수 있습니다).
사용 가능한 경우 stdbuf
명령을 사용 하여 stdio
버퍼링 동작 을 변경할 수 있습니다 .
stdbuf -oL xinput test 10 > file
있습니다 이 사이트에 많은 질문 하지 않도록 다루 표준 입출력 당신이 더 많은 다른 솔루션을 찾을 수 있습니다 유형 버퍼링.
답변
명령은 /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
답변
xinput
파일에 대한 출력은 거부하지만 터미널에 대한 출력은 거부하지 않는 것 같습니다 . 이를 위해서는 아마도 xinput
시스템 호출을 사용하십시오
int isatty(int fd)
열 파일 설명자가 터미널을 참조하는지 여부를 확인합니다.
나는라는 프로그램으로 얼마 전에 같은 현상을 발견했다 dpic
. 소스와 일부 디버깅을 살펴본 후 관련 줄을 제거 isatty
하고 모든 것이 다시 예상대로 작동했습니다.
그러나 나는이 경험이 매우 혼란 스럽다는 것에 동의합니다.)
답변
당신의에서 test.c
파일 당신은 사용 버퍼링 된 데이터를 플러시 할 수 (void)fflush(stdout);
귀하의 직후 printf
문.
// in test.c
printf("key %s %d ", (Event.type == key_release_type) ? "release" : "press ", key->keycode);
//fprintf(stderr,"key %s %d ", (Event.type == key_release_type) ? "release" : "press ", key->keycode);
//(void)fflush(NULL);
(void)fflush(stdout);
명령 행에서 명령 xinput test 10
으로 의사 터미널 (pty)에서 실행하여 라인 버퍼 출력을 사용할 수 있습니다 script
.
script -q /dev/null xinput test 10 > file # FreeBSD, Mac OS X
script -c "xinput test 10" /dev/null > file # Linux
답변
예. 파스칼로 프로그래밍 할 때 DOS 시간 에도이 작업을 수행했습니다. 나는 원칙이 여전히 유지한다고 생각합니다.
- stdout 닫기
- 콘솔로 stdout을 다시여십시오
- 출력을 stdout에 씁니다.
이로 인해 파이프가 파손되었습니다.
답변
