Bagaimana skrip memeriksa apakah dijalankan sebagai root?

104

Saya sedang menulis skrip bash yang sederhana, tetapi saya membutuhkannya untuk memeriksa apakah skrip tersebut dijalankan sebagai root atau tidak. Saya tahu mungkin ada cara yang sangat sederhana untuk melakukan itu, tetapi saya tidak tahu caranya.

Untuk lebih jelasnya:
Apa cara sederhana untuk menulis skrip foo.sh , sehingga perintah ./foo.shmenghasilkan 0, dan perintah sudo ./foo.shmenghasilkan 1?

Malabarba
sumber

Jawaban:

148
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 
   exit 1
fi
aneeshep
sumber
7
Saya menerima penyebab yang satu ini (setelah beberapa pengujian) menggunakan variabel sistem EUID ternyata (kira-kira 100 kali) lebih cepat daripada menjalankan perintah (id -u), tetapi semua jawaban bekerja dengan baik.
Malabarba
18
Juga, $UIDdan $EUIDmerupakan bashism. Hanya shell yang mematuhi POSIX yang tidak memiliki variabel-variabel itu dan Anda harus menggunakannya id(1).
David Foerster
3
dalam skrip bash, Anda bisa menggunakan if ((EUID)); then, lihat komentar @ geirha
jfs
7
@Andrew: Variabel diganti sebelum diteruskan ke sudo. Jika Anda menjalankan, sudo sh -c 'echo $EUID'Anda akan melihat hasil yang Anda harapkan.
M. Dudley
6
@Andrew - Saya tahu saya terlambat di sini, tetapi untuk anak cucu: $EUIDadalah Bashism (seperti yang disebutkan di atas oleh @DavidFoerster), dan /bin/shkemungkinan besar Anda memiliki tautan /bin/dash, bukan /bin/bash. sudo bash -c 'echo $EUID'akan menghasilkan hasil yang diharapkan.
Adrian Günter
118

Seorang pengguna root tidak harus dinamai "root". whoamimengembalikan nama pengguna pertama dengan ID pengguna 0. $USERberisi nama pengguna yang masuk, yang dapat memiliki ID pengguna 0, tetapi memiliki nama yang berbeda.

Satu-satunya program yang dapat diandalkan untuk memeriksa apakah akun tersebut login sebagai root, atau tidak:

id -u

Saya menggunakan -uuntuk ID pengguna yang efektif , bukan -runtuk ID pengguna yang sebenarnya . Izin ditentukan oleh ID pengguna yang efektif , bukan yang asli .

Tes

/etc/passwdberisi nama pengguna berikut dengan ID pengguna 0dalam urutan yang diberikan:

rootx
root2

Masuk sebagai root2, memberikan hasil selanjutnya:

  • whoami: rootx
  • echo $USER: root2(ini mengembalikan string kosong jika program dimulai di lingkungan kosong, mis. env -i sh -c 'echo $USER')
  • id -u: 0 Seperti yang Anda lihat, program lain gagal dalam pemeriksaan ini, hanya id -uberlalu.

Skrip yang diperbarui akan terlihat seperti ini:

#!/bin/bash
if ! [ $(id -u) = 0 ]; then
   echo "I am not root!"
   exit 1
fi
Lekensteyn
sumber
5
Anda tidak perlu id -udi bash askubuntu.com/questions/30148/…
jfs
5
Saya selalu berusaha untuk tetap memenuhi standar POSIX, menggunakan sh( dash) sebagai penerjemah alih-alih bash. Tapi tembakan yang bagus, simpan garpu lain :)
Lekensteyn
Setelah kedinginan beberapa saat, saya kembali dan memeriksanya. Metode Lekensteyn tampaknya memang lebih baik. Jawabannya sekarang adalah jawaban yang baru diterima. +1 untuk Anda, Lekensteyn, esp. untuk mendapatkan lencana yang sulit didapat dari pertanyaan ini;)
Thomas Ward
Terima kasih telah menunggu selama itu untuk menerima pertanyaan saya: DI saya mendapat lencana Penduduk Emas dan Jawaban yang bagus untuk jawaban ini :) Saya ingin tahu bagaimana pertanyaan ini menjadi populer, 345 dilihat dalam sehari!
Lekensteyn
3
Saya telah melihat versi yang lebih pendek [ -w / ],. Idenya tetap sama. Catatan: pada chroot tertentu, [ -w /etc/shadow ]akan gagal karena /etc/shadowtidak ada, oleh karena itu pendekatan dengan /lebih disukai. Cara yang lebih baik akan memeriksa kebutuhan aktual untuk izin root. Jika skrip perlu ditulis /etc/someconfig, cukup periksa apakah file itu dapat ditulisi ATAU file tersebut tidak ada dan /etcdapat ditulisi.
Lekensteyn
30

Seperti yang dikatakan @Lekensteyn, Anda harus menggunakan ID pengguna yang efektif. Anda tidak perlu memanggil id -ubash:

#!/bin/bash

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

Saran @ geirha dari komentar menggunakan evaluasi aritmatika:

#!/bin/bash

if (( EUID != 0 )); then
   echo "You must be root to do this." 1>&2
   exit 100
fi
jfs
sumber
7
Secara umum orang harus menggunakan ((..))untuk menguji angka, dan [[..]]untuk menguji string dan file, jadi saya akan melakukan if (( EUID != 0 )); thensebaliknya, atau hanyaif ((EUID)); then
geirha
@geirha: Saya telah menambahkan saran Anda.
jfs
2
EUIDharus menjadi $EUID. Alih-alih menggunakan (( $EUID != 0 )), gunakan [ $EUID != 0 ]. Ini juga akan bekerja dengan baik dash.
Lekensteyn
2
@Lekensteyn: EUIDbekerja dengan baik. Pertanyaan bashtidak ditandai dash. Perintah env -i sh -c '[ $EUID != 0 ]'gagal, tetapi env -i bash -c '(( EUID != 0 ))'berhasil. btw, dashtidak berfungsi untuk beberapa karakter non-ascii di Ubuntu stackoverflow.com/questions/5160125/… Ini adalah 2011 dan ada orang yang menggunakan bahasa lain.
jfs
Setelah melihat kembali hal ini ketika sedang bosan, dan pengujian, saya akan menggunakan metode ini seperti yang tercantum di sini dengan $EUIDhal - hal dari titik ini ke depan. Saya telah mengubah jawaban yang diterima sebagai hasilnya.
Thomas Ward
20

Anda dapat melakukannya dengan menggunakan whoamiperintah, yang mengembalikan pengguna saat ini:

#!/bin/bash

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

...

Menjalankan di atas akan mencetak You must be root to do this.jika pengguna saat ini tidak root.


Catatan: alternatif dalam beberapa kasus adalah dengan hanya memeriksa $USERvariabel:

if [ $USER != 'root' ]
Nathan Osman
sumber
Saya akan melihat kode, melihat apakah tidak membuat skrip gagal atau sesuatu. Jika berhasil, saya akan menerima jawaban Anda :)
Thomas Ward
4
@ George Edison: Saya merekomendasikan untuk tidak menggunakan $USER, terutama dengan cara ini. $USERdiatur oleh shell login, tidak perlu disebarkan ke program ( env -i sh -c 'echo $USER'). Dengan cara itu, $USERkosong dan terjadi kesalahan sintaksis.
Lekensteyn
1
@Lekensteyn Tidak hanya $USERdiatur oleh shell, itu juga sesuatu yang mudah dipalsukan. Whoami akan mengembalikan pengguna yang sebenarnya.
Paul de Vrieze
2
@ PauldeVrieze Apa gunanya menipu cek itu?
htorque
1
@ andrewsomething: $USERditafsirkan oleh shell Anda, contoh Anda harus sudo sh -c 'echo $USER'bermakna. @ George: itu membuat asumsi yang salah yang whoamiakan selalu kembali rootuntuk UID 0.
sam hocevar
11

Mempertimbangkan efisiensi, Anda dapat menguji, pertama, EUIDvariabel lingkungan dan kemudian, jika tidak ada, hubungi idperintah standar :

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

Dengan cara ini, karena pintasan OR , Anda menghindari memanggil perintah sistem, memprioritaskan kueri dari variabel di dalam memori.

Penggunaan kembali kode:

function amIRoot() {
  ! ((${EUID:-0} || "$(id -u)"))
}
Luchostein
sumber
Saya khawatir Anda belum membandingkannya, ya sudah dan ini membutuhkan waktu yang sama id -u. Lihat skrip bench bersama dengan hasil di bawahnya di sini: pastebin.com/srC3LWQy
LinuxSecurityFreak
9
#!/bin/bash
[[ $(id -u) != 0 ]] 
echo $?
João Pinto
sumber
2

Salah satu cara sederhana untuk membuat skrip hanya dapat dijalankan oleh root adalah memulai skrip dengan baris:
#!/bin/su root

alexandre1985
sumber
1
Jangan lakukan ini. Ia mencoba masuk secara langsung sebagai root, sedangkan sudo mungkin diperlukan pada banyak sistem karena yang pertama dilarang. Lebih jauh, shebang dimaksudkan untuk memastikan skrip Anda berjalan dalam skrip yang dirancang, sedangkan metode Anda akan menyebabkan skrip dijalankan dalam shell default root, yang tidak dapat diprediksi jika skrip dijalankan oleh siapa pun selain penulis. Oleh karena itu, menggunakan shebang untuk meningkatkan hak istimewa skrip akan sangat merusak portabilitasnya dan mengakibatkan kesalahan pada banyak sistem. (su: Kegagalan otentikasi)
StarCrashr
1
#!/bin/bash
uid=`id -u`
if [ "$uid" == "0" ]
then
    echo 1
else
    echo 0
fi
Delan Azabani
sumber
1

Cuplikan ini akan:

  • Periksa sesi yang berbeda
  • menyarankan untuk digunakan sudo !!
  • dan kembalikan kesalahan
if ["$ (whoami & 2> / dev / null)"! = "root"] && ["$ (id -un & 2> / dev / null)"! = "root"]
      kemudian
      echo "Anda harus root untuk menjalankan skrip ini!"
      gema "gunakan 'sudo !!'"
      keluar 1
fi
rubo77
sumber
1

Jawaban ini hanya untuk menyimpan ide dengan semoga bermanfaat bagi sebagian dari Anda. Jika Anda memerlukan skrip yang dijalankan dari desktop GUI dan membutuhkan hak akses root, coba cara ini:

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

Dengan cara ini Anda akan mendapatkan jendela dialog yang bagus meminta Anda untuk kata sandi pengguna root. Sama seperti dengan sudo baris perintah.

The gksudomungkin tidak tersedia di sistem anda kemudian menginstalnya dengan sudo apt-get install gksu.

gertas
sumber
0

Kode ini bekerja di bawah Bash dan Bourne sh stock (diuji di bawah FreeBSD) yang tidak mendefinisikan EUID. Jika EUID ada, nilainya dikembalikan, jika tidak maka perintah 'id' dijalankan. Ini sedikit lebih pendek daripada contoh "atau" di atas, karena menggunakan shell bawaan ": -".

Root di 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
sumber