Como verificar se está sendo executado como root em um script bash

275

Estou escrevendo um script que requer permissões de nível raiz e quero fazê-lo para que, se o script não for executado como root, ele simplesmente ecoará "Por favor, execute como root". e sai.

Aqui estão alguns pseudocódigo para o que estou procurando:

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

  else (do stuff)
fi

exit

Como eu poderia (melhor e com segurança) conseguir isso? Obrigado!

Ah, só para esclarecer: a parte (do stuff) envolveria a execução de comandos que, por si só, exigem raiz. Portanto, executá-lo como um usuário normal apresentaria um erro. Isso serve apenas para executar corretamente um script que requer comandos root, sem usar o sudo dentro do script, estou apenas procurando por algum açúcar sintático.

Nathan
fonte
8
(1) faça com que ele não seja executável por qualquer outra coisa, em seguida, o root (2) organize outras permissões também. (3) id -uretorne 0para o root.
precisa saber é o seguinte

Respostas:

404

A variável de ambiente $ EUID mantém o UID do usuário atual. O UID da raiz é 0. Use algo como isto em seu script:

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

Nota: Se você conseguir 2: [: Illegal number:verificar se está #!/bin/shno topo e altere para #!/bin/bash.

ptierno
fonte
Parece que as boas permissões e tendo esta é uma dupla camada de segurança
Kolob Canyon
25
Eu acho que é melhor comparar string com string, número com número. usando colchetes duplos, você pode usar> diretamente sem aspas [[$ EUID> 0]]
Sergio Abreu
7
Recebi um 2: [: Illegal number:aviso até mudar para a versão do Sergio.
Alexeydemin
1
@ thekiwi5000 O ponto e vírgula é necessário apenas se o thené na mesma linha como a condição ...
ptierno
1
@StephenAngelico Sudo deve funcionar. Se você estiver testando usando $ sudo echo $ EUID; esse é um teste ruim e falhará porque $ EUID é expandido antes que o comando seja passado para o sudo. Tente colocar echo $ EUID em um script de teste e execute-o com o sudo.
user1169420
79

Em um script bash, você tem várias maneiras de verificar se o usuário em execução é root.

Como aviso , não verifique se um usuário é root usando o rootnome de usuário. Nada garante que o usuário com o ID 0 seja chamadoroot . É uma convenção muito forte que é amplamente seguida, mas qualquer um poderia renomear o superusuário com outro nome.

Eu acho que a melhor maneira de usar o bash é usar $EUID, na página de manual:

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

Essa é uma maneira melhor do $UIDque a que poderia ser alterada e não refletir o usuário real executando o script.

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

Uma maneira de abordar esse tipo de problema é injetando sudomeus comandos quando não é executado como root. Aqui está um exemplo:

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

Dessa maneira, meu comando é executado pela raiz ao usar o superusuário ou sudopor um usuário comum.

Se seu script sempre deve ser executado pela raiz, simplesmente defina os direitos adequadamente ( 0500).

sberder
fonte
Se a pessoa que está tentando executar o script não tiver privilégios de sudo, isso causará o erro e o comando não será executado? Só quero ter certeza, eu entendi corretamente.
Caperneoignis
1
Não tenho certeza se esta resposta está 100% completamente correta. No RHEL7.2 usando o Bash 4.2.46 ... se eu printf $EUIDcom ou sem sudo, recebo meu próprio UID de volta. Se eu uso id -u, recebo meu UID e, quando o invoco com sudo, recebo 0 de volta. Fiz algo de errado?
precisa saber é o seguinte
4
@ 0xSheepdog, é possível que no bash cli, a expansão da variável $ EUID seja resolvida primeiro e depois o sudo mude de usuário. Portanto, você obteria esse comportamento, mas nos scripts tudo ainda funcionaria bem.
Alexander Bird
@AlexanderBird Bom ponto, obrigado! Eu não fiz nenhum teste real, apenas relatei minha experiência.
precisa saber é o seguinte
3
Use um "herestring" para o seu teste para impedir a expansão do shell local da variável. Compare sudo bash <<<'echo $EUID'com bash <<<'echo $EUID'. Mais sobre a herestroc como herestroc em tldp.org/LDP/abs/html/x17837.html
Bruno Bronosky
75

Algumas respostas foram dadas, mas parece que o melhor método é usar é:

  • id -u
  • Se executado como root, retornará um ID 0.

Isso parece ser mais confiável que os outros métodos e parece que ele retorna um ID igual a 0, mesmo que o script seja executado sudo.

Nathan
fonte
1
Ótimo, esta é a melhor resposta
Dan Ortega
59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

ou

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

:)

Dale_Reagan
fonte
Você pode considerar integrar a resposta de Jeremy J Starcher a esta parte, no final, é sempre a mesma coisa ...
reallynice
Eu sei que no terminal, quando eu esqueço de prefixar algo sudo, posso simplesmente digitar sudo !!e ele faz o trabalho para mim, em vez de pressionar a seta PARA CIMA, indo para o início da linha e adicionando sudo à mão. Não tenho certeza se isso é uma coisa BASH ou uma coisa SUDO ou outra, mas funciona na maioria das vezes.
0xSheepdog
@ 0xSheepdog: É uma coisa do Bash (e é uma característica de alguns outros shells, como o csh, onde IIRC se originou).
Pausado até novo aviso.
No geral, eu removia a parte de trás como um todo e reescrevia a linha ok if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. Felicidades.
LinuxSecurityFreak 20/01
29

Como @wrikken mencionado em seus comentários, id -ué uma verificação muito melhor para o root.

Além disso, com o uso adequado de sudo, você pode fazer com que o script verifique e veja se está sendo executado como root. Caso contrário, faça com que ele se lembre via sudoe execute com permissões de root.

Dependendo do que o script faz, outra opção pode ser configurar uma sudoentrada para quaisquer comandos especializados que o script possa precisar.

Jeremy J Starcher
fonte
Existe uma maneira elegante de fazer com que um programa se lembre? Talvez haja alguma variável bash com o caminho absoluto para o programa?
Nathan
1
No momento, não estou perto de um prompt do BASH para testar, mas tenho $0o nome do script em execução. Existem alguns exemplos aqui que podem ajudá-lo.
precisa saber é o seguinte
25

Há uma verificação simples para um usuário ser root.

A [[ stuff ]]sintaxe é a maneira padrão de executar uma verificação no bash.

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

Isso também pressupõe que você deseja sair com 1 se falhar. A errorfunção é um talento que define o texto de saída para vermelho (não necessário, mas bastante elegante, se você me perguntar).

Slater Victoroff
fonte
O que é esse errorcomando? Meu sistema parece não ter. . .
Ruakh 13/08
Oh, isso é apenas uma coisa pequena. Não importa muito, mas eu vou anexar.
Slater Victoroff
4
Isso é bem legal! Se eu puder sugerir algumas melhorias: (1) mova a nova linha para o final; (2) gravar no erro padrão em vez da saída padrão; (3) defina a cor apenas se o erro padrão for um terminal (em vez de arriscar gravar caracteres de escape em arquivos de log lessou outros enfeites); e (4) definir uma cor de fundo, para que o texto seja legível, independentemente da cor de fundo do terminal do usuário. Então, algo como function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (Emenda como desejado.)
ruach
3
Isso não deveria ser "-ne" em vez de "-eq"?
Carlos Rendon
2
O código de @CarlosRendon Slater é impedir que algo seja executado como root. (Este é o oposto o que o OP estava pedindo, mas o método de verificação seria o mesmo.)
Joshua Taylor
11

Maneira muito simples, basta colocar:

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

O benefício de usar isso em vez de idé que você pode verificar se um determinado usuário não raiz também está executando o comando; por exemplo.

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
Matthew Trotter
fonte
se você testar o usuário com uma sequência "root", não está permitindo executar alguém chamado "root"?
pcarvalho 21/10
Você esqueceu o ';' após o if #
18715 Triskeldeian
1
@ Peteroak quem mais seria nomeado root diferente de root?
Ptierno 5/05
3
+1 para responder à pergunta sobre, em whoamivez de usar id; o whoamicomando também pode ser usado para procurar outros usuários que não sejam root, por nome.
Jez
10

0- Leia a documentação oficial do GNU Linux, existem várias maneiras de fazê-lo corretamente.

1- certifique-se de colocar a assinatura do shell para evitar erros de interpretação:

 #!/bin/bash

2- este é o meu roteiro

#!/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
Sergio Abreu
fonte
10

Nesta resposta, fique claro, presumo que o leitor é capaz de ler bashe scripts shell POSIX como dash.

Acredito que não há muito o que explicar aqui, já que as respostas altamente votadas fazem um bom trabalho ao explicar grande parte delas.

No entanto, se houver algo a explicar mais, não hesite em comentar, farei o meu melhor preenchendo as lacunas.


Polivalente otimizado (não apenas bashSolução ) para desempenho e confiabilidade; todas as conchas compatíveis

Nova solução:

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

Referência (salvar em arquivo 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: [email protected]                      ##
##                             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

Solução original:

#!/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

^^^ A solução riscada foi comprovada para não acelerar as coisas, mas existe há muito tempo, então vou mantê-la aqui pelo tempo que achar necessário.


Explicação

Como é muito mais rápido ler a variável $EUIDpadrão bash, o número de ID do usuário efetivo, do que executar o id -ucomando para POSIX - apenas encontrar o ID do usuário, esta solução combina ambos em uma função bem compactada. Se, e somente se, $EUIDpor algum motivo não estiver disponível, o id -ucomando será executado, garantindo que obtemos o valor de retorno adequado, independentemente das circunstâncias .


Por que postei esta solução após tantos anos que o OP perguntou

Bem, se eu entendi corretamente, parece haver um pedaço de código ausente acima.

Veja bem, existem muitas variáveis que precisam ser levadas em consideração, e uma delas é combinar desempenho e confiabilidade .


Solução portátil POSIX + Exemplo de uso da função acima

#!/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

Conclusão

Por mais que você não goste, o ambiente Unix / Linux se diversificou bastante. Ou seja, existem pessoas que gostam bashtanto, que nem pensam em portabilidade ( cartuchos POSIX ). Outros como eu preferem as conchas POSIX . Hoje em dia é uma questão de escolha e necessidades pessoais.

LinuxSecurityFreak
fonte
6

Se o script realmente requer acesso root, suas permissões de arquivo devem refletir isso. Ter um script raiz executável por usuários não raiz seria uma bandeira vermelha. Convido você a não controlar o acesso com um ifcheque.

chown root:root script.sh
chmod u=rwx,go=r script.sh
John Kugelman
fonte
4
Se alguém tiver suas permissões em ordem, isso funcionará muito bem, mas sinto que o uso excessivo da 777bomba torna essa verificação um pouco defeituosa para o tipo de usuário que cometeria o erro.
Slater Victoroff
7
Isso pressupõe que o usuário esteja executando um script executável. Se o usuário só chama bash /path/to/scriptele ainda pode ser executado mesmo queo=r
ptierno
5

Uma maneira simples de tornar o script apenas executável pela raiz é iniciar o script com a linha:

#!/bin/su root

alexandre1985
fonte
1
Estou curioso para saber por que essa resposta não foi votada mais? Parece o mais simples e limpo. Existem desvantagens aqui?
Bassinator 10/09
@Bassinator Eu acredito que algumas pessoas dizem que ele não funcionará em certos nix's, mas tem funcionado perfeitamente no meu Linux até agora. Tente! Talvez esta resposta tenha chegado atrasada à corrida, mas estou tentando adicionar conhecimentos simples para a comunidade (em vez de dar respostas semelhantes, como a maioria neste tópico: /) Vote nisso se tiver sorte em ler isso e ele trabalha em sua máquina
alexandre1985
@TamusJRoyce Se o objetivo é verificar se você está executando como raiz e não forçar o script a ser executado apenas como raiz, por que, então, em todas as respostas, após a verificação de se executar como raiz, eles criam o script exit? E essas respostas ainda estão sendo votadas? Acho que as pessoas implicitamente não querem que o script seja executado como root. Então, eu estou seguindo essa maneira de pensar, com uma resposta mais simples. Mas sim, você também pode aprender com o mais detalhado respostas acima
alexandre1985
@ alexandre1985 Exatamente. Cenário: Se estiver executando como root, talvez você queira que um script seja o padrão para instalar o programa globalmente quando perguntar como você deseja instalá-lo. Caso contrário, o padrão é definido para instalá-lo localmente. Em vez de pressionar Enter, o usuário pode optar por instalá-lo global ou local. Mas se eles gostarem do padrão, poderão pressionar enter. E eles não serão solicitados com uma senha. Seu shebang nunca "verificará" se você é root (por título). Mas ainda acho que essa resposta é útil.
TamusJRoyce 25/05/19
@TamusJRoyce faz totalmente sentido o seu comentário. De fato, é uma preocupação e esta solução não é para esse caso de uso. Você abriu minhas perspectivas. Você está certo. Obrigado
alexandre1985
4

tente o seguinte código:

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

OU

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

Tanto quanto eu sei a maneira correta de verificar é:

if [ $(id -u) = "0" ]; then
    echo "You are root"
else
    echo "You are NOT root"
fi

Consulte a seção "Teste de raiz" aqui:

http://linuxcommand.org/lc3_wss0080.php

WebBrother
fonte
1
substitua = "0"por-eq 0
LinuxSecurityFreak
1
@LinuxSecurityFreak, vou substituí-lo se você explicar por que devo fazê-lo.
WebBrother 20/01
2

id -ué muito melhor do que whoami, já que alguns sistemas como o Android podem não fornecer a palavra raiz.

Exemplo:

# whoami
whoami
whoami: unknown uid 0
Smeterlink
fonte
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

Nota do editor: Se você não precisar de colchetes duplos, use um para a portabilidade do código.

Pramod Kharade
fonte
3
Você não explicou por que forneceu uma resposta alternativa a uma pergunta de 5 anos que já possui várias respostas.
Styphon
0

Verifique se você é root e saia se não for:

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

Ou, neste exemplo, tente criar um diretório no local raiz e tente depois que os direitos forem elevados.

Verifique se você é root e, caso contrário, eleve, se possível:

# 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)
Mike Q
fonte
-1

Verifique a raiz:

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

Testado e executando na raiz.

fvillalba89
fonte