스크립트에서 가장 가까운 대화형 조상 셸의 이름을 어떻게 얻을 수 있나요?

스크립트에서 가장 가까운 대화형 조상 셸의 이름을 어떻게 얻을 수 있나요?

$-당신이 포함을 사용할 수 있다는 것을 알고$PS1쉘이 대화형인지 여부를 판별하기 위해 널을 검사하거나 검사합니다 .

그러나 이러한 솔루션은 현재 셸에서만 작동합니다.

대화형 직접 상위 쉘을 찾으려는 bash 스크립트가 있습니다.

예를 들어:

  1. 대화형 셸: zsh
  2. bash 스크립트 1 bash 스크립트 2 실행
  3. bash 스크립트 2에는 실시간 대화형 셸을 찾는 메커니즘이 포함되어 있습니다.

따라서 대화형 셸에서 bash 스크립트 1을 실행할 때 zsh출력은 zsh.

스크립트가 서브셸에서 실행될 때 이 작업을 수행하는 방법을 모르겠습니다.

노트

스크립트를 실행하는 것이 아니라 실행하고 싶습니다.

밝히다

첫 번째 대화형 조상 쉘을 찾으려는 bash 스크립트가 있습니다.

첫 번째 조상이란 상향식 프로세스 체인 스캔 중에 만난 첫 번째 대화형 셸을 의미합니다.

예를 들어 다음과 같은 경우: zsh(첫 번째 대화형 쉘) -> bash(두 번째 대화형 쉘) -> bash(스크립트 1의 배치 쉘) -> bash(스크립트 2의 배치 쉘), 우리는 bash(두 번째 대화형 쉘)를 출력하려고 합니다. 껍데기).

답변1

이것은 매우 이상한 요청입니다. 어떤 대화형 쉘이 스크립트를 호출하는지, 또는 대화형 쉘이 아닌 다른 프로그램을 호출하여 스크립트를 호출하는지 신경 써야 하는 이유는 무엇입니까? 이거 냄새가 엄청 강해요XY 문제.

꼭 알아야 한다면 알아내려고 노력할 수 있지만 완전히 신뢰할 수 있는 방법은 없고 일반적인 상황에서 작동하는 방법은 하나만 있는 것 같습니다.

처음부터 시작하여 찾고 있는 프로세스를 찾을 때까지 또는 너무 멀리 갔음을 나타내는 프로세스를 찾을 때까지 $PPID스크립트의 조상 프로세스( )를 추적합니다 .ps -o ppid= -p $ancestor_pid

간단한 전략은 다양한 프로세스 그룹( )에서 프로세스를 찾는 것입니다 ps -o pgid= -p $ancestor_pid. 일반적인 상황에서 스크립트가 대화형 셸(호출되는 스크립트)에 의해 호출되는 경우 도달하는 프로세스는 스크립트(스크립트의 상위)를 실행하는 작업 제어 기능이 있는 셸입니다.

이 전략이 잘못될 수 있는 몇 가지 예는 다음과 같습니다.

  • 체인의 프로세스 중 하나가 종료되었습니다.
  • 스크립트는 대화형 셸을 통해 호출되지 않고 크론 작업, X11 프로그램 등을 통해 호출됩니다.

lsof프로세스의 표준 입력, 표준 출력 및 표준 오류(예: Linux 외부로의 이식성이 필요하지 않은 경우 사용 또는 통해)가 스크립트와 동일한 터미널인지 확인하고 싶을 수도 있고 원하지 않을 수도 있습니다 . /proc다음과 같은 상황을 어떻게 처리하려는지에 따라 다릅니다.

bash$ xterm -e your_script

답변2

옵션을 확인하세요.

[ "$-" = "${-#*i}" ] ||
echo shell is interactive

파일 설명자를 확인할 수도 있습니다. 이것은 조금 다릅니다. 셸 자체가 대화형인지 여부는 반드시 알려주지는 않지만 터미널과 통신하는지 여부는 알려줍니다.

for fd in 0 1 2
do     [ -t "$fd" ] && 
       break 
done|| echo shell fds 0 1 2 are not connected to a terminal.

우리는 약간의 해킹을 통해 터미널의 모든 용도를 알아내려고 노력할 수 있습니다.

tty_users()
    for fd in 0 1 2 "$@"
    do     [ -t "$fd" ] && {
           fuser "$(tty)"
           break; } <&"$fd"
    done 

현재 셸에서 실행되고 처음 감지된 터미널에서 실행 중인 프로세스의 프로세스 ID 목록을 인쇄합니다.std(in|out|err) (기본값 - 다른 인수를 테스트하려면 함수 숫자 인수를 전달합니다.)각기. 쉘 변수를 $fd이 터미널과 연결된 파일 설명자 번호로 설정하거나, 표준 설명자가 없거나 터미널과 연결된 인수가 없으면 false를 반환합니다.

위의 내용은 터미널의 세션 ID(있는 경우)를 찾지 않는 한 얻을 수 있는 가장 가까운 정보일 것입니다.

ps -osid= -p"$$"

그러면 제어 터미널 소유자의 pid가 반환됩니다(있는 경우).

전시하다:

echo "$$"; sh -c 'sh -c "ps -osid= -p\"\$$\""' 

6023
6023

하지만 이런 것들에만 의존할 수는 없습니다. 전혀 그렇지 않습니다. 바라보다:

sh -acm 'IFS=\; i=0;eval "$0"'          \
        '[ "$i" -lt 5 ] && eval "$*"'   \
        'ps -opid -opgid -p"$$"'        \
        'sh -acm "$0" "$0" "$@" i=$((i+=1))'
  PID  PGID
28766 28766
  PID  PGID
28768 28768
  PID  PGID
28770 28770
  PID  PGID
28772 28772
  PID  PGID
28774 28774

바라보다? 내가 이러한 프로세스를 실행하는 대화형 셸은 해당 목록에도 없습니다. 각 sh하위 프로세스는 깊이가 5에 도달할 때까지 자체 하위 프로세스를 시작하고, 각 하위 프로세스가 깊이에 도달하면 psPID 및 PGID 인쇄를 호출합니다.모든프로세스는 새로운 PGID를 얻습니다. 작업 제어는 터미널이 작업을 테스트하는 더 직접적인 방법이라는 점을 제외하면 터미널과 마찬가지로 대화형 셸과 관련되어 있습니다.

관련 정보