Como interromper a execução de um script se ele não for root (e ecoar "Não está executando como root! Saindo ...")

17

Aqui está a minha fonte:

#!/bin/bash

echo "Running script to free general cached memory!"
echo "";
echo "Script must be run as root!";
echo "";
echo "Clearing swap!";
swapoff -a && swapon -a;
echo "";
echo "Clear inodes and page file!";
echo 1 > /proc/sys/vm/drop_caches;
echo "";

Ele limpa caches e outras coisas, e faz eco que ele precisa ser executado como root no terminal. Basicamente, só quero que o script pare de ser executado se detectar que não está sendo executado como root.

Exemplo:

"Running script to free general cached memory!"
"Warning: script must be run as root or with elevated privileges!"
"Error: script not running as root or with sudo! Exiting..."

Se executado com privilégios elevados, é executado normalmente. Alguma ideia? Obrigado!

M. Knepper
fonte
Possível duplicata Como raiz impedem de executar um script
Muru
2
@ muru, exceto que outra pergunta é oposta: falha no script se estiver sendo executado como root.
Stéphane Chazelas
3
@ StéphaneChazelas ah, meu mal. Retirado
muru
Uma alternativa é a de limitar a quantidade de trabalho realizado como rootpor prefixac prefixo todos os comandos que devem ser executados como rootcom sudo.
Reinierpost

Respostas:

46
#!/bin/sh

if [ "$(id -u)" -ne 0 ]; then
        echo 'This script must be run by root' >&2
        exit 1
fi

cat <<HEADER
Host:          $(hostname)
Time at start: $(date)

Running cache maintenance...
HEADER

swapoff -a && swapon -a
echo 1 >/proc/sys/vm/drop_caches

cat <<FOOTER
Cache maintenance done.
Time at end:   $(date)
FOOTER

O usuário root possui o UID 0 (independentemente do nome da conta "root"). Se o UID efetivo retornado por id -unão for zero, o usuário não estará executando o script com privilégios de root. Use id -rupara testar o ID real (o UID do usuário que está chamando o script).

Não use $EUIDno script, pois isso pode ser modificado por um usuário não privilegiado:

$ bash -c 'echo $EUID'
1000

$ EUID=0 bash -c 'echo $EUID'
0

Se um usuário fizer isso, obviamente isso não levará à escalada de privilégios, mas poderá fazer com que os comandos no script não consigam fazer o que deveriam fazer e os arquivos sejam criados com o proprietário errado etc.

Kusalananda
fonte
1
Nota: no Solaris 5.10, /bin/id -u/bin/id: illegal option -- u Usage: id [-ap] [user]
jrw32982 suporta Monica
1
@ jrw32982 Você deve ter /usr/xpg4/binno início $PATHpara ter acesso aos utilitários POSIX no Solaris.
Kusalananda
1
O ponto é que a -uopção de idnão é universal e, portanto, essa solução é universal somente com a ressalva de que uma versão POSIX iddeve ocorrer primeiro no seu CAMINHO.
Jrw32982 suporta Monica
1
@ jrw32982 Para o seu script pegar os utilitários corretos do POSIX no Solaris, modifique $PATHna parte superior do script, como /usr/xpg4/binantes /bin. Se você insistir em não usar o POSIX id, obviamente terá que criar uma solução mais portátil.
Kusalananda
1
@ Harry Sim, para que o script possa usar PATH=$( getconf PATH )ou definir outro caminho padrão explícito ou usar um caminho explícito para chamar id.
Kusalananda
19

Acho que o que você deseja é verificar se você possui privilégios de superusuário, ou seja, se seu ID de usuário efetivo é 0.

zshe bashdisponibilize isso na $EUIDvariável, para que você possa:

if ((EUID != 0)); then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Com qualquer shells do tipo POSIX, você pode usar o idcomando padrão:

if [ "$(id -u)" -ne 0 ]; then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Note-se que todos id -unou whoamiou a $USERNAMEvariável zshirá obter o primeiro nome de usuário para o uid. Em sistemas que possuem outros usuários com o ID 0, isso pode não ser o rootmesmo se o processo for descendente de um que foi autenticado como root.

$USERseria normalmente dar-lhe o usuário que autenticou, mas contando com ele é bastante frágil. Não é definido pelo shell, mas geralmente é definido pelo comando de autenticação (como login, su(nos sistemas GNU / Linux, não necessariamente em outros)) sudo, sshd(pelo menos o do openssh) ...). Nem sempre é assim (alterar o uid não define automaticamente essa variável, isso deve ser feito explicitamente pelo aplicativo que altera o uid) e também pode ter sido modificado por algum outro processo na ancestralidade do shell. $LOGNAME, com a mesma ressalva é mais confiável, conforme especificado pelo POSIX (originalmente do FIPS 151-2)

Stéphane Chazelas
fonte
12

Você pode usar $USERou whoamipara verificar o usuário atual.

if [[ "$USER" != "root" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

if [[ $(whoami) != "root" ]]; then
    echo "Warning: script must be run as root or with elevated privileges!"
    exit 1
fi

if [[ $(id -u) != "0" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi
Jesse_b
fonte
1
NP. Eu sugiro literalmente apenas ler o manual do bash [ gnu.org/software/bash/manual/bashref.html] . Na verdade, é uma preparação surpreendentemente fácil. Para esta resposta, em particular, sugiro referência: 3.2.4.2 Conditional Constructs 3.5.4 Command Substitution
Jesse_b
9
O comando id -ucom ou sem uma -nopção é uma alternativa ao uso de whoami. Sem um -n e comparar com zero é uma melhor correspondência para o teste que o kernel está realmente fazendo. Tudo o que o kernel se importa é o ID, não o nome do arquivo de senhas.
icarus 31/08
6
Eu acredito que usar $(id -u)é melhor. Em alguns casos (maliciosos), $USERpode estar errado.
Basile Starynkevitch
1
Para aqueles que estão interessados ​​no link fornecido por @Jesse_b: há um erro de digitação. Deve ser gnu.org/software/bash/manual/bashref.html
Kryten
1
Alguns sistemas não usam "root" como o nome da conta privilegiada com uid 0. QNAP vem à mente como um. Portanto, você deve verificar apenas o uid 0, e não o nome da conta raiz.
roaima 9/09/17
10

O que você realmente deseja é determinar se você tem acesso para executar essas operações. É uma prática recomendada verificar se você está ou não raiz em vez disso.

Se o sistema foi configurado para permitir que um usuário não root modifique o swap e descarte o cache da página, por que esse usuário não deve executar seu script?

Em vez disso, você pode simplesmente tentar a operação e sair com uma mensagem útil se ela falhar:

if ! ( swapoff -a && swapon -a )
then
  echo "Failed to clear swap (rerun as root?)" >&2
  exit 1
fi

if ! echo 1 > /proc/sys/vm/drop_caches
then 
  echo "Failed to free page cache (rerun as root?)" >&2
  exit 1
fi
aquele outro cara
fonte
Um usuário não root desativando a troca?
Kusalananda
2
Sim. Você pode configurar isso com o SELinux. Da mesma forma, você pode desativar um processo raiz.
esse outro cara
1
Talvez você não queira exitdepois que algo falhar, caso o usuário queira fazer o máximo que puder com seus privilégios atuais. (. Mas para um sistema típico onde tudo isso exige raiz, saindo seria mais útil / menos ruidoso)
Peter Cordes
2
Eu não chegaria ao ponto de dizer que é "má prática" verificar se você é ou não raiz. Especialmente se é exatamente isso que você quer saber. Entendo que é melhor verificar se você possui permissões suficientes para fazer o que deseja.
Erik Bennett