이미 실행중인 스크립트에서 stderr를 리디렉션


14

나는 며칠 동안 스크립트를 실행 해 왔습니다. stdout을로 리디렉션 $HOME/mylog했지만 아무것도 없을 것이라고 생각했기 때문에 stderr를 리디렉션하지 않았습니다. 갑자기 수천 개의 회선이 stderr에서 나오기 시작하여 작업을 중단했습니다. $HOME/myerr스크립트를 다시 시작할 필요없이 stderr을 지금부터 리디렉션 할 수있는 방법이 있습니까?

상자에 sudo 액세스 권한이 있으며 OS X입니다.

아마도 dtools trapping을 사용하는 것이 있습니까?

스크립트가 지금까지 한 작업을 잃어 버릴 수 없으며 처음부터 다시 시작할 수 없습니다. 디스크에 "메모리 내 개체를 덤프"하고 프로그램을 정지 시키며 변수 (예 : 파일 설명자)를 편집 하고 새로운 컨텍스트로 다시 시작 하는 방법이 있습니까?


답변:


12

관련 통역사의 프로세스를 gdb에 첨부하면 가능하다고 생각합니다. 이 펄 원 라이너로 시도했습니다

 perl -e 'do { print "x\n"; sleep(1) } while(1)'

불행히도 비슷한 bash 스크립트로는 작동하지 않습니다.


먼저 출력을 캡처하려는 프로세스의 PID를 파악해야합니다. 그런 다음 gdb다른 터미널에서 시작 하여 다음 gdb 명령을 실행하십시오.

attach PID
call close(2)
call open("/abs/olu/te/path/filename", 65, 384)
detach PID

그 후에 기록 된 전체 데이터 stderr가로 리디렉션됩니다 /abs/olu/te/path/filename.

  • attach PID 프로세스를 gdb에 첨부하고 중지
  • call close(2)stderr프로세스 의 파일 디스크립터를 닫습니다 (파일 stdout디스크립터가 1 인 경우).
  • call open(...) 새 파일을 열고 새로 작성된 파일 설명자에 대해 사용되지 않은 최저 정수를 취합니다.
  • detach PID 프로세스를 계속

적어도 내 컴퓨터에서는 처음 두 줄은 POSIX와 호환되지만 세 번째 줄은 아닙니다.

open세 번째 줄 의 두 번째 및 세 번째 인수는 에 설명되어 man 2 open있습니다. 필자의 경우 65 open는 파일을 만들고 쓰기 전용 파일을 열어야 함을 의미합니다 O_WRONLY | O_CREAT( 즉 ,에 정의 됨 fcntl.h). 세 번째 인수는 open에 사용자에게 읽기 및 쓰기 권한이있는 파일을 작성하도록 지시합니다 S_IWUSR | S_IRUSR(에 정의 됨 sys/stat.h). 따라서 컴퓨터에서 적절한 값을 스스로 찾아야 할 수도 있습니다.


이것은 매우 훌륭하게 작동했습니다 ... 모자 제거!
로봇 티노 시노

8

이것은 조잡한 대답이며 다른 사람이 더 잘하기를 바랍니다. 그러나 다른 아이디어가 없다면 gdb를 첨부하고 프로세스를 강제로 몇 번의 시스템 호출을하십시오.

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c

맵시 있는. 나는 gdb가 그렇게 할 수 있다는 것을 몰랐다. 특정 파일 디스크립터 번호로 강제하는 방법이 있습니까? FD 1을 사용하지 않고 FD 1을 잡는 것처럼 말 open()합니까? 아니면 dup()몇 번만 전화해야 합니까?
Patrick

않습니다 p open("errfile", O_WRONLY)정말 컴퓨터에 작업?
user1146332

a를 붙인 p dup2(xxx, 2)다음 의 반환 값은 p close(xxx)어디에 있습니까 ? 이것은 까다로운 일이므로 다른 선택이 없을 때까지 장기 실행 프로세스에서 이러한 명령을 사용하지 않는 것이 좋습니다. xxxopen
Alan Curry

@ user1146332 내가 사용하기 때문에 나는 그것을 시도 할 때했던 /dev/null내 것처럼 errfile내가 필요하지 않았다 O_CREAT. 그리고 O_WRONLY매크로되고,이 팽창 여부 GDB 디버깅 심볼들이 제공되며, 매크로 정의 된 라인의 처리를 중지할지 여부에 의존한다. gdb로 프로세스에 코드를 삽입하는 것은 위험하므로 아무도이 명령을 이해하지 않고 복사해서는 안됩니다.
Alan Curry

@AlanCurry 일반적인 디버깅 정보를 사용할 수 있다면 gdb가 매크로를 확장한다고 생각하지 않습니다. 특수 플래그를 사용하여 소스를 컴파일해야합니다 ( 여기 참조 ). 또한 시스템의 임의의 실행 파일에 디버깅 정보가 포함되어있는 경우는 매우 드 un니다 (독립적으로 정보가 매크로 정보로 확장 될 수 있음). 그러나 코드 삽입은 일반적으로 권장되지 않지만 이점이있는 경우가 있음에 동의합니다.
user1146332
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.