bash 스크립트에서 루트로 실행 중인지 확인하는 방법


274

루트 수준의 권한이 필요한 스크립트를 작성 중입니다. 스크립트가 루트로 실행되지 않는 경우 단순히 "루트로 실행하십시오."라는 메시지를 표시합니다. 종료합니다.

내가 찾고있는 의사 코드는 다음과 같습니다.

if (whoami != root)
  then echo "Please run as root"

  else (do stuff)
fi

exit

어떻게하면 깨끗하고 안전하게 최선을 다할 수 있습니까? 감사!

아, 분명히 말하면 : (작업) 부분에는 자체적으로 루트가 필요한 명령을 실행하는 것이 포함됩니다. 따라서 일반 사용자로 실행하면 오류가 발생합니다. 이것은 스크립트 내에서 sudo를 사용하지 않고 루트 명령이 필요한 스크립트를 깨끗하게 실행하기위한 것입니다. 저는 구문 설탕을 찾고 있습니다.


8
(1) 다른 어떤 것에 의해서도 실행 가능하지 않게 한 다음 루트 (2) 추가 권한도 준비하십시오. (3) 루트로 id -u돌아갑니다 0.
Wrikken

답변:


403

$ EUID 환경 변수는 현재 사용자의 UID를 보유합니다. Root의 UID는 0입니다. 스크립트에서 다음과 같은 것을 사용하십시오.

if [ "$EUID" -ne 0 ]
  then echo "Please run as root"
  exit
fi

참고 : 당신이 얻는 경우에 2: [: Illegal number:당신이있는 경우 검사를 #!/bin/sh상단과로 변경 #!/bin/bash.


좋은 권한과이를 갖는 것은 이중 보안 계층 ​​인 것 같습니다
Kolob Canyon

25
문자열과 문자열, 숫자와 숫자를 비교하는 것이 좋습니다. 이중 괄호를 사용하면 인용없이 바로 사용할 수 있습니다. [[$ EUID> 0]]
Sergio Abreu

7
2: [: Illegal number:그것을 Sergio의 버전으로 바꿀 때까지 경고를 받았습니다 .
alexeydemin

1
@ thekiwi5000 세미콜론은 then조건과 같은 줄에있는 경우에만 필요합니다 .
ptierno

1
@StephenAngelico Sudo가 작동해야합니다. $ sudo echo $ EUID를 수행하여 테스트하는 경우; 이것은 나쁜 테스트이며 명령이 sudo로 전달되기 전에 $ EUID가 확장되어 실패합니다. echo $ EUID를 테스트 스크립트에 넣고 sudo로 실행하십시오.
user1169420

79

bash 스크립트에서는 실행중인 사용자가 root인지 확인하는 몇 가지 방법이 있습니다.

A와 경고를 사용자가 루트가 사용하는 것입니다 있는지 확인하지 않는 root사용자 이름을. ID가 0 인 사용자가 호출된다는 보장은 없습니다 root. 광범위하게 따르는 매우 강력한 규칙이지만 누구나 슈퍼 유저 이름을 다른 이름으로 바꿀 수 있습니다.

bash 를 사용할 때 가장 좋은 방법 $EUID은 맨 페이지 에서을 사용 하는 것입니다.

EUID   Expands to the effective user ID of the current  user,  initialized
       at shell startup.  This variable is readonly.

이것은 $UID변경 될 수있는 보다 나은 방법이며 스크립트를 실행하는 실제 사용자를 반영하지 않습니다.

if (( $EUID != 0 )); then
    echo "Please run as root"
    exit
fi

내가 그런 종류의 문제에 접근하는 방법 sudo은 루트로 실행되지 않을 때 내 명령 을 주입 하는 것입니다. 예를 들면 다음과 같습니다.

SUDO=''
if (( $EUID != 0 )); then
    SUDO='sudo'
fi
$SUDO a_command

이렇게하면 수퍼 유저를 sudo사용할 때 또는 일반 사용자 가 실행할 때 내 명령이 루트로 실행됩니다.

스크립트가 항상 루트에서 실행되는 경우 이에 따라 권한을 설정하십시오 ( 0500).


스크립트를 실행하려는 사람에게 sudo 권한이 없으면 오류가 발생하고 명령이 실행되지 않습니까? 나는 확실히 이해하고 싶다.
Caperneoignis

1
이 답변이 100 % 완전히 정확한지 확실하지 않습니다. Bash 4.2.46을 사용하는 RHEL7.2에서 ... printf $EUIDsudo를 사용하거나 사용하지 않으면 내 UID를 다시 얻습니다. 내가 사용 id -u하면 UID를 얻고 sudo로 호출하면 0이 반환됩니다. 내가 뭐 잘못 했어요?
0xSheepdog

4
@ 0xSheepdog, bash cli에서 $ EUID 변수 확장이 먼저 해결 된 다음 sudo가 사용자를 변경할 수 있습니다. 따라서 그 동작을 얻을 수 있지만 스크립트에서는 모든 것이 여전히 잘 작동합니다.
Alexander Bird

@AlexanderBird 좋은 지적, 감사합니다! 나는 실제 테스트를하지 않았으며 방금 내 경험을보고했습니다.
0xSheepdog

3
변수의 로컬 쉘 확장을 막으려면 테스트에 "herestring"을 사용하십시오. 비교 sudo bash <<<'echo $EUID'bash <<<'echo $EUID'. tldp.org/LDP/abs/html/x17837.html의 heredoc
Bruno Bronosky

75

몇 가지 답변이 있지만 최선의 방법은 다음과 같습니다.

  • id -u
  • 루트로 실행하면 id 0을 반환합니다.

이것은 다른 방법보다 신뢰할 수있는 것으로 보이며 스크립트가 실행 되더라도 id 0을 반환하는 것으로 보입니다 sudo.


1
대답입니다
Dan Ortega

59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

또는

if [[ `id -u` -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

:)


Jeremy J Starcher의 답변 을이 부분과 통합하는 것을 고려할 수 있습니다 . 결국에는 항상 같은 것입니다.
reallynice

터미널에서 접두사로 무언가를 잊어 버렸을 때 sudo간단히 입력 할 수 있으며 sudo !!위쪽 화살표를 누르고 줄의 시작 부분으로 이동하여 sudo 직접 추가 하는 대신 작업을 수행합니다 . 그것이 BASH 일인지 SUDO 일인지 다른지 확실하지 않지만 대부분 항상 작동합니다.
0xSheepdog

@ 0xSheepdog : 이것은 Bash 일입니다 (IIRC가 시작된 csh와 같은 다른 쉘의 기능).
추후 공지가있을 때까지 일시 중지되었습니다.

대체로, 백틱 된 부분을 전체적으로 제거하고 ok 행을에 다시 씁니다 if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. 건배.
LinuxSecurityFreak

29

@ wrikken은 그의 의견에서 언급했듯이 id -u루트를 훨씬 잘 검사합니다.

또한을 올바르게 사용 sudo하면 스크립트를 확인하여 루트로 실행 중인지 확인할 수 있습니다. 그렇지 않은 경우이를 통해 자신을 리콜 sudo하고 루트 권한으로 실행하십시오.

스크립트의 기능에 따라 다른 옵션은 sudo스크립트에 필요한 특수 명령에 대한 항목 을 설정하는 것입니다.


프로그램 자체를 리콜 할 수있는 우아한 방법이 있습니까? 아마도 프로그램의 절대 경로가있는 bash 변수가 있습니까?
Nathan

1
현재 테스트 할 BASH 프롬프트 $0가 아니지만 실행중인 스크립트의 이름이 있습니다. 여기 도움이 될만한 몇 가지 예가 있습니다.
Jeremy J Starcher

25

루트 사용자에 대한 간단한 점검이 있습니다.

[[ stuff ]]구문은 떠들썩한 파티에서 검사를 실행의 표준 방법입니다.

error() {
  printf '\E[31m'; echo "$@"; printf '\E[0m'
}

if [[ $EUID -eq 0 ]]; then
    error "Do not run this as the root user"
    exit 1
fi

또한 실패하면 1로 종료한다고 가정합니다. 이 error기능은 출력 텍스트를 빨간색으로 설정 하는 기능입니다 (필요하지는 않지만 나에게 묻는다면 꽤 고급 스럽습니다).


error명령 은 무엇입니까 ? 내 시스템에는없는 것 같습니다. . .
ruakh

오, 그건 작은 감각 일뿐입니다. 그다지 중요하지는 않지만 첨부하겠습니다.
Slater Victoroff

4
꽤 괜찮은데! 몇 가지 개선 사항을 제안 할 수있는 경우 : (1) 줄 바꿈을 끝까지 이동하십시오. (2) 표준 출력보다는 표준 오류에 기록; (3) 표준 오류가 터미널 인 경우에만 색상을 설정합니다 (로그 파일에 이스케이프 문자를 쓸 위험이 있거나 less그렇지 않은 경우). 및 (4) 배경색을 설정하여, 사용자 단말기의 배경색에 관계없이 텍스트를 읽을 수있게한다. 그래서 function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (원하는대로 조정하십시오.)
ruakh

3
"-eq"대신 "-ne"이 아니어야합니까?
Carlos Rendon

2
@CarlosRendon Slater의 코드는 루트로 무언가가 실행되는 것을 방지하는 것입니다. (이것은 OP가 요구 한 것과 반대이지만 검사 방법은 동일합니다.)
Joshua Taylor

11

아주 간단한 방법은 다음과 같습니다.

if [ "$(whoami)" == "root" ] ; then
    # you are root
else
    # you are not root
fi

대신에 이것을 사용하면 id루트가 아닌 특정 사용자가 명령을 실행 중인지 확인할 수 있다는 이점이 있습니다. 예.

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi

"root"라는 문자열로 사용자를 테스트하는 경우 "root"라는 이름의 사용자를 실행할 수 없습니까?
pcarvalho

당신은 ';'을 잊었다 if 후
Triskeldeian

1
@peteroak 누가 루트 이외의 루트로 명명 될까요?
ptierno

3
실제로 whoami사용 하는 대신에 대한 질문에 대답하기 위해 +1 id; 이 whoami명령을 사용하여 루트가 아닌 다른 사용자를 이름 으로 확인할 수도 있습니다 .
Jez

10

0- 공식 GNU Linux 문서를 읽으십시오. 올바르게 수행하는 방법에는 여러 가지가 있습니다.

1- 해석시 오류를 피하기 위해 쉘 서명을 넣었는지 확인하십시오.

 #!/bin/bash

2- 이것은 내 스크립트입니다

#!/bin/bash 

if [[ $EUID > 0 ]]; then # we can compare directly with this syntax.
  echo "Please run as root/sudo"
  exit 1
else
  #do your stuff
fi

10

이 답변에서, 독자가 읽을 수 있다고 가정 bash하고 POSIX 쉘 스크립트를dash .

나는 투표가 많은 답변이 많은 것을 설명하는 좋은 일을하기 때문에 여기에 설명 할 것이 많지 않다고 생각합니다.

그러나 추가로 설명 할 것이 있으면 주저하지 말고 격차를 메우도록 최선을 다하겠습니다.


전체적으로 최적화 bash성능과 안정성을 위해 솔루션입니다. 모든 쉘 호환

새로운 솔루션 :

# bool function to test if the user is root or not
is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

벤치 마크 (파일로 저장 is_user_root__benchmark)

###############################################################################
##                          is_user_root() benchmark                         ##
##                  Bash is fast while Dash is slow in this                  ##
##          Tested with Dash version 0.5.8 and Bash version 4.4.18           ##
##                     Copyright: 2020 Vlastimil Burian                      ##
##                      E-mail: info@vlastimilburian.cz                      ##
##                             License: GPL-3.0                              ##
##                               Revision: 1.0                               ##
###############################################################################

# intentionally, the file does not have executable bit, nor it has no shebang
# to use it, please call the file directly with your shell interpreter like:

# bash is_user_root__benchmark
# dash is_user_root__benchmark

# bool function to test if the user is root or not
is_user_root () { [ ${EUID:-$(id -u)} -eq 0 ]; }

# helper functions
print_time   () { date +"%T.%2N"; }
print_start  () { printf '%s' 'Start  : '; print_time; }
print_finish () { printf '%s' 'Finish : '; print_time; }

readonly iterations=10000

printf '%s\n' '______BENCHMARK_____'
print_start

i=1; while [ $i -lt $iterations ]; do
    is_user_root
    i=$((i + 1))
done

print_finish

독창적 인 솔루션 :

#!/bin/bash

is_user_root()
# function verified to work on Bash version 4.4.18
# both as root and with sudo; and as a normal user
{
    ! (( ${EUID:-0} || $(id -u) ))
}

if is_user_root; then
    echo 'You are the almighty root!'
else
    echo 'You are just an ordinary user.'
fi

^^^ 파업 된 솔루션은 속도를 높이 지 않는 것으로 입증되었지만 오랜 시간 동안 사용되어 왔으므로 필요에 따라 여기에 보관할 것입니다.


설명

POSIX에 명령을 실행하는 것보다 $EUID표준 bash사용자 변수 인 효과적인 사용자 ID 번호 를 읽는 것이 훨씬 빠르기 때문에 사용자 ID를 찾기 만하면이 솔루션은 둘 다 훌륭하게 묶인 함수로 결합됩니다. is가 어떤 이유로 든 사용할 수없는 경우에만 명령이 실행 되어 상황에 관계없이 올바른 반환 값을 얻습니다 .id -u$EUIDid -u


OP가 요청한 오랜 세월이 지난 후에이 솔루션을 게시하는 이유

글쎄, 올바르게 보면 위의 코드가 누락 된 것 같습니다.

당신은 고려해야 할 많은 변수 가 있으며, 그중 하나는 성능과 신뢰성을 결합 하는 것입니다 .


휴대용 POSIX 솔루션 + 위 기능 사용 예

#!/bin/sh

# bool function to test if the user is root or not (POSIX only)
is_user_root() { [ "$(id -u)" -eq 0 ]; }

if is_user_root; then
    echo 'You are the almighty root!'
    exit 0 # unnecessary, but here it serves the purpose to be explicit for the readers
else
    echo 'You are just an ordinary user.' >&2
    exit 1
fi

결론

마음에 들지 않는 한, 유닉스 / 리눅스 환경은 다양해졌습니다. 좋아하는 사람들이 있다는 의미bash너무 이식성을 생각조차하지 않습니다 ( POSIX 쉘). 나와 같은 다른 사람들은 POSIX 쉘을 선호합니다 . 오늘날은 개인적으로 선택하고 필요로하는 문제입니다.


6

스크립트에 실제로 루트 액세스가 필요한 경우 파일 권한에이를 반영해야합니다. 루트가 아닌 사용자가 루트 스크립트를 실행 가능하게하는 것은 위험합니다. if수표로 액세스를 제어하지 않는 것이 좋습니다 .

chown root:root script.sh
chmod u=rwx,go=r script.sh

4
누군가가 권한을 가지고 있다면 이것이 잘 작동하지만 777폭탄을 과도하게 사용 하면 처음에는 실수를 한 사용자의 경우이 검사가 약간 잘못되는 것 같습니다.
Slater Victoroff

7
이것은 사용자가 실행 스크립트를 실행한다고 가정합니다. 사용자가 전화 bash /path/to/scripto=r
만해

5

루트로만 스크립트를 실행 가능하게하는 간단한 방법은 다음과 같이 스크립트를 시작하는 것입니다.

#!/bin/su root


1
이 답변이 왜 더 많이 투표되지 않는지 궁금합니다. 가장 단순하고 깨끗한 것 같습니다. 여기에 단점이 있습니까?
Bassinator

@Bassinator 어떤 사람들은 특정 nix에서 실행되지 않을 것이라고 말하지만 지금까지 내 Linux에서 완벽하게 작동했습니다. 시도 해봐! 어쩌면이 답변은 레이스에 늦었 지 만 커뮤니티에 간단한 지식을 추가하려고합니다 (이 스레드에서 가장 유사한 답변을하는 대신 : /). 귀하의 컴퓨터에서 작동
alexandre1985

@TamusJRoyce 목표가 루트로 실행 중인지 확인하고 스크립트를 루트로만 실행하지 않는 경우 왜 루트로 실행 중인지 확인한 후 모든 답변에서 스크립트를 작성하는 이유는 exit무엇입니까? 그리고 여전히 그 대답은 upvoted? 사람들이 암묵적으로 스크립트를 루트로 실행하기를 원하지 않는 것 같습니다. 그래서 나는 더 간단한 대답으로 그런 사고 방식을 따르고 있습니다. 그러나 네, 당신은 또한 위의 더 자세한 답변으로부터 배울 수 있습니다
alexandre1985

@ alexandre1985 정확합니다. 시나리오 : 루트로 실행중인 경우 프로그램 설치 방법을 묻는 메시지가 표시 될 때 스크립트를 기본적으로 프로그램을 기본적으로 설치하도록 할 수 있습니다. 그렇지 않으면 기본값이 로컬로 설치되도록 설정되어 있습니다. Enter 키를 누르는 대신 사용자가 전역 또는 로컬로 설치하도록 선택할 수 있습니다. 그러나 그들이 기본값을 좋아한다면 enter를 누르십시오. 그리고 그들은 암호를 요구하지 않을 것입니다. 당신이 (직위 당) 루트 경우 shebang은 "확인"하지 않습니다. 그러나 나는 여전히이 대답이 유용하다고 생각합니다.
TamusJRoyce

@TamusJRoyce는 귀하의 의견을 전적으로 이해합니다. 실제로 우려 사항이며이 솔루션은 해당 사용 사례에 적합하지 않습니다. 당신은 내 관점을 열었습니다. 네 말이 맞아 감사합니다
alexandre1985

4

다음 코드를 시도하십시오.

if [ "$(id -u)" != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi

또는

if [ `id -u` != "0" ]; then
    echo "Sorry, you are not root."
    exit 1
fi


2

id -u 보다 훨씬 낫다 whoami안드로이드와 같은 일부 시스템은 루트라는 단어를 제공하지 않을 수 있기 때문에 .

예:

# whoami
whoami
whoami: unknown uid 0

0
#!/bin/bash

# GNU bash, version 4.3.46
# Determine if the user executing this script is the root user or not

# Display the UID
echo "Your UID is ${UID}"

if [ "${UID}" -eq 0 ]
then
    echo "You are root"
else
    echo "You are not root user"
fi

편집자 주 : 이중 괄호가 필요하지 않은 경우 코드 이식성을 위해 단일 괄호를 사용하십시오.


3
이미 몇 가지 답변이있는 5 살짜리 질문에 대한 대체 답변을 제공 한 이유를 설명하지 않았습니다.
Styphon

0

루트인지 확인하고 그렇지 않은 경우 종료하십시오.

if ((EUID != 0)); then
    echo "Root or Sudo  Required for script ( $(basename $0) )"
    exit
fi

또는이 예에서는 루트 위치에 디렉토리를 작성한 다음 권한이 상승 된 후에 시도하십시오.

당신이 뿌리이고 가능한 경우 상승하지 않는지 확인하십시오.

# Fails to create these dirs (needs sudo)
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)

if ((EUID != 0)); then
    echo "Granting root privileges for script ( $(basename $0) )"
    if [[ -t 1 ]]; then
        sudo "$0" "$@"
    else
        exec 1> output_file
        gksu "$0" "$@"
    fi
    exit
fi
echo "Root privileges granted..."
# Creates Dirs as it now has rights
mkdir /test-dir-$(basename $0)
rmdir /test-dir-$(basename $0)

-1

루트를 확인하십시오.

ROOT_UID=0   # Root has $UID 0.

if [ "$UID" -eq "$ROOT_UID" ]
then
  echo "You are root."
else
  echo "You are just an ordinary user."
fi

exit 0

루트에서 테스트 및 실행

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.