하위 프로세스가 bash 프롬프트를 방해하는 것을 방지하는 방법은 무엇입니까?

하위 프로세스가 bash 프롬프트를 방해하는 것을 방지하는 방법은 무엇입니까?

관련 응용 프로그램은 DaVinci Resolve입니다. 터미널에서 실행합니다. 닫으면 애플리케이션의 "Socket Disconnected" 메시지가 터미널 출력에 기록됩니다. 그러면 bash 프롬프트가 정상적으로 표시됩니다. 새 명령을 입력하기 시작했는데 갑자기 "소켓 연결 끊김" 터미널에 또 다른 메시지가 나타났습니다. 이것은 내가 입력하는 것을 방해합니다. 다음과 같습니다.

[andrew@unihost ~]$ davinci-resolve
... # Now I exit the application.
Host 'Fusion' Removed
FusionScript Server [37457] Terminated
Socket disconnected
[andrew@unihost ~]$ ls ls Socket disconnected
wtf!!!^C
[andrew@unihost ~]$

비디오 데모:https://youtu.be/arcCOjrN7kw

왜 이런 일이 발생합니까? 이런 일이 발생하지 않도록 하는 방법이 있나요?

내 생각에는 기본 프로세스에 기본 프로세스가 종료된 후에도 지속되는 하위 프로세스가 있는 것 같습니다. 내가 찾았어이것답변. 이게 개발자의 잘못인가요? 이 문제를 어떻게든 해결할 수 있나요(하위 프로세스가 없더라도)?

답변1

예비 설명

davinci-resolve나는 그것을 전혀 테스트하지 않았습니다. 이 답변은 일반적으로 설계되었습니다.


분석하다

쉘은 davinci-resolve다시 전경으로 돌아가서 프롬프트를 인쇄하기 전에 종료될 때까지 기다립니다. 분명히, davinci-resolve메인 프로세스가 종료되고 쉘이 반응한 후, 메인 프로세스의 일부 하위 프로세스(또는 후속 프로세스)가 원치 않는 메시지를 인쇄합니다.


해결책

해결책은 간단할 수 있습니다.

davinci-resolve | cat

요령은 cat파이프에 쓰는 모든 프로세스가 파이프 끝을 닫을 때까지 종료하지 않는 것입니다. 문제가 있는 자식은 아마도 메인에서 stdout을 상속받아 이를 기다릴 davinci-resolve것입니다 . cat일반적으로 이는 원치 않는 메시지가 stderr 또는로 인쇄되는 경우에도 작동합니다 /dev/tty(즉, 우리 메시지를 우회합니다 cat). 다른 곳에서 인쇄 중이더라도 아이가 파이프를 열어 두는 것이 중요합니다.

단점도 있습니다:

  • cat전체 파이프라인의 종료 상태는 가 아닌 에서 옵니다 davinci-resolve.일부 쉘에서는 다음과 같은 작업을 수행할 수 있습니다..

  • 전자는 통과되고 후자는 통과되지 않기 때문에 (및 그 하위 항목)의 stdout 및 stderr은 davinci-resolve동기화되지 않습니다 .cat

  • Ctrl+ 경우 c인쇄가 끝나기 전에 다른 프로세스를 종료할 수 있으므로 cat실제로 보고 싶은 일부 출력을 놓칠 수 있습니다. 또한 문제가 있는 메시지가 stderr에 인쇄되면 아마도 프롬프트를 본 후에 어쨌든 인쇄될 것입니다.

    + 면역을 만들 수 있습니다 cat:Ctrlc

    davinci-resolve | sh -c 'trap "" INT; exec cat'
    
  • 문제가 있는 프로세스는 조기에 종료되거나 표준 출력을 리디렉션할 수 있지만 여전히 표준 오류로 인쇄됩니다. 이 경우에는 기다릴 필요가 없습니다 cat.

  • 문제가 있는 프로세스는 지속되도록 설계되었을 수 있으며 원치 않는 메시지가 프로세스가 종료되었다는 의미는 아닙니다. 이 프로세스가 여전히 존재하고 파이프를 열어둔다면 우리 cat의 의지도 계속 존재할 것입니다. davinci-resolve버그가 없는 한 후손이 남을 가능성은 거의 없지만 일반적으로 그런 일이 발생할 수 있습니다.

어떤 이유로 stdout을 전달하고 싶을 수도 있습니다.그리고표준 오류는 통과됩니다 cat. Immunity cat+는 여전히 좋은 생각입니다 Ctrl.c

  davinci-resolve 2>&1 | sh -c 'trap "" INT; exec cat'

이제 stderr of(및 그 하위 항목)와 stdout을 구별할 수 없으며 davinci-resolve둘 다 catstdout을 전달합니다. 어쨌든 터미널에서 혼합하기를 원하기 때문에 문제가 되지 않습니다. 개별적으로 리디렉션하거나 캡처하려면 설정을 포기하고 처음부터 시작해야 합니다.

문제가 있는 프로세스가 조기에 종료되거나 stdout 및 stderr를 리디렉션하고 원치 않는 메시지를 /dev/tty(). 이 상황에서 우리가 할 수 있는 일은 아무것도 없습니다 cat.


쉘 기능

우리 솔루션을 셸 함수로 구현할 수 있습니다.

davinci-resolve() {
   command davinci-resolve "$@" 2>&1 | sh -c 'trap "" INT; exec cat'
}

이 함수는 에 인수 전달을 지원 davinci-resolve하지만 종료 상태는 프로세스 cat가 아닌 에서 옵니다(질문이 있는 경우 참조).davinci-resolve이미 링크가 제공되었습니다.아이디어).

답변2

control-l을 입력하여 화면을 지울 수 있습니다. 이렇게 하면 "소켓 연결 끊김" 메시지가 지워지지만 명령 프롬프트와 부분적으로 작성된 명령은 그대로 유지됩니다. 안타깝게도 davinci-resolve의 출력도 지워지는데, 이는 원하는 작업에 적합할 수도 있고 적합하지 않을 수도 있습니다.

답변3

기본 프로세스가 종료된 직후 "소켓 연결 끊김" 메시지가 나타나면 ; sleep 2명령에 추가하고 이를 쉘 별칭에 넣을 수 있습니다. 이는 기본적으로 새로운 명령을 바로 입력하지 않도록 상기시키기 위한 방법입니다. 이렇게 하려면 다음을 추가하세요.

alias davinci-resolve="davinci-resolve; sleep 2"

귀하의 .bashrc에

답변4

백그라운드 프로세스는 실제로 쉘을 방해하지 않으며 단지 화면에 낙서를 하고 있을 뿐이며 백그라운드 프로세스의 출력과 쉘이 혼합됩니다.

이 문제를 해결하는 방법에는 여러 가지가 있습니다.

  • 파일 리디렉션과 같은 기능을 사용하여 터미널에서 메시지를 삭제 하거나 nohup파일에 저장할 수 있습니다.
  • 이 횡설수설을 무시하고 계속 입력하거나, 아무 것도 입력하지 않은 경우 Enter를 누르면 새 프롬프트가 표시됩니다.
  • 백그라운드 프로세스에서 보낸 메시지를 읽은 다음 명령줄 편집 키 입력을 사용하여 입력한 내용을 새로 고치고 다시 읽을 수 있게 만들 수 있습니다. 일반 터미널 모드에서는 Ctrl-R이 작업이 수행됩니다. Bash와 같은 다른 많은 응용 프로그램에서는 Ctrl-L화면이 지워지고 프롬프트와 입력한 내용이 다시 인쇄됩니다.
  • 전용 창에서 애플리케이션을 실행하고 그래픽 창 시스템의 기능을 사용하여 해당 출력으로 인해 오염되지 않은 다른 창을 열 수 있습니다. :) (이렇게 시끄러운 어플리케이션을 실행시키기 위해 옆에 작은 창을 남겨두었습니다.)
  • 애플리케이션을 종료한 후에 이런 일이 발생하고 중지하려는 작업자 스레드가 뒤에 남아 있는 경우 ps -t터미널에서 현재 실행 중인 항목을 표시하기 위해 해당 스레드를 찾아 종료할 수 있습니다.

관련 정보