Como um script pode verificar se está sendo executado como root?

105

Estou escrevendo um script bash simples, mas preciso verificar se está sendo executado como root ou não. Sei que provavelmente existe uma maneira muito simples de fazer isso, mas não faço ideia de como.

Só para esclarecer:
Qual é uma maneira simples de escrever um script foo.sh , para que o comando seja ./foo.shexibido 0e o comando seja sudo ./foo.shexibido 1?

Malabarba
fonte

Respostas:

151
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 
   exit 1
fi
aneeshep
fonte
7
Estou aceitando essa causa (após alguns testes), usando a variável de sistema EUID, que resultou ser (aproximadamente 100 vezes) mais rápida do que executar um comando (id -u), mas todas as respostas funcionaram muito bem.
Malabarba
18
Além disso, $UIDe $EUIDsão bashisms. Os shells meramente compatíveis com POSIX não têm essas variáveis ​​e você precisa usá-los id(1).
David Foerster
3
em um script bash, você pode usar if ((EUID)); then, consulte o comentário de @ geirha
jfs
7
@ Andrew: Variáveis ​​são substituídas antes de serem passadas para sudo. Se você executar sudo sh -c 'echo $EUID', verá os resultados esperados.
M. Dudley
6
@ Andrew - Eu sei que estou muito atrasado aqui, mas para a posteridade: $EUIDé um Bashism (como mencionado acima por @DavidFoerster), e seu /bin/shprovavelmente é um link para /bin/dash, não /bin/bash. sudo bash -c 'echo $EUID'produzirá o resultado esperado.
Adrian Günter
118

Um usuário root não precisa ser nomeado "root". whoamiretorna o primeiro nome de usuário com o ID do usuário 0. $USERcontém o nome do usuário conectado, que pode ter um ID de usuário 0, mas um nome diferente.

O único programa confiável para verificar se a conta está logada como root ou não:

id -u

Eu uso -upara o ID do usuário efetivo , não -rpara o ID do usuário real . As permissões são determinadas pelo ID do usuário efetivo , não o real .

Testes

/etc/passwdcontém os seguintes nomes de usuário com o ID do usuário 0na ordem especificada:

rootx
root2

Conectado como root2, fornece os próximos resultados:

  • whoami: rootx
  • echo $USER: root2(isso retorna uma string vazia se o programa foi iniciado em um ambiente vazio, por exemplo env -i sh -c 'echo $USER')
  • id -u: 0 Como você pode ver, os outros programas falharam nessa verificação, somente foram id -uaprovados.

O script atualizado ficaria assim:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   echo "I am not root!"
   exit 1
fi
Lekensteyn
fonte
5
Você não precisa id -udo bash askubuntu.com/questions/30148/…
jfs
5
Eu sempre tento permanecer o mais compatível possível com POSIX, usando sh( dash) como intérprete em vez de bash. Mas bom tiro, salva outra bifurcação :)
Lekensteyn
Depois de ficar frio por um tempo, voltei e dei uma olhada. O método de Lekensteyn realmente parece ser melhor. Sua resposta agora é a nova resposta aceita. +1 para você, Lekensteyn, esp. para obter aquele duro-à-obter crachá fora desta questão;)
Thomas Ward
Obrigado por aguardar tanto tempo por aceitar minha pergunta: A DI recebeu um distintivo populista de ouro e uma de bronze. Resposta agradável por esta resposta :) Gostaria de saber como essa pergunta chegou a tão populares 345 visualizações em um dia!
Lekensteyn
3
Eu já vi versões mais curtas [ -w / ]. A ideia permanece a mesma. Nota: em certos chroots, [ -w /etc/shadow ]falhará porque /etc/shadowé inexistente; portanto, a abordagem com /é preferida. Uma maneira melhor seria verificar a necessidade real de permissões de root. Se o script precisar gravar /etc/someconfig, verifique se esse arquivo é gravável OU se o arquivo não existe e /etcé gravável.
Lekensteyn
30

Como o @Lekensteyn disse, você deve usar um ID de usuário eficaz. Você não precisa ligar id -uno bash:

#!/bin/bash

if [[ $EUID -ne 0 ]]; then
   echo "You must be root to do this." 1>&2
   exit 100
fi

A sugestão de @ geirha dos comentários usa avaliação aritmética:

#!/bin/bash

if (( EUID != 0 )); then
   echo "You must be root to do this." 1>&2
   exit 100
fi
jfs
fonte
7
Em um geral deve usar ((..))para os números de teste, e [[..]]para testar cordas e arquivos, assim que eu faria if (( EUID != 0 )); thenem vez disso, ou apenasif ((EUID)); then
geirha
@ geirha: Adicionei sua sugestão.
jfs
2
EUIDdeve se tornar $EUID. Em vez de usar (( $EUID != 0 )), use [ $EUID != 0 ]. Também funcionará dash.
Lekensteyn
2
@Lekensteyn: EUIDfunciona muito bem. A pergunta está marcada como bashnão dash. O comando env -i sh -c '[ $EUID != 0 ]'falha, mas env -i bash -c '(( EUID != 0 ))'funciona. btw, dashnão funciona para alguns caracteres não-ascii no Ubuntu stackoverflow.com/questions/5160125/… É 2011 e há pessoas que usam outros idiomas.
jfs
Depois de olhar para trás, enquanto estou terrivelmente entediado e testando, vou usar esse método, conforme listado aqui, com as $EUIDcoisas deste ponto em diante. Alterei a resposta aceita como resultado.
Thomas Ward
20

Você pode fazer isso usando o whoamicomando, que retorna o usuário atual:

#!/bin/bash

if [ `whoami` != 'root' ]
  then
    echo "You must be root to do this."
    exit
fi

...

A execução do procedimento acima será impresso You must be root to do this.se o usuário atual não estiver root.


Nota: uma alternativa em alguns casos é simplesmente verificar a $USERvariável:

if [ $USER != 'root' ]
Nathan Osman
fonte
Vou dar uma olhada no código, ver se ele não faz o script falhar ou algo assim. Se funcionar, eu vou aceitar a sua resposta :)
Thomas Ward
4
@ George Edison: Eu recomendo o uso $USER, especialmente dessa maneira. $USERé definido pelo shell de login, não é necessário propagar para o programa ( env -i sh -c 'echo $USER'). Dessa forma, $USERestá vazio e ocorre um erro de sintaxe.
Lekensteyn
11
@Lekensteyn Não só é $USERdefinido pelo shell, mas também é algo fácil de falsificar. Whoami retornará o usuário real.
Paul de Vrieze
2
@PauldeVrieze Qual o sentido de enganar esse cheque?
htorque
11
@andrewsomething: $USERé interpretado pelo seu shell, seu exemplo deve ser sudo sh -c 'echo $USER'para ser significativo. @George: faz a suposição errada de que whoamisempre retornará rootpara UID 0.
Sam Hocevar
11

Levando em consideração a eficiência, você pode testar primeiro a EUIDvariável de ambiente e, se não existir, chamar o idcomando padrão :

if ((${EUID:-0} || "$(id -u)")); then
  echo You are not root.
else
  echo Hello, root.
fi

Dessa forma, devido ao atalho OU , você evita chamar um comando do sistema, priorizando a consulta de uma variável na memória.

Reutilização de código:

function amIRoot() {
  ! ((${EUID:-0} || "$(id -u)"))
}
Luchostein
fonte
Receio que você não tenha comparado, bem, eu tenho e isso leva o mesmo tempo que id -u. Veja o script do banco, juntamente com os resultados abaixo, aqui: pastebin.com/srC3LWQy
LinuxSecurityFreak
9
#!/bin/bash
[[ $(id -u) != 0 ]] 
echo $?
João Pinto
fonte
2

Uma maneira simples de tornar o script apenas executável pela raiz é iniciar o script com a linha:
#!/bin/su root

alexandre1985
fonte
11
Não faça isso. Ele tenta efetuar login diretamente como root, enquanto o sudo pode ser necessário em muitos sistemas porque o primeiro é proibido. Além disso, o shebang tem como objetivo garantir que seu script seja executado naquele para o qual foi projetado, enquanto seu método fará com que o script seja executado no shell padrão do root, o que não pode ser previsto se o script for executado por alguém que não seja o autor. Portanto, usar o shebang para elevar os privilégios de um script interromperá severamente sua portabilidade e resultará em erros em muitos sistemas. (su: falha na autenticação)
StarCrashr 20/09/18
1
#!/bin/bash
uid=`id -u`
if [ "$uid" == "0" ]
then
    echo 1
else
    echo 0
fi
Delan Azabani
fonte
1

Esse trecho:

  • Confira em diferentes sessões
  • sugerir usar sudo !!
  • e retornar um erro
if ["$ (whoami & 2> / dev / null)"! = "root"] && ["$ (id-un & 2> / dev / null)"! = "root"]
      então
      eco "Você deve ser root para executar este script!"
      eco "use 'sudo !!'"
      saída 1
fi
rubo77
fonte
1

Esta resposta é apenas para salvar uma ideia, pode ser útil para alguns de vocês. Se você precisar de um script que seja executado na GUI da área de trabalho e exija privilégios de root, tente desta maneira:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   gksudo -w $0 $@
   exit
fi

#here go superuser commands, e.g. (switch intel cpu into powersave mode):
echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo
cpupower frequency-set -g powersave

Dessa forma, você terá uma boa janela de diálogo solicitando a senha do usuário root. Assim como no sudo da linha de comando.

A gksudopodem não estar disponíveis em seu sistema, em seguida, instalá-lo com sudo apt-get install gksu.

gertas
fonte
0

Esse código funciona tanto no Bash quanto no Bourne sh de ações (testado no FreeBSD) que não define o EUID. Se existir EUID, seu valor será retornado, caso contrário, o comando 'id' será executado. É um pouco mais curto que o exemplo "ou" acima, pois usa um shell ": -" embutido.

Raiz em sh:

# echo $EUID

# euid=${EUID:-`id -u`}
# echo $euid
0

In bash:
[chaapala@tenfwd2 ese]$ euid=${EUID:-`id -u`}
[chaapala@tenfwd2 ese]$ echo $euid
10260
Clayton Haapala
fonte