Bir bash betiğinde root olarak çalışıp çalışmadığını kontrol etme


274

Kök düzeyi izinleri gerektiren bir komut dosyası yazıyorum ve komut dosyası kök olarak çalıştırılmazsa, basitçe "Lütfen kök olarak çalıştırın." ve çıkar.

İşte aradığım şey için bazı sözde kod:

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

  else (do stuff)
fi

exit

Bunu en iyi (temiz ve güvenli) nasıl başarabilirim? Teşekkürler!

Ah, sadece açıklığa kavuşturmak için: (şeyler yap) kısmı, kendi başına kök gerektiren komutları çalıştırmayı içerecektir. Yani normal bir kullanıcı olarak çalıştırmak sadece bir hata ile gelirdi. Bu sadece temiz komutlar için sudo kullanmadan kök komutları gerektiren bir komut dosyası çalıştırmak içindir, ben sadece sözdizimsel şeker arıyorum.


8
(1) başka bir şey tarafından çalıştırılamaz hale getirin, sonra root (2) daha fazla izin düzenler .. (3) root için id -ugeri döner 0.
Wrikken

Yanıtlar:


403

$ EUID ortam değişkeni, geçerli kullanıcının UID'sini tutar. Kökün UID'si 0. Komut dosyanızda şöyle bir şey kullanın:

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

Not: Eğer alırsanız 2: [: Illegal number:varsa çek #!/bin/shüstündeki ve bunu değiştirmek #!/bin/bash.


Öyle görünüyor ki iyi izinler ve buna sahip olmak iki kat güvenlikli
Kolob Kanyonu

25
Dize dize, sayı ile sayı karşılaştırmak daha iyi olduğunu düşünüyorum. çift ​​parantez kullanarak,> tırnak işareti olmadan doğrudan kullanabilirsiniz [[$ EUID> 0]]
Sergio Abreu

7
2: [: Illegal number:Sergio'nun sürümüne geçene kadar uyarı aldım .
alexeydemin

1
@ thekiwi5000 Noktalı virgül, yalnızca koşulla thenaynı
satırdaysa gereklidir

1
@StephenAngelico Sudo çalışmalı. Eğer $ sudo echo $ EUID yaparak test ediyorsanız; bu kötü bir testtir ve başarısız olacaktır çünkü komut sudo'ya geçmeden önce $ EUID genişletilmiştir. Echo $ EUID'yi bir test komut dosyasına koymayı ve sudo ile çalıştırmayı deneyin.
user1169420

79

Bir bash betiğinde, çalışan kullanıcının kök olup olmadığını kontrol etmenin birkaç yolu vardır.

Bir As uyarı , bir kullanıcı kök kullanarak ise, kontrol etmiyoruz rootadı. Hiçbir şey 0 kimliğine sahip kullanıcının çağrılmasını garanti etmez root. Geniş bir şekilde takip edilen çok güçlü bir kongre ama herkes süper kullanıcıyı başka bir adla yeniden adlandırabilirdi.

Ben kullanarak en iyi şekilde düşünmek bash kullanmaktır $EUIDadam sayfasından,:

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

Bu, $UIDdeğiştirilebilecek olandan daha iyi bir yoldur ve betiği çalıştıran gerçek kullanıcıyı yansıtmaz.

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

Bu tür bir soruna yaklaşmamın bir yolu sudo, kök olarak çalışmadığında komutlarımı enjekte etmektir . İşte bir örnek:

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

Bu şekilde, süper kullanıcı kullanırken komutum kök tarafından veya sudonormal bir kullanıcı tarafından çalıştırıldığında çalıştırılır.

Betiğiniz her zaman root tarafından çalıştırılacaksa, hakları buna göre ayarlayın ( 0500).


Komut dosyasını çalıştırmaya çalışan kişi sudo ayrıcalıklarına sahip değilse, bu hata atılır ve komut çalışmaz? Sadece emin olmak istiyorum, doğru anladım.
Caperneoignis

1
Bu cevabın% 100 tamamen doğru olduğundan emin değilim. Bash 4.2.46 kullanan RHEL7.2'de ... printf $EUIDsudo ile veya sudo olmadan, kendi UID'mi geri alıyorum. Ben kullanırsanız id -usudo ile bunun çağırmak benim UID harekete geçtiğinde ben 0 kolla. Ben yanlış bir şey mi yaptım?
0xSheepdog

4
@ 0xSheepdog, bash cli'de $ EUID değişken genişletmesinin önce çözülmesinin ardından sudo'nun kullanıcıyı değiştirmesi mümkündür. Bu nedenle, bu davranışı elde edersiniz, ancak komut dosyalarında her şey yine de iyi çalışır.
Alexander Bird

@AlexanderBird İyi bir nokta, teşekkür ederim! Gerçek bir test yapmadım, tecrübemi rapor ettim.
0xSheepdog

3
Değişkenin yerel kabuk genişlemesini önlemek için testiniz için bir "herestring" kullanın. Karşılaştırma sudo bash <<<'echo $EUID'için bash <<<'echo $EUID'. Yorumlu metin benzeri yorumlamalar hakkında daha fazla bilgi için tldp.org/LDP/abs/html/x17837.html
Bruno Bronosky

75

Birkaç cevap verilmiştir, ancak en iyi yöntem kullanmaktır:

  • id -u
  • Kök olarak çalıştırılırsa, 0 kimliği döndürür.

Bu, diğer yöntemlerden daha güvenilir gibi görünüyor ve komut dosyası çalıştırılsa bile 0 kimliği döndürüyor gibi görünüyor sudo.


1
Harika, bu en iyi cevap
Dan Ortega

59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

veya

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

:)


Jeremy J Starcher'ın cevabını bu bölümle entegre etmeyi düşünebilirsiniz , sonunda her zaman aynı şeyler ...
reallynice

Terminalden bir şeyi önek eklemeyi unuttuğumda sudo, basitçe yazabileceğimi sudo !!ve YUKARI okuna basmak, satırın başına gitmek ve sudo elle eklemek yerine işi benim için yaptığını biliyorum . Bunun bir BASH veya SUDO veya başka bir şey olup olmadığından emin değilim, ancak çoğu zaman işe yarıyor.
0xSheepdog

@ 0xSheepdog: Bu bir Bash olayı (ve IIRC'nin ortaya çıktığı csh gibi diğer kabukların bir özelliği).
sonraki duyuruya kadar duraklatıldı.

Sonuçta, bir bütün olarak backticked parçası kaldırmak ve yeniden ok satırına yazmak if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. Şerefe.
LinuxSecurityFreak

29

@Wrikken'in yorumlarında belirttiği gibi, id -u kök için çok daha iyi bir kontrol.

Buna ek olarak, uygun kullanımı ile sudo, komut dosyasının root olarak çalışıp çalışmadığını kontrol edebilir ve görebilirsiniz. Değilse, kendisinisudo ve kök izinleriyle çalıştırır.

Komut dosyasının ne yaptığına bağlı olarak, komut sudodosyasının ihtiyaç duyabileceği özel komutlar için bir giriş ayarlamak olabilir.


Bir programın kendisini hatırlatmasının zarif bir yolu var mı? Belki de programın mutlak yolunu içeren bazı bash değişkenleri vardır?
Nathan

1
Şu anda test etmek için bir BASH istemine yakın değilim, ancak $0çalışan komut dosyasının adı var. Burada size yardımcı olabilecek bazı örnekler var .
Jeremy J Starcher

25

Bir kullanıcının root olması için basit bir kontrol vardır.

[[ stuff ]]Sözdizimi bash bir çek çalışan standart bir yöntemdir.

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

Bu, başarısız olursa 1 ile çıkmak istediğinizi varsayar. errorFonksiyon kırmızıya setleri çıkış metni (gerekli değil, ama oldukça klas bana sorarsanız) bazı yetenek olduğunu.


Bu errorkomut nedir? Sistemimde öyle görünmüyor. . .
ruakh

Oh, bu sadece küçük bir yetenek. O kadar da önemli değil, ama ekleyeceğim.
Slater Victoroff

4
Bu oldukça havalı! Birkaç iyileştirme önerebilirsem: (1) yeni satırı sonuna taşı; (2) standart çıktı yerine standart hataya yazma; (3) yalnızca standart hata bir terminal ise rengi ayarlayın (kaçış karakterlerini günlük dosyalarına yazma riskinden ziyade ya lessda değil); ve (4) bir arka plan rengi ayarlayın, böylece metin kullanıcının terminalinin arka plan renginden bağımsız olarak okunabilir. Yani, böyle bir şey function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (İstediğiniz gibi
düzenleyin

3
"-Eq" yerine "-ne" olmamalı mı?
Carlos Rendon

2
@CarlosRendon Slater'in kodu, bir şeyin kök olarak çalıştırılmasını önlemektir . (Bu OP'nin istediklerinin tersidir, ancak kontrol yöntemi aynı olurdu.)
Joshua Taylor

11

Çok basit bir şekilde söylemek gerekirse:

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

Bunun yerine bunu kullanmanın yararı, idkök olmayan bir kullanıcının komutu çalıştırıp çalıştırmadığını kontrol edebilmenizdir; Örneğin.

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

kullanıcıyı "root" dizesiyle test ediyorsanız, "root" adlı kimsenin çalıştırılmasına izin vermiyor musunuz?
pcarvalho

';' if sonra
Triskeldeian

1
@peteroak root'tan başka kimin root olarak adlandırılması gerekir?
ptierno

3
whoamiKullanmak yerine soruyu gerçekten cevapladığınız için +1 id; whoamiKomut ayrıca kontrol etmek için kullanılabilecek diğer adıyla, root daha kullanıcılara.
Jez

10

0- Resmi GNU Linux belgelerini okuyun, doğru şekilde yapmanın birçok yolu vardır.

1- yorumlamadaki hataları önlemek için kabuk imzasını koyduğunuzdan emin olun:

 #!/bin/bash

2- bu benim senaryom

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

10

Bu cevapta, net olsun, okuyucunun okuduğu bashve POSIX kabuk komut dosyalarınıdash .

Yüksek oylanan cevapların çoğunu açıklamak için iyi bir iş çıkardığı için burada açıklanacak çok şey olmadığına inanıyorum.

Ancak, daha fazla açıklanacak bir şey varsa, yorum yapmaktan çekinmeyin, boşlukları doldurmak için elimden geleni yapacağım.


bashPerformans ve güvenilirlik için optimize edilmiş çok yönlü (sadece değil ) çözüm; tüm mermiler uyumlu

Yeni çözüm:

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

Karşılaştırma ölçütü (dosyaya kaydet 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: info@vlastimilburian.cz                      ##
##                             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

Orijinal çözüm:

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

^^^ Çarpıcı çözüm, işleri hızlandırmak için kanıtlanmadı, ancak uzun zamandır var, bu yüzden gerekli gördüğüm sürece burada tutacağım.


açıklama

Etkili kullanıcı kimlik numarası olan $EUIDstandart bashdeğişkeni okumak id -uiçin POSIX -ly kullanıcı kimliğini bulmak için komut yürütmekten çok daha hızlı olduğundan , bu çözüm her ikisini de iyi paketlenmiş bir işlevde birleştirir. Eğer ve sadece $EUIDherhangi bir nedenden dolayı mevcut değilse, id -ukomut çalıştırılacak ve koşullar ne olursa olsun uygun dönüş değerini almamızı sağlayacaktır .


OP'yi bu kadar yıl sonra neden bu çözümü gönderiyorum?

Peki, doğru görürsem, yukarıda eksik bir kod parçası var gibi görünüyor.

Görülmesi gereken birçok değişken var ve bunlardan biri performans ve güvenilirliği birleştiriyor .


Taşınabilir POSIX çözümü + Yukarıdaki fonksiyonun kullanım örneği

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

Sonuç

Beğenmediğiniz kadar Unix / Linux ortamı çok çeşitlendi. Yani bashçok hoşlanan insanlar var, taşınabilirliği bile düşünmüyorlar ( POSIX kabukları). Benim gibi diğerleri POSIX mermilerini tercih ediyor . Bugünlerde kişisel seçim ve ihtiyaçlar söz konusudur.


6

Komut dosyası gerçekten kök erişimi gerektiriyorsa, dosya izinleri bunu yansıtmalıdır. Kök olmayan kullanıcılar tarafından çalıştırılabilir bir kök komut dosyasına sahip olmak kırmızı bir bayrak olacaktır. Erişimi bir ifçekle kontrol etmemenizi tavsiye ederim .

chown root:root script.sh
chmod u=rwx,go=r script.sh

4
Birinin bu harika çalışması için izinleri varsa, ama 777bombanın aşırı kullanımı bu kontrolü ilk etapta hata yapacak kullanıcılar için biraz hatalı yapıyor gibi hissediyorum .
Slater Victoroff

7
Bu, kullanıcının yürütülebilir bir komut dosyası çalıştırdığını varsayar. Kullanıcı sadece ararsa bash /path/to/scriptbile yine de çalıştırılabiliro=r
ptierno

5

Komut dosyasını yalnızca root tarafından çalıştırılabilir yapmanın basit bir yolu, komut dosyasını şu satırla başlatmaktır:

#!/bin/su root


1
Bu cevabın neden daha yüksek oy kullanıldığını merak ediyorum? En basit ve en temiz gibi görünüyor. Burada dezavantajlar var mı?
Bassinator

@Bassinator Bazı insanların belirli nix'lerde çalışmadığını söylediğine inanıyorum, ancak şu ana kadar Linux'umda kusursuz bir şekilde çalışıyor. Dene! Belki bu cevap yarışa geç geldi ama topluluğa basit bir bilgi eklemek istiyorum (bu konudaki çoğu gibi benzer cevaplar vermek yerine: /) Bunu okumak için şanslıysanız buna oy verin ve makinenizde çalışıyor
alexandre1985

@TamusJRoyce Hedef bir kök olarak çalışıp çalışmadığınızı kontrol edip komut dosyasını yalnızca kök olarak çalıştırmaya zorlamıyorsanız, neden her yanıtta, kök olarak çalışıp çalışmadığını kontrol ettikten sonra komut dosyasını oluştururlar exit? Ve hala bu cevaplar iptal ediliyor mu? Sanırım insanlar dolaylı olarak betiğin root olarak çalıştırılmasını istemiyorlar. Ben de bu düşünce tarzını daha basit bir cevapla takip ediyorum. Ama evet, yukarıdaki daha ayrıntılı cevaplardan da öğrenebilirsiniz
alexandre1985

@ alexandre1985 Kesinlikle. Senaryo: Kök olarak çalışıyorsa, bir komut dosyasının programı nasıl yüklenmesini istediğinizi sorduğunda varsayılan olarak yüklemesini isteyebilirsiniz. Aksi takdirde, varsayılan ayar yerel olarak yüklenecek şekilde ayarlanmıştır. Enter tuşuna basmak yerine, kullanıcı genel veya yerel olarak yüklemeyi seçebilir. Ancak varsayılanı beğenirlerse enter tuşuna basabilirler. Ve parola istenmez. Kök (başlık başına) iseniz shebang asla "kontrol" olmaz. Ama yine de bu cevabın yararlı olduğunu düşünüyorum.
TamusJRoyce

@TamusJRoyce yorumunuzu tamamen mantıklı. Gerçekten bir endişe kaynağıdır ve bu çözüm bu kullanım durumu için değildir. Benim bakış açımı açtın. Haklısın. Teşekkürler
alexandre1985

4

aşağıdaki kodu deneyin:

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

VEYA

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


2

id -u daha iyidir whoamiandroid gibi bazı sistemler kelime kökünü sağlamayabileceğinden .

Misal:

# whoami
whoami
whoami: unknown uid 0

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

Editörün notu: Çift parantez gerekmiyorsa, kod taşınabilirliği için tek parantez kullanın.


3
Zaten birkaç cevabı olan 5 yaşındaki bir soruya neden alternatif bir cevap verdiğinizi açıklamadınız.
2018'de Styphon

0

Kök olup olmadığınızı kontrol edin ve değilseniz:

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

Veya bu örnekte, kök konumunda bir dizin oluşturmaya çalışın ve sonra haklar yükseltildikten sonra deneyin.

Kök olup olmadığınızı ve mümkünse yükselmediğinizi kontrol edin:

# 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)

-1

Kök olup olmadığını kontrol edin:

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

Test edildi ve kökte çalışıyor.

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.