화면을 종료하기 전에 어떻게 확인을 받을 수 있나요?

화면을 종료하기 전에 어떻게 확인을 받을 수 있나요?

화면을 종료하기 전에 확인하는 방법(명령줄에 종료를 입력하는 경우) 가능합니까?

답변1

나는 exit함수로 명령을 마스킹하여 이 문제를 해결했습니다. 이 함수는 사용자가 화면 안에 있는지, 그리고 해당 화면 프로세스에 남아 있는 유일한 하위 프로세스인지 확인합니다.

exit() {
  if  [[ "$(ps -o pid= --ppid "$(ps -o ppid= -p "$$")" | wc -l)" -eq 1 ]]
  then
    read -p "Warning: you are in the last screen window; do you really want to exit? (y/n) "
    case $REPLY in
        (y*) command exit "$@" ;;
    esac
  else
    # not within screen at all, or not within the last screen window
    command exit "$@"
  fi
}

이 기능을 (bash) 구성 파일의 일부로 포함해야 합니다. 즉, ~/.bash_profile화면을 시작할 때 (달리 지정하지 않는 한) $SHELL 인스턴스를 시작합니다. 쉘은 스크린 프로세스의 하위 프로세스가 됩니다. 하위 쉘에서 종료할 때 위 코드는 현재 쉘의 상위 프로세스의 하위 프로세스 수를 확인합니다. 내부에서 밖으로:

  • $(ps -o ppid= -p "$$")-- =현재 프로세스의 상위 PID를 요청합니다(억제 헤더 라인 추가)( $$)
  • $(ps -o pid= --ppid ... | wc -l)-- 상위 PID가 우리의 상위인 PID 목록(헤더 없이)을 요청한 다음 출력된 행 수를 계산합니다.

우리가 screen 세션의 마지막 자식인 것처럼 보이면 확인 메시지가 표시됩니다. 응답이 문자로 시작하면 y함수는 "실제" exit명령을 호출하여 셸을 종료합니다.

우리가 마지막 자식 프로세스가 아닌 경우 함수는 계속 실행되고 정상적으로 종료됩니다.

이것을 개발할 때 주의해야 할 몇 가지 사항이 있습니다.

  • if처음에는 스크린 세션에 있는지 확인하기 위해 STY채워졌는지, SHLVL1보다 큰지 확인하는 등 더 많은 테스트를 수행했습니다 . 화면은 STY를 설정하고 bash는 SLVL을 증가시키지만 이러한 변수 중 어느 것도 읽기 전용이 아니므로 이 테스트는 많이 사용할 만큼 강력하지 않습니다.

  • screen 도 WINDOW변수를 설정하지만 이를 확인하는 0것은 신뢰할 수 없습니다. 두 개의 창을 연 다음 window 를 닫고 0window 를 1마지막 창으로 남겨 둘 수 있습니다.

  • 기본적으로 EOF(보통 Control+ D)를 입력하면 이 래퍼 기능을 우회하여 셸이 즉시 종료됩니다. 내가 아는 가장 좋은 해결 방법은 변수를 IGNOREEOF0이 아닌 값으로 설정하는 것입니다. 그러나 이는 불가피한 쉘 종료를 지연시킬 뿐입니다.

위에서는 bash(및 GNU procutils) 관련 기능을 많이 사용하고 있기 때문에 POSIX 호환 솔루션도 제공하고 싶었습니다. 이 줄을 특정 상위 PID가 있는 프로세스 수를 캡처하는 시나리오 ps로 변경합니다. 또 다른 변경 사항은 프롬프트 및 를 ps ... | grep -c재작업하는 것입니다 .read -pread

exit() {
  parent="$(ps -o ppid= -p $$)"
  if [ "$( ps -eo ppid= | grep -c "^ *${parent}\$" )" -eq 1 ]
  then
    printf "Warning: you are in the last screen window; do you really want to exit? (y/n) "
    read REPLY
    case $REPLY in
        (y*) command exit "$@" ;;
    esac
  else
    # not within screen at all, or not within the last screen window
    command exit "$@"
  fi
}

답변2

나는 당신이 bash를 사용하고 있다고 가정합니다.

are_u_sure(){
        read -n1 -p "Are you sure to exit? [y/N] "
        [ "$REPLY" != y ] && { echo; history -a; bash; }
}

trap are_u_sure EXIT

이것을 ~/.bashrc에 추가하면 bash를 종료하려고 할 때마다 메시지가 표시됩니다(exit 또는 ^D 입력). "y"를 누르지 않으면 절대 종료되지 않습니다.

이렇게 하면 bash 범위 내에서 화면 마법을 수행할 수 있으므로 화면 마법에 집착할 필요가 없습니다.

이 방법은 매우 간단하기 때문에 한 가지 단점이 있습니다. 즉, 이전에 입력한 변수 할당을 잃게 됩니다. 하지만 아마도 우리는 그 일을 할 수 있을 것입니다. 어쨌든 필요에 맞게 이 코드를 수정할 수 있습니다.

답변3

나는 내가 본 다른 솔루션에 너무 만족하지 않았기 때문에 결국 다음을 사용하게 되었습니다(.bashrc에 추가됨).

exit_with_prompt() {
    printf "Do you really want to exit screen? (y/n) "
    read REPLY
    case $REPLY in
        (y*) command exit "$@" ;;
    esac
}

export IGNOREEOF=0
[[ $(type -t exit) == "alias" ]] && unalias exit
[[ $(type -t logout) == "alias" ]] && unalias logout

if grep -q "^screen\b" /proc/$PPID/comm; then
    export IGNOREEOF=2
    alias exit=exit_with_prompt
    alias logout=exit_with_prompt
fi

그런 다음 이것을 .screenrc에 추가하십시오.

shell -$SHELL

제가 평소에 하던 방식이랑 좀 반대네요. 별칭을 설정 해제하고 ctrl-d -> 종료를 다시 활성화하지만 bash가 화면 인스턴스 내에서 즉시 실행되고 있는지 확인합니다(구체적으로 상위 프로세스 명령이 "screen"으로 시작한 다음 단어 경계로 시작하는지 확인합니다). 그런 다음 ctrl-d/EOF 종료를 비활성화하고 종료 및 로그아웃을 위한 프롬프트 별칭을 사용하여 종료를 설정합니다.

오랫동안 사용하지는 않았지만 현재까지는 작동 방식에 매우 만족합니다.

관련 정보