Bash 스크립트는 실행 방법을 어떻게 알 수 있나요?

Bash 스크립트는 실행 방법을 어떻게 알 수 있나요?

에코와 읽기를 통해 나에게 묻는 작은 변경 사항이 포함된 다소 복잡한 명령을 실행하는 데 도움이 되도록 만들려고 했던 Bash 스크립트가 있습니다.

명령을 실행하기 위해 터미널을 강제로 실행하는 솔루션을 찾았지만 관심이 없습니다. 내가 원하는 것은 노틸러스에서 공백을 두고 Enter 키를 누르면(소프트웨어 실행으로 실행되도록 함) "터미널에서 이것을 실행하십시오"라는 알림이 부드럽게 팝업되는 것입니다.

명령을 알고 있는 것처럼 팝업이 발생하도록 할 수 있지만 Bash 스크립트가 터미널 내부에서 실행되고 있는지 여부를 알려주는 것은 불가능합니다. 항상 그렇게 생각하는 것 같습니다. 심지어 가능합니까?

답변1

man bash아래 에서조건식:

-t fd  
    True if file descriptor fd is open and refers to a terminal.

fd 1이 표준 출력이라고 가정하면 if [ -t 1 ]; then효과가 있을 것입니다. 그만큼고급 쉘 스크립팅 가이드-t이 방법을 사용한 주장은 장애 조치될 것이며 ssh따라서 테스트(stdout이 아닌 stdin을 사용하여)는 다음과 같아야 합니다.

if [[ -t 0 || -p /dev/stdin ]]

-p파일이 존재하고 명명된 파이프인지 테스트합니다. 하지만, 나는 경험적으로 이것이 나에게 사실이 아니라는 점을 지적하고 싶습니다. -p /dev/stdin일반 터미널과 ssh 세션 모두에서 실패하는 반면 if [ -t 0 ](or -t 1)는 두 경우 모두에서 작동합니다(또한 해당 섹션의 문제에 대한 아래 Gilles 의견 참조).고급 쉘 스크립팅 가이드).


주요 문제가 해당 컨텍스트에 적합한 방식으로 작동하도록 스크립트를 호출하려는 특수 컨텍스트인 경우 래퍼와 사용자 정의 변수를 사용하여 이러한 모든 기술을 회피하고 번거로움을 덜 수 있습니다.

!#/bin/bash

export SPECIAL_CONTEXT=1
/path/to/real/script.sh

live_script.sh이것 저것 호출 하고 대신 저것을 더블클릭하세요. 물론 명령줄 인수를 사용하여 동일한 작업을 수행할 수 있지만 GUI 파일 브라우저에서 가리키고 클릭하는 작업을 수행하려면 래퍼가 여전히 필요합니다.

답변2

bash $SHLVL 변수를 사용하여 쉘 중첩 수준을 감지하십시오. 두 번 클릭하여 'raw'를 실행하는 스크립트에서는 1이 되고, 터미널 내에서 실행되는 스크립트에서는 2가 됩니다.

#!/bin/bash
if (( SHLVL < 2 )) ; then
    echo "Please run this from a terminal."
    read -p "Press <Enter> to close this window"
    exit 1
fi
# rest of script

참고: (( )) 내의 숫자 변수를 테스트할 때는 $가 필요하지 않습니다.

답변3

일반적인 경우에는 골디락스의 대답이 맞을 수도 있지만 극단적인 경우도 있는 것 같습니다. 내 경우에는 xserver가 시작되도록 구성되어 tty1있으며 해당 tty를 떠나지 않습니다. Xorg가 stdoutTTY인 경우 클라이언트는 기본적으로 해당 TTY를 파일 설명자에 연결하는 것 같습니다.

내 문제를 해결한 방법은 다음과 같습니다.

#!/bin/bash
isxclient=$( readlink /dev/fd/2 | grep -q 'tty' && [[ -n $DISPLAY ]] ; echo $? )
if [[ ! -t 2  || $isxclient == "0" ]]; then
        notify-send "Script wasn't started from an interactive shell"
else
        echo "Script was started from an interactive shell"
fi

나는 이것이 더 표준적인 X 구성에서 작동하는지 확인하기 위해 이것을 테스트하지 않았으며 이것이 유일한 극단적인 경우인지도 의심합니다. 보다 일반적으로 적용 가능한 솔루션을 찾은 사람이 있으면 다시 돌아와서 알려주십시오.

답변4

또 다른 하나는 bash 옵션을 사용하여 내부 변수를 설정하는 $-.

에서 .bashrc,

# If not running interactively, don't do anything
case $- in
    *i*) ;;
    *) return;;
esac

관련 정보