Cara memeriksa apakah menjalankan sebagai root di skrip bash

275

Saya sedang menulis skrip yang memerlukan izin tingkat root, dan saya ingin membuatnya sehingga jika skrip tidak dijalankan sebagai root, itu hanya gema "Tolong jalankan sebagai root." dan keluar.

Inilah beberapa pseudocode untuk apa yang saya cari:

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

  else (do stuff)
fi

exit

Bagaimana saya bisa melakukan yang terbaik (bersih dan aman)? Terima kasih!

Ah, hanya untuk memperjelas: bagian (melakukan hal-hal) akan melibatkan menjalankan perintah yang di-dan-dari mereka sendiri membutuhkan root. Jadi menjalankannya sebagai pengguna biasa hanya akan menghasilkan kesalahan. Ini hanya dimaksudkan untuk menjalankan skrip yang membutuhkan perintah root, tanpa menggunakan sudo di dalam skrip, saya hanya mencari beberapa gula sintaksis.

Nathan
sumber
8
(1) membuatnya tidak dapat dieksekusi oleh apa pun kemudian root (2) mengatur izin lebih lanjut juga .. (3) id -umengembalikan 0untuk root.
Wrikken

Jawaban:

404

Variabel lingkungan $ EUID memegang UID pengguna saat ini. UID Root adalah 0. Gunakan sesuatu seperti ini di skrip Anda:

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

Catatan: Jika Anda mendapatkan 2: [: Illegal number:centang apakah Anda memiliki #!/bin/shdi bagian atas dan mengubahnya ke #!/bin/bash.

ptierno
sumber
Tampaknya izin yang baik dan memiliki ini adalah lapisan keamanan ganda
Kolob Canyon
25
Saya pikir lebih baik membandingkan string dengan string, angka dengan angka. menggunakan tanda kurung ganda, Anda dapat menggunakan> secara langsung tanpa kutip [[$ EUID> 0]]
Sergio Abreu
7
Saya mendapat 2: [: Illegal number:peringatan sampai mengubahnya ke versi Sergio.
alexeydemin
1
@ thekiwi5000 Tanda titik koma hanya diperlukan jika thenberada pada baris yang sama dengan kondisi ...
ptierno
1
@StephenAngelico Sudo harus bekerja. Jika Anda mengujinya dengan melakukan $ sudo echo $ EUID; itu ujian yang buruk dan akan gagal karena $ EUID diperluas sebelum perintah dilewatkan ke sudo. Coba letakkan echo $ EUID dalam skrip uji dan jalankan dengan sudo.
user1169420
79

Dalam skrip bash, Anda memiliki beberapa cara untuk memeriksa apakah pengguna yang berjalan adalah root.

Sebagai peringatan , jangan periksa apakah pengguna root dengan menggunakan rootnama pengguna. Tidak ada yang menjamin bahwa pengguna dengan ID 0 dipanggil root. Ini adalah konvensi yang sangat kuat yang diikuti secara luas tetapi siapa pun bisa mengganti nama superuser dengan nama lain.

Saya pikir cara terbaik saat menggunakan bash adalah dengan menggunakan $EUID, dari halaman manual:

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

Ini adalah cara yang lebih baik daripada $UIDyang bisa diubah dan tidak mencerminkan pengguna nyata yang menjalankan skrip.

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

Cara saya mendekati masalah semacam itu adalah dengan menyuntikkan sudoperintah saya ketika tidak dijalankan sebagai root. Berikut ini sebuah contoh:

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

Dengan cara ini perintah saya dijalankan oleh root saat menggunakan superuser atau sudoketika dijalankan oleh pengguna biasa.

Jika skrip Anda selalu dijalankan oleh root, cukup setel hak-haknya ( 0500).

Sberder
sumber
Jika orang yang mencoba menjalankan skrip tidak memiliki hak sudo, ini akan menyebabkan kesalahan untuk dilemparkan dan perintah tidak akan berjalan? Hanya ingin memastikan, saya mengerti benar.
Caperneoignis
1
Saya tidak yakin jawaban ini 100% sepenuhnya benar. Di RHEL7.2 menggunakan Bash 4.2.46 ... jika saya printf $EUIDdengan atau tanpa sudo, saya mendapatkan kembali UID saya sendiri. Jika saya menggunakan, id -usaya mendapatkan UID saya dan ketika saya memohon dengan sudo saya mendapatkan 0 kembali. Apakah saya melakukan sesuatu yang salah?
0xSheepdog
4
@ 0xSheepdog, mungkin saja pada bash cli, ekspansi variabel $ EUID diselesaikan terlebih dahulu, lalu sudo mengubah pengguna. Karena itu Anda akan mendapatkan perilaku itu, tetapi dalam skrip, semuanya masih berfungsi dengan baik.
Alexander Bird
@AlexanderBird Poin bagus, terima kasih! Saya tidak melakukan pengujian nyata, hanya melaporkan pengalaman saya.
0xSheepdog
3
Gunakan "herestring" untuk pengujian Anda untuk mencegah ekspansi shell lokal dari variabel. Bandingkan sudo bash <<<'echo $EUID'dengan bash <<<'echo $EUID'. Lebih lanjut tentang heredok seperti heredoc di tldp.org/LDP/abs/html/x17837.html
Bruno Bronosky
75

Beberapa jawaban telah diberikan, tetapi tampaknya metode terbaik yang digunakan adalah:

  • id -u
  • Jika dijalankan sebagai root, akan mengembalikan id 0.

Ini tampaknya lebih dapat diandalkan daripada metode lain, dan tampaknya itu mengembalikan id 0 bahkan jika skrip dijalankan sudo.

Nathan
sumber
1
Hebat ini adalah jawaban terbaik
Dan Ortega
59
if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi

atau

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

:)

Dale_Reagan
sumber
Anda dapat mempertimbangkan untuk mengintegrasikan jawaban Jeremy J Starcher dengan bagian ini, pada akhirnya selalu hal yang sama ...
reallynice
Saya tahu itu dari terminal, ketika saya lupa untuk awalan sesuatu dengan sudosaya cukup ketik sudo !!dan itu berfungsi untuk saya, daripada menekan panah UP, pergi ke awal baris, dan menambahkan sudo dengan tangan. Tidak yakin apakah itu merupakan hal BASH atau SUDO atau lainnya, tetapi sebagian besar berfungsi sepanjang waktu.
0xSheepdog
@ 0xSheepdog: Ini adalah hal Bash (dan fitur dari beberapa shell lain seperti csh, di mana IIRC itu berasal).
Dijeda sampai pemberitahuan lebih lanjut.
Semua dalam semua, saya akan menghapus bagian backticked secara keseluruhan dan menulis ulang baris ok menjadi if [ "$(id -u)" -ne 0 ]; then echo 'Please run as root.' >&2; exit 1; fi. Bersulang.
LinuxSecurityFreak
29

Seperti @wrikken disebutkan dalam komentarnya, id -uadalah pemeriksaan root yang jauh lebih baik.

Selain itu, dengan penggunaan yang benar sudo, Anda dapat meminta skrip memeriksa dan melihat apakah skrip berjalan sebagai root. Jika tidak, minta ingat kembali melalui sudodan kemudian jalankan dengan izin root.

Bergantung pada apa yang dilakukan skrip, opsi lain mungkin untuk mengatur sudoentri untuk perintah khusus apa pun yang mungkin diperlukan skrip.

Jeremy J Starcher
sumber
Apakah ada cara yang anggun untuk membuat program mengingatnya sendiri? Mungkin ada beberapa variabel bash dengan jalur absolut ke program?
Nathan
1
Saya tidak berada di dekat perintah BASH sekarang untuk menguji, tetapi $0memiliki nama skrip yang berjalan. Ada beberapa contoh di sini yang mungkin dapat membantu Anda.
Jeremy J Starcher
25

Ada pemeriksaan sederhana untuk pengguna menjadi root.

The [[ stuff ]]sintaks adalah cara standar menjalankan pemeriksaan di bash.

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

Ini juga mengasumsikan bahwa Anda ingin keluar dengan 1 jika Anda gagal. The errorfungsi beberapa bakat yang set keluaran teks ke merah (tidak diperlukan, tapi cukup berkelas jika Anda bertanya kepada saya).

Slater Victoroff
sumber
Apa errorperintah itu? Sistem saya sepertinya tidak memilikinya. . .
ruakh
Oh, itu hanya bakat kecil. Tidak terlalu penting, tapi saya akan melampirkannya.
Slater Victoroff
4
Itu keren sekali! Jika saya dapat menyarankan beberapa perbaikan: (1) pindahkan baris baru ke akhir; (2) menulis ke standard error daripada standard output; (3) hanya mengatur warna jika kesalahan standar adalah terminal (daripada risiko menulis karakter melarikan diri ke file log lessatau yang lainnya); dan (4) mengatur warna latar belakang, sehingga teks akan dapat dibaca terlepas dari warna latar belakang terminal pengguna. Jadi, kira-kira seperti itu function error () { if [[ -t 2 ]] ; then echo $'\033[31;2;47m'"$@"$'\033[0m' ; else echo "$@" ; fi >&2 ; }. (Tweak seperti yang diinginkan.)
ruakh
3
Bukankah itu "-ne" bukannya "-eq"?
Carlos Rendon
2
Kode @CarlosRendon Slater adalah untuk mencegah sesuatu agar tidak dijalankan sebagai root. (Ini berlawanan dengan apa yang diminta OP, tetapi metode pemeriksaannya akan sama.)
Joshua Taylor
11

Cara yang sangat sederhana:

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

Manfaat menggunakan ini alih-alih idadalah Anda dapat memeriksa apakah pengguna non-root tertentu juga menjalankan perintah; misalnya.

if [ "$(whoami)" == "john" ] ; then
    # you are john
else
    # you are not john
fi
Matthew Trotter
sumber
jika Anda menguji pengguna dengan string "root", tidakkah Anda mengizinkan untuk menjalankan siapa pun yang bernama "root"?
pcarvalho
Anda lupa ';' setelah if
Triskeldeian
1
@peteroak siapa lagi yang akan dinamai root selain root?
ptierno
3
+1 untuk benar-benar menjawab pertanyaan tentang whoamidaripada menggunakan id; yang whoamiperintah juga dapat digunakan untuk memeriksa lain pengguna selain root, dengan nama.
Jez
10

0- Baca dokumentasi resmi GNU Linux, ada banyak cara untuk melakukannya dengan benar.

1- pastikan Anda meletakkan tanda tangan shell untuk menghindari kesalahan dalam interpretasi:

 #!/bin/bash

2 - ini skrip saya

#!/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
Sergio Abreu
sumber
10

Dalam jawaban ini, biarkan itu menjadi jelas, saya kira pembaca dapat membaca bashdan POSIX shell scripts like dash.

Saya percaya tidak ada banyak yang bisa dijelaskan di sini karena jawaban yang dipilih dengan sangat baik menjelaskan banyak hal.

Namun, jika ada sesuatu untuk dijelaskan lebih lanjut, jangan ragu untuk berkomentar, saya akan melakukan yang terbaik untuk mengisi kekosongan ini.


bashSolusi serba optimal (tidak hanya ) untuk kinerja dan keandalan; semua kerang kompatibel

Solusi baru:

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

Benchmark (simpan ke file 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: [email protected]                      ##
##                             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

Solusi asli:

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

^^^ Solusi striked-out terbukti tidak mempercepat, tetapi sudah ada sejak lama, jadi saya akan menyimpannya di sini selama saya melihat perlu.


Penjelasan

Karena banyak kali lebih cepat untuk membaca variabel $EUIDstandar bash, nomor ID pengguna yang efektif, daripada menjalankan id -uperintah untuk POSIX - hanya menemukan ID pengguna, solusi ini menggabungkan keduanya menjadi fungsi yang dikemas dengan baik. Jika, dan hanya jika, $EUIDkarena alasan apa pun tidak tersedia, id -uperintah akan dieksekusi, memastikan kami mendapatkan nilai pengembalian yang tepat, apa pun kondisinya .


Mengapa saya memposting solusi ini setelah bertahun-tahun OP bertanya

Nah, jika saya melihat dengan benar, sepertinya ada kode yang hilang di atas.

Soalnya, ada banyak variabel yang harus diperhitungkan, dan salah satunya adalah menggabungkan kinerja dan keandalan .


Solusi POSIX portabel + Contoh penggunaan fungsi di atas

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

Kesimpulan

Sebanyak mungkin Anda tidak menyukainya, lingkungan Unix / Linux telah sangat beragam. Berarti ada orang yang bashsangat menyukai, mereka bahkan tidak memikirkan portabilitas ( cangkang POSIX ). Orang lain seperti saya lebih suka kerang POSIX . Sekarang ini masalah pilihan dan kebutuhan pribadi.

LinuxSecurityFreak
sumber
6

Jika skrip benar-benar membutuhkan akses root maka izin file-nya harus mencerminkan itu. Memiliki skrip root yang dapat dieksekusi oleh pengguna non-root akan menjadi bendera merah. Saya mendorong Anda untuk tidak mengontrol akses dengan ifcek.

chown root:root script.sh
chmod u=rwx,go=r script.sh
John Kugelman
sumber
4
Jika seseorang memiliki izin mereka agar ini berfungsi dengan baik, tapi saya merasa terlalu sering menggunakan 777bom membuat pemeriksaan ini sedikit salah untuk jenis pengguna yang akan melakukan kesalahan di tempat pertama.
Slater Victoroff
7
Ini dengan asumsi pengguna menjalankan skrip yang dapat dieksekusi. Jika pengguna hanya memanggilnya bash /path/to/scriptmasih dapat dijalankan meskipuno=r
ptierno
5

Salah satu cara sederhana untuk membuat skrip hanya dapat dijalankan oleh root adalah memulai skrip dengan baris:

#!/bin/su root

alexandre1985
sumber
1
Saya ingin tahu mengapa jawaban ini tidak dipilih lebih tinggi? Sepertinya yang paling sederhana dan terbersih. Apakah ada kerugian di sini?
Bassinator
@Bassinator Saya percaya beberapa orang mengatakan itu tidak akan berjalan pada nix tertentu tetapi sejauh ini telah bekerja dengan baik di Linux saya. Cobalah! Mungkin jawaban ini sudah terlambat untuk perlombaan, tetapi saya mencoba menambahkan pengetahuan yang sederhana untuk komunitas (daripada memberikan jawaban yang serupa, seperti kebanyakan di utas ini: /) Pilih ini jika Anda beruntung membaca ini dan itu bekerja pada mesin Anda
alexandre1985
@TamusJRoyce Jika tujuannya memeriksa apakah Anda menjalankan sebagai root dan tidak memaksa skrip untuk menjalankan hanya sebagai root, mengapa kemudian dalam setiap jawaban, setelah memeriksa jika dijalankan sebagai root, mereka membuat skrip exit? Dan masih jawaban-jawaban itu sedang dibesarkan? Saya kira orang secara implisit tidak ingin skrip dijalankan sebagai root. Jadi saya mengikuti cara berpikir itu, dengan jawaban yang lebih sederhana. Tapi ya, Anda juga bisa belajar dari jawaban yang lebih jelas di atas
alexandre1985
@ alexandre1985 Persis. Skenario: Jika dijalankan sebagai root, mungkin Anda ingin skrip default untuk menginstal program secara global ketika ditanya bagaimana Anda ingin menginstalnya. Kalau tidak, defaultnya diatur untuk menginstalnya secara lokal. Alih-alih menekan enter, pengguna dapat memilih untuk menginstalnya global atau lokal. Tetapi jika mereka menyukai default, mereka bisa menekan enter. Dan mereka tidak akan diminta dengan kata sandi. Shebang Anda tidak akan pernah "memeriksa" apakah Anda root (per judul). Tetapi saya masih berpikir jawaban ini bermanfaat.
TamusJRoyce
@TamusJRoyce benar-benar masuk akal komentar Anda. Memang merupakan masalah dan solusi ini bukan untuk kasus penggunaan itu. Anda membuka perspektif saya. Kamu benar. Terima kasih
alexandre1985
4

coba kode berikut:

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

ATAU

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

Sejauh yang saya tahu cara yang benar untuk memeriksanya adalah:

if [ $(id -u) = "0" ]; then
    echo "You are root"
else
    echo "You are NOT root"
fi

Lihat bagian "Menguji Root" di sini:

http://linuxcommand.org/lc3_wss0080.php

WebBrother
sumber
1
ganti = "0"dengan-eq 0
LinuxSecurityFreak
1
@LinuxSecurityFreak, saya akan menggantinya jika Anda menjelaskan mengapa saya harus melakukannya.
WebBrother
2

id -ujauh lebih baik daripada whoami, karena beberapa sistem seperti android mungkin tidak menyediakan kata root.

Contoh:

# whoami
whoami
whoami: unknown uid 0
Tautan kecil
sumber
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

Catatan editor: Jika Anda tidak membutuhkan tanda kurung ganda, gunakan tanda kurung tunggal untuk portabilitas kode.

Pramod Kharade
sumber
3
Anda belum menjelaskan mengapa Anda telah memberikan jawaban alternatif untuk pertanyaan berusia 5 tahun yang sudah memiliki beberapa jawaban.
Styphon
0

Periksa apakah Anda root dan berhenti jika Anda tidak:

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

Atau dalam contoh ini, cobalah untuk membuat direktori di lokasi root lalu coba setelah hak ditingkatkan.

Periksa apakah Anda root dan jika tidak meningkat jika memungkinkan:

# 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)
Mike Q
sumber
-1

Periksa root:

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

Diuji dan berjalan di root.

fvillalba89
sumber