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

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

약간의 변경 사항이 포함된 상당히 복잡한 명령을 실행하는 데 도움이 되도록 만들려고 하는 Bash 스크립트가 있는데 에코 및 읽기를 통해 이에 대한 정보를 요청합니다.

명령을 실행하기 위해 터미널을 강제로 실행하는 솔루션을 찾았지만 그것에는 관심이 없습니다. 내가 원하는 것은 Nautilus에 공간을 만들고 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테스트(표준 출력이 아닌 표준 입력 사용)는 다음과 같아야 합니다.

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

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


주요 문제가 해당 컨텍스트에 적합한 방식으로 호출 스크립트를 실행하려는 특수한 컨텍스트인 경우 래퍼 및 사용자 정의 변수를 사용하여 이러한 모든 기술적 세부 사항을 회피하고 문제를 줄일 수 있습니다.

!#/bin/bash

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

이 이름 또는 다른 이름을 부르고 live_script.sh두 번 클릭하십시오. 물론 명령줄 인수를 사용하여 동일한 작업을 수행할 수 있지만 GUI 파일 브라우저에서 가리키고 클릭하는 작업이 제대로 작동하도록 하려면 여전히 래퍼가 필요합니다.

답변2

bash $SLVL 변수를 사용하여 쉘 중첩 수준을 감지하십시오. 두 번 클릭하여 "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

일반적인 경우에는 Goldilocks의 답변이 정확할 수 있지만 극단적인 경우도 있는 것 같습니다. 제 경우에는 xserver가 해당 tty에서 시작 tty1하고 절대 해당 tty를 떠나지 않도록 구성되어 있습니다. Xorg stdout가 TTY인 경우 클라이언트는 기본적으로 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

관련 정보