O que há de errado com este script?

2

Então, peguei este script neste guia: www.tldp.org/LDP/abs/abs-guide.pdf

LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=86
E_NOTROOT=87

if [ "$UID" != "$ROOT_UID" ]
then
echo "Must be root to run this script."
exit $E_NOTROOT
fi

if [ -n "" ]
then
lines=
else
lines=$LINES
fi

cd $LOG_DIR

if [ 'pwd' != "$LOG_DIR" ]
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi

Agora eu fiz sudo su no terminal e ecoei $ UID, o que me deu 0. Isso significa que minha condição se torna falsa, mas ainda estou recebendo "Deve ser root para executar este script." enquanto executa este script.

Também no script original, esta condição foi dada como

if [ "$UID" -ne "$ROOT_UID" ]

mas eu estava recebendo erro de número ilegal porque aparentemente -ne é usado apenas para string, então eu mudei para! =.

    
por rishiag 22.08.2014 / 20:02

2 respostas

3

Em vez de executá-lo com

sh script.sh

execute com

bash script.sh

(ou adicione #!/bin/bash como a primeira linha para definir o interpretador).

O shell sh no Ubuntu não é não bash , mas um shell separado chamado dash . dash não possui tantos recursos quanto bash , o que o torna mais eficiente, mas esses recursos ausentes às vezes interrompem os scripts destinados a bash . Um desses recursos é a variável $UID , que não está definida em dash .

Isso significa que quando o script é executado em dash , a comparação se tornará ["" != "0"] , que é avaliada como verdadeira, não importa qual usuário esteja executando. No entanto, se for executado em bash com permissões de root, as sequências serão iguais e o script funcionará.

    
por McLovin 22.08.2014 / 20:37
1

Como McLovin diz , a variável UID (e EUID ) readonly, definida automaticamente, é um recurso especial de bash (e alguns outros shells). Não é padrão para shells estilo Bourne e sh não pode ser assumido para definir essas variáveis. Em particular, sh no Ubuntu é (atualmente, por padrão) dash , que não os define.

Você tem duas opções:

  1. Faz com que seu script seja executado por bash em vez de sh .
  2. Altere seu script para torná-lo mais portátil e não exija bash .

Executando seu script com bash

Você não nos disse o nome do seu roteiro (o que está bem). Vou chamá-lo cleanup , pois esse é o nome do script semelhante no guia do qual você está trabalhando.

Note, em particular, que eu não estou chamando algo como cleanup.sh . Isso é porque eu não recomendo que você nomeá-lo com um sufixo .sh :

  • Um sufixo .sh sugere que seja compatível com sh !
  • A maioria dos scripts não recebe um sufixo, e ter um sufixo .sh ou .bash pode até ser interpretado como sugerindo que seu arquivo seja uma "biblioteca" em vez de um script de "nível superior". Ou seja, ele fornece código para ser originado por outros scripts (por exemplo, com o . builtin) em vez de ser executado diretamente.

No entanto, incluir um sufixo .sh não afetará o comportamento técnico de seu script de nenhuma maneira. Não há vantagem técnica ou desvantagem associada a isso.

Adicione uma linha de hashbang como a primeira linha do seu script: #!/bin/bash

Torne seu script executável com chmod +x cleanup .

Agora você pode executar seu script executando o comando:

  • ./cleanup , quando estiver no diretório atual. (Especialmente quando o script para educação, exploração, teste, diversão ou outro uso limitado ou de uso único, esta é talvez a maneira mais comum.)

  • /path/to/cleanup , em geral. Se a primeira palavra de um comando contiver um / , ele será interpretado como caminho para um arquivo executável. (Essa é a razão para a sintaxe ./ acima, pois . significa o diretório atual.)

    Por primeira palavra , quero dizer o comando até, mas não incluindo, o primeiro espaço sem escape ou tab:
    foo-bar/baz é a primeira palavra de foo-bar/baz qux , enquanto spam\ ham é a primeira palavra de spam\ ham eggs porque o espaço antes de ham é escapado com uma barra invertida.

  • cleanup , se estiver em um diretório no seu PATH (e nenhum diretório listado tiver um executável com o mesmo nome e não for substituído por um construção do shell , função ou alias ).

Independentemente de o script cleanup ter ou não uma linha #!... hashbang ou o que a linha diz:

  • sh cleanup continuará (tentando) executá-lo com sh como o interpretador.
  • bash cleanup continuará (tentando) executá-lo com bash como o interpretador.

Isso ocorre porque, nesses casos, você está realmente executando o interpretador ( sh ou bash ) e passando o nome do script para o interpretador, para ser executado. Muitos programas aceitam nomes de arquivos para abrir na linha de comando, e shells como sh e bash seguem essa convenção.

Tornando seu script portátil

Se você quiser tornar seu script portátil, a maneira mais simples é não usar $UID , e em vez disso, usar algum recurso disponível para todos os shells ao estilo Bourne.

Em geral, não há recurso de shell interno para determinar o ID do usuário. Mas você pode usar id . Este é um programa externo em vez de um shell embutido, mas como cat e ls , é razoável esperar que esteja presente.

id em si gera muitas informações, mas id -u fornece apenas o ID do usuário efetivo.

Então, em vez de if [ "$UID" != "$ROOT_UID" ] , você pode usar:

if [ "$(id -u)" != "$ROOT_UID" ]

Tecnicamente , isso não é equivalente. $UID in bash fornece o ID do usuário real e id -u corresponde a bash ' $EUID '. Se você realmente quiser o UID e não o EUID, use id -ru .

    
por Eliah Kagan 23.08.2014 / 06:56