Cách ngăn tập lệnh chạy nếu nó không root (và echo Hồi không chạy bằng root! Thoát ra khỏi Trò chơi)


17

Đây là nguồn của tôi:

#!/bin/bash

echo "Running script to free general cached memory!"
echo "";
echo "Script must be run as root!";
echo "";
echo "Clearing swap!";
swapoff -a && swapon -a;
echo "";
echo "Clear inodes and page file!";
echo 1 > /proc/sys/vm/drop_caches;
echo "";

Nó xóa bộ nhớ cache và các công cụ, và nó lặp lại rằng nó cần phải được chạy như root trong thiết bị đầu cuối. Về cơ bản tôi chỉ muốn tập lệnh ngừng chạy nếu nó phát hiện ra nó không được thực thi như root.

Thí dụ:

"Running script to free general cached memory!"
"Warning: script must be run as root or with elevated privileges!"
"Error: script not running as root or with sudo! Exiting..."

Nếu chạy với đặc quyền nâng cao, nó chỉ chạy như bình thường. Có ý kiến ​​gì không? Cảm ơn!


Bản sao có thể có của Cách ngăn cản root chạy tập lệnh
muru

2
@muru, ngoại trừ câu hỏi khác là ngược lại: thất bại tập lệnh nếu chạy bằng root.
Stéphane Chazelas

3
@ StéphaneChazelas ah, xấu của tôi. Đã rút lại
muru

Một cách khác là giới hạn số lượng công việc được thực hiện rootbằng tiền tố tất cả các lệnh phải chạy như rootvới sudo.
Revierpost

Câu trả lời:


46
#!/bin/sh

if [ "$(id -u)" -ne 0 ]; then
        echo 'This script must be run by root' >&2
        exit 1
fi

cat <<HEADER
Host:          $(hostname)
Time at start: $(date)

Running cache maintenance...
HEADER

swapoff -a && swapon -a
echo 1 >/proc/sys/vm/drop_caches

cat <<FOOTER
Cache maintenance done.
Time at end:   $(date)
FOOTER

Người dùng root có UID 0 (bất kể tên của tài khoản "root"). Nếu UID hiệu quả được trả về id -ukhông bằng 0, người dùng sẽ không thực thi tập lệnh với quyền root. Sử dụng id -ruđể kiểm tra ID thật (UID của người dùng gọi tập lệnh).

Không sử dụng $EUIDtrong tập lệnh vì điều này có thể được sửa đổi bởi người dùng không có đặc quyền:

$ bash -c 'echo $EUID'
1000

$ EUID=0 bash -c 'echo $EUID'
0

Nếu người dùng đã làm điều này, rõ ràng nó sẽ không dẫn đến sự leo thang đặc quyền, nhưng có thể dẫn đến các lệnh trong tập lệnh không thể thực hiện những gì họ phải làm và các tệp được tạo với chủ sở hữu sai, v.v.


1
Lưu ý: trên Solaris 5.10, /bin/id -ucho/bin/id: illegal option -- u Usage: id [-ap] [user]
jrw32982 hỗ trợ Monica

1
@ jrw32982 Bạn nên có /usr/xpg4/binsớm $PATHđể có quyền truy cập vào các tiện ích POSIX trên Solaris.
Kusalananda

1
Vấn đề là -utùy chọn idnày không phải là phổ quát và do đó, giải pháp này chỉ phổ biến với sự cảnh báo rằng phiên bản POSIX idphải xuất hiện đầu tiên trong PATH của bạn.
jrw32982 hỗ trợ Monica

1
@ jrw32982 Để tập lệnh của bạn nhận các tiện ích POSIX chính xác trên Solaris, hãy sửa đổi $PATHở đầu tập lệnh như /usr/xpg4/bintrước /bin. Nếu bạn khăng khăng sử dụng phi POSIX id, thì rõ ràng bạn sẽ phải đưa ra một giải pháp di động hơn.
Kusalananda

1
@Harry Có, do đó, tập lệnh có thể sử dụng PATH=$( getconf PATH )hoặc đặt một số đường dẫn mặc định rõ ràng khác hoặc sử dụng đường dẫn rõ ràng để gọi id.
Kusalananda

19

Tôi nghĩ những gì bạn muốn là để kiểm tra xem bạn có đặc quyền siêu người dùng hay không, nghĩa là id người dùng hiệu quả của bạn là 0.

zshbashlàm cho nó có sẵn trong $EUIDbiến, vì vậy bạn có thể làm:

if ((EUID != 0)); then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Với bất kỳ shell nào giống POSIX, bạn có thể sử dụng idlệnh tiêu chuẩn:

if [ "$(id -u)" -ne 0 ]; then
  echo >&2 "Error: script not running as root or with sudo! Exiting..."
  exit 1
fi

Lưu ý rằng tất cả id -unhoặc whoamihoặc $USERNAMEbiến trong zshsẽ giúp bạn có tên người dùng đầu tiên cho uid. Trên các hệ thống có người dùng khác có id 0, điều đó có thể không rootngay cả khi quy trình là hậu duệ của một hệ thống đã được xác thực là root.

$USERthường sẽ cung cấp cho bạn người dùng đã được xác thực, nhưng dựa vào nó khá dễ vỡ. Nó không được thiết lập bởi shell, nhưng thường được đặt bằng lệnh xác thực (như login, su(trên các hệ thống GNU / Linux, không nhất thiết phải là các hệ thống khác) sudo, sshd(ít nhất là từ openssh) ...). Không phải lúc nào cũng vậy (việc thay đổi uid không tự động đặt biến đó, nó phải được thực hiện rõ ràng bằng ứng dụng thay đổi uid) và nó cũng có thể được sửa đổi bởi một số quy trình khác trong tổ tiên của shell. $LOGNAME, với cùng một cảnh báo là đáng tin cậy hơn như được chỉ định bởi POSIX (ban đầu từ Trin 151-2)


12

Bạn có thể sử dụng $USERhoặc whoamiđể kiểm tra người dùng hiện tại.

if [[ "$USER" != "root" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

if [[ $(whoami) != "root" ]]; then
    echo "Warning: script must be run as root or with elevated privileges!"
    exit 1
fi

if [[ $(id -u) != "0" ]]; then
    echo "Error: script not running as root or with sudo! Exiting..."
    exit 1
fi

1
NP. Tôi đề nghị theo nghĩa đen chỉ cần đọc thẳng qua hướng dẫn bash [ gnu.org/software/bash/manual/bashref.html] . Đó thực sự là một sự sẵn sàng dễ dàng đáng ngạc nhiên. Đối với câu trả lời này cụ thể, tôi đề nghị tham khảo: 3.2.4.2 Conditional Constructs 3.5.4 Command Substitution
Jesse_b

9
Lệnh id -ucó hoặc không có -ntùy chọn là một cách thay thế cho việc sử dụng whoami. Không có -n và so sánh với 0 là phù hợp hơn với kiểm tra mà kernel thực sự đang làm. Tất cả các kernel quan tâm là id, không phải tên từ tệp mật khẩu.
icarus

6
Tôi tin rằng sử dụng $(id -u)là tốt hơn. Trong một số trường hợp (độc hại), $USERcó thể sai.
Stilenkevitch Basile

1
Đối với những người quan tâm đến liên kết được cung cấp bởi @Jesse_b: có một lỗi đánh máy. Nó phải là gnu.org/software/bash/manual/bashref.html
Kryten

1
Một số hệ thống không sử dụng "root" làm tên của tài khoản đặc quyền có uid 0. QNAP nảy ra như một. Vì vậy, bạn chỉ nên kiểm tra uid 0 chứ không phải tên tài khoản root.
roaima

10

Những gì bạn thực sự muốn là xác định xem bạn có quyền truy cập để thực hiện các hoạt động này hay không. Nó được coi là thực hành xấu để kiểm tra xem bạn có gốc rễ thay cho điều đó hay không.

Nếu hệ thống đã được cấu hình để cho phép người dùng không phải root sửa đổi bộ đệm và thả bộ đệm trang, tại sao người dùng đó không nên chạy tập lệnh của bạn?

Thay vào đó, bạn chỉ cần thử thao tác và thoát bằng một thông báo hữu ích nếu thất bại:

if ! ( swapoff -a && swapon -a )
then
  echo "Failed to clear swap (rerun as root?)" >&2
  exit 1
fi

if ! echo 1 > /proc/sys/vm/drop_caches
then 
  echo "Failed to free page cache (rerun as root?)" >&2
  exit 1
fi

Một người dùng không root tắt trao đổi?
Kusalananda

2
Đúng. Bạn có thể thiết lập điều này với SELinux. Tương tự như vậy, bạn có thể vô hiệu hóa một quá trình root để làm điều đó.
anh chàng kia

1
Bạn có thể không muốn exitsau khi một cái gì đó thất bại, trong trường hợp người dùng muốn làm nhiều nhất có thể với các đặc quyền hiện tại của họ. (. Nhưng đối với một hệ thống điển hình nơi mà tất cả những điều này đòi hỏi phải có gốc, xuất cảnh sẽ có nhiều hữu ích / ít ồn ào)
Peter Cordes

2
Tôi sẽ không đi xa để nói rằng đó là "thực hành xấu" để kiểm tra xem bạn có root hay không. Đặc biệt nếu đó là chính xác những gì bạn muốn biết. Tôi có quan điểm của bạn rằng tốt nhất là kiểm tra xem bạn có đủ quyền để làm những gì bạn muốn không.
Erik Bennett
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.