Bir komut dosyası root olarak çalıştırılıp çalıştırılmadığını nasıl kontrol edebilir?


104

Basit bir bash betiği yazıyorum, ancak root olarak çalıştırılıp çalıştırılmadığını kontrol etmem gerekiyor. Bunu yapmanın çok basit bir yolu olduğunu biliyorum ama nasıl yapacağımı bilemiyorum.

Daha açıkçası:
Bir komut dosyası yazmak için basit bir yolu nedir foo.sh , böylece komut ./foo.shçıkışları 0ve komut sudo ./foo.shçıkışları 1?

Yanıtlar:


148
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 
   exit 1
fi

7
EUID sistem değişkenini kullanarak (bazı testlerden sonra) bunun bir nedenini kabul ediyorum (yaklaşık 100 kat) bir komut çalıştırmadan (id -u) daha hızlı, ancak tüm cevaplar mükemmel sonuç verdi.
Malabarba

18
Ayrıca, $UIDve $EUIDtemel bilgilerdir. Yalnızca POSIX uyumlu mermilerde bu değişkenler yoktur ve id(1)bunun yerine kullanmanız gerekir .
David Foerster

3
bir bash betiğinde, kullanabilirsiniz if ((EUID)); then, @ geirha'nın yorumuna
jfs

7
@Andrew: Değişkenler iletilmeden önce değiştirilir sudo. Eğer sudo sh -c 'echo $EUID'koşarsanız, beklenen sonuçları göreceksiniz.
M. Dudley

6
@Andrew - Buraya çok geç kaldığımı biliyorum, ama gelecek için: $EUIDbir Bashizm (yukarıda @DavidFoerster tarafından bahsedildiği gibi) ve sizin /bin/shbüyük olasılıkla bir bağlantı /bin/dashdeğil /bin/bash. sudo bash -c 'echo $EUID'beklenen sonucu verecektir.
Adrian Günter

118

Bir kök kullanıcının "kök" olarak adlandırılması gerekmez. whoamikullanıcı kimliğiyle ilk kullanıcı adını döndürür 0. $USERKullanıcı kimliğine sahip 0, ancak farklı bir ada sahip olan, oturum açan kullanıcının adını içerir.

Hesabın root olarak giriş yapıp yapmadığını kontrol eden tek güvenilir program:

id -u

Kullandığım -uiçin etkili değil, kullanıcı kimliği -riçin gerçek kullanıcı kimliğine. İzinler edilir tespit tarafından etkin bir kullanıcı kimliği değil, gerçek bir.

Testler

/etc/passwd0verilen sırada kullanıcı kimliğine sahip aşağıdaki kullanıcı adlarını içerir :

rootx
root2

Olarak oturum açtığınızda root2, aşağıdaki sonuçları verir:

  • whoami: rootx
  • echo $USER: root2(program boş bir ortamda başlatılmışsa bu boş bir dize döndürür, örneğin env -i sh -c 'echo $USER')
  • id -u: 0 Gördüğünüz gibi, diğer programlar bu kontrolde başarısız oldu, yalnızca id -ugeçti.

Güncellenen komut dosyası şöyle görünür:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   echo "I am not root!"
   exit 1
fi

5
Buna gerek yok id -ubash içinde askubuntu.com/questions/30148/...
jfs

5
Her zaman mümkün olduğunca POSIX ile uyumlu kalmaya çalışıyorum, yerine tercüman olarak sh( dash) kullanıyorum bash. Ama iyi atış, başka bir çatal
korur

Bir süre soğuk kaldıktan sonra geri döndüm ve bir göz attım. Lekensteyn'in yöntemi gerçekten de daha iyi görünüyor. Cevabı şimdi yeni kabul edilmiş cevap. +1 sana, Lekensteyn, esp. bu sorudan elde edilmesi zor olan rozeti almak için;)
Thomas Ward

Sorumu kabul ettiğin için bu kadar beklediğin için teşekkür ederim: DI bir Altın Popülist rozeti ve bronz bir cevap aldı Bu cevabın güzel bir cevabı :) Bu sorunun bir günde nasıl popüler hale geldiğini merak ediyorum!
Lekensteyn

3
Daha kısa versiyonları gördüm [ -w / ]. Fikir aynı kalır. Not: Bazı kroketlerde, [ -w /etc/shadow ]başarısız olacaktır çünkü /etc/shadowmevcut değildir, bu nedenle yaklaşım /tercih edilir. Kök izinleri için gerçek ihtiyacı kontrol etmenin daha iyi bir yolu. Komut dosyasının yazması gerekiyorsa /etc/someconfig, sadece bu dosyanın yazılabilir olup olmadığını kontrol edin VEYA dosya mevcut değil ve /etcyazılabilir.
Lekensteyn

30

@Lekensteyn'in dediği gibi etkili bir kullanıcı kimliği kullanmalısınız. id -uBash aramanıza gerek yok :

#!/bin/bash

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

@ geirha'nın yorumlardan aldığı öneri aritmetik değerlendirmeyi kullanıyor:

#!/bin/bash

if (( EUID != 0 )); then
   echo "You must be root to do this." 1>&2
   exit 100
fi

7
Genel olarak bir kullanmalıdır ((..))ve test numaraları için [[..]]dizeleri ve dosyaları test etmek için, bu yüzden yapardım if (( EUID != 0 )); thenyerine, ya da sadeceif ((EUID)); then
geirha

@geirha: Önerinizi ekledim.
jfs

2
EUIDOlmalı $EUID. Kullanmak yerine (( $EUID != 0 ))kullanın [ $EUID != 0 ]. O da işe yarayacak dash.
Lekensteyn

2
@Lekensteyn: EUIDsadece iyi çalışıyor. Soru etiketli bashdeğil dash. Komut env -i sh -c '[ $EUID != 0 ]'başarısız, ancak env -i bash -c '(( EUID != 0 ))'çalışıyor. btw, dashUbuntu'da bazı asci olmayan karakterler için çalışmıyor stackoverflow.com/questions/5160125/… 2011 ve başka dilleri kullanan insanlar var.
jfs

Korkunç bir şekilde sıkılırken ve test ederken bu konuya tekrar baktıktan sonra, bu metodu burada listelenen $EUIDşekilde bu noktadan itibaren kullanacağım . Sonuç olarak kabul edilen cevabı değiştirdim.
Thomas Ward

20

whoamiGeçerli kullanıcıyı döndüren komutu kullanarak bunu başarabilirsiniz :

#!/bin/bash

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

...

You must be root to do this.Geçerli kullanıcı değilse yukarıdakilerin çalıştırılması yazdırılacaktır root.


Not: Bazı durumlarda alternatif, $USERdeğişkeni kontrol etmektir :

if [ $USER != 'root' ]

Koda bir göz atacağım, bakalım betiğin başarısız olmasına ya da bir şey yapamayacağını. İşe yararsa, cevabınızı kabul edeceğim :)
Thomas Ward

4
@ George Edison: $USERÖzellikle bu şekilde kullanmamanı tavsiye ederim . $USERgiriş kabuğu tarafından ayarlanır, programa ( env -i sh -c 'echo $USER') yayılmaz . Bu şekilde $USERboştur ve bir sözdizimi hatası oluşur.
Lekensteyn

1
@Lekensteyn Sadece $USERkabuk tarafından değil, aynı zamanda taklit edilmesi kolay bir şeydir. Whoami asıl kullanıcıyı geri getirecek.
Paul de Vrieze

2
@ PauldeVrieze Bu çeki kandırmanın amacı nedir?
htorque

1
@vewrewsomething: $USERkabuğunuz tarafından yorumlanır, örneğin sudo sh -c 'echo $USER'anlamlı olması için örneğiniz olmalıdır . @George: Yanlış varsayım yapar whoamihep dönecektir root0 kullanıcı kimliği için
sam Hocevar

11

Verimliliği göz önünde bulundurarak, önce EUIDçevre değişkenini test edebilir ve sonra mevcut değilse, standart idkomutu çağırabilirsiniz :

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

Bu sayede, OR kısayolu nedeniyle, bir sistem içi komut çağırmaktan kaçınılır, bir bellek içi değişkenin sorgusunu öncelersiniz.

Kod tekrar kullanımı:

function amIRoot() {
  ! ((${EUID:-0} || "$(id -u)"))
}

Korkarım ki kıyaslama yapmadın, ben de öyle ve bu da aynı zaman alıyor id -u. Burada aşağıdaki sonuçlarla birlikte tezgah betiğine bakın: pastebin.com/srC3LWQy
LinuxSecurityFreak


2

Komut dosyasını yalnızca root tarafından çalıştırılabilir hale getirmenin basit bir yolu, komut dosyasını şu satırla başlatmaktır:
#!/bin/su root


1
Bunu yapma Doğrudan root olarak giriş yapmaya çalışır, oysaki yasak olduğu için birçok sistemde sudo gerekebilir. Ayrıca, shebang, betiğinizin tasarlandığı sırada çalışmasını sağlamak için tasarlanmıştır, oysaki yöntem, betiğin, yazarın başkası tarafından çalıştırılması durumunda tahmin edilemeyeceği varsayılan kökünde çalışmasına neden olur. Bu nedenle, bir betiğin ayrıcalıklarını yükseltmek için shebang'ı kullanmak taşınabilirliğini ciddi şekilde kıracak ve birçok sistemde hatalara neden olacaktır. (su: Kimlik doğrulama hatası)
StarCrashr


1

Bu snippet şöyle olur:

  • Farklı oturumları kontrol et
  • kullanmayı öner sudo !!
  • ve bir hata döndür
eğer ["$ (whoami & 2> / dev / null)"! = "root"] && ["$ (id -un & 2> / dev / null)"! = "root"]
      sonra
      echo "Bu betiği çalıştırmak için kök olmalısın!"
      echo "kullanımı 'sudo !!'"
      çıkış 1
fi

1

Bu cevap sadece bir fikrinizi saklamak için bazılarınız için yararlı olabilir. Masaüstü GUI'den çalıştırılan ve kök ayrıcalıkları gerektiren bir komut dosyasına ihtiyacınız varsa, şu yolu deneyin:

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

Bu şekilde sizden kök kullanıcı şifresini isteyen hoş bir iletişim penceresi açılır. Sadece komut satırı sudo ile olduğu gibi.

Sisteminizde gksudomevcut olmayabilir, ardından yükleyin sudo apt-get install gksu.


0

Bu kod hem Bash hem de altında çalışan Bourne sh (FreeBSD altında test edilmiştir) ile EUID tanımlamamaktadır. EUID varsa, değeri döndürülür, aksi takdirde 'id' komutu çalıştırılır. Dahili ": -" bir kabuk kullandığı için yukarıdaki "veya" yukarıdaki örnekten biraz daha kısadır.

Sh içindeki kök:

# echo $EUID

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

In bash:
[chaapala@tenfwd2 ese]$ euid=${EUID:-`id -u`}
[chaapala@tenfwd2 ese]$ echo $euid
10260
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.