Không tìm thấy lệnh nào khi có chức năng sudo'ing từ ~ / .zshrc


10

Tôi có một chức năng trong ~/.zshrc:

findPort() {
    lsof -t -i :$1
}

Các cách gọi thông thường là findPort 3306.

Tôi muốn chạy nó với đặc quyền nâng cao. Nhưng tôi nhận được "lệnh không tìm thấy".

  git 🍔 sudo findPort 3306
sudo: findPort: command not found

Tôi cho rằng lý do là người dùng root chạy dưới dạng shell không tương tác (do đó không đề cập đến .zshrc) hoặc đề cập đến một cái khác .zshrc .

Tôi đã thấy các câu hỏi tương tự liên quan alias, nhưng không có câu hỏi liên quan đến các chức năng do người dùng xác định. Các câu trả lời cho vấn đề này liên aliasquan đến việc thêm bí danh vào ~/.zshrc:

alias sudo='nocorrect sudo '

Hoặc có lẽ:

alias sudo='sudo '

Tôi đã thử cả hai giải pháp này và vấn đề vẫn còn tồn tại (vâng, tôi đã khởi động lại vỏ).

Tôi cũng đã thử chạy sudo chshđể đảm bảo rằng vỏ gốc của tôi chạy bên dưới zsh. Không có giải pháp nào trong số này loại bỏ vấn đề "lệnh không tìm thấy".

Có cách nào để chạy các chức năng do người dùng xác định theo sudo không?


Xem thêm: unix.stackexchange.com/questions/181414/ trên (không gắn cờ vì zsh có thủ thuật riêng)
muru

Câu trả lời:


13

sudochạy lệnh trực tiếp, không qua một lớp vỏ, và thậm chí nếu nó chạy một shell để chạy lệnh đó, nó sẽ là một invocation vỏ mới, và không chỉ một mà đọc của bạn ~/.zshrc(ngay cả khi nó bắt đầu một vỏ tương tác, nó có lẽ sẽ đọc root's ~/.zshrc, không phải của bạn trừ khi bạn định cấu hình sudođể không đặt lại $HOMEbiến).

Ở đây, bạn cần nói sudođể bắt đầu một trình zshbao mới và nói rằng zshhãy đọc của bạn ~/.zshrctrước khi chạy chức năng đó:

sudo zsh -c '. $0; "$@"' ~/.zshrc findPort 3306

Hoặc là:

sudo zsh -c '. $0; findPort 3306' ~/.zshrc

Hoặc để chia sẻ các hàm zsh hiện tại của bạn với hàm mới zshđược gọi bởi sudo:

sudo zsh -c "$(functions); findPort 3306"

Mặc dù bạn có thể nhận được một danh sách arg lỗi quá dài nếu bạn có nhiều hàm được xác định (như khi sử dụng hệ thống hoàn thành). Vì vậy, bạn có thể muốn giới hạn findPortchức năng này (và mọi chức năng khác mà nó phụ thuộc vào nếu có):

sudo zsh -c "$(functions findPort); findPort 3306"

Bạn cũng có thể làm:

sudo zsh -c "(){$functions[findPort]} 3306"

Để nhúng mã của findPorthàm trong một hàm ẩn danh mà bạn truyền đối số 3306. Hoặc thậm chí:

sudo zsh -c "$functions[findPort]" findPort 3306

(tập lệnh nội tuyến được truyền vào -c phần thân của hàm).

Bạn có thể sử dụng chức năng trợ giúp như:

zsudo() sudo zsh -c "$functions[$1]" "$@"

Không được dùng:

sdo () {sudo zsh -c "() {$ Hàm [$ 1]} $ {@: 2}"}

Khi các đối số sdosẽ trải qua một mức phân tích shell khác. Đối chiếu:

$ e() echo "$@"
$ sdo e 'tname;uname'
tname
Linux
$ zsudo e 'tname;uname'
tname;uname

Tôi cần một giải pháp ngắn như gõ sudo. Tôi đã có thể điều chỉnh giải pháp chức năng ẩn danh của bạn để làm việc đó. Tôi đã thêm chức năng sau vào chức năng của mình ~/.zshrc, đây là chức năng để chạy các chức năng khác với các đặc quyền nâng cao:sdo() { sudo zsh -c "(){$functions[$1]} ${@:2}" }
Birchlabs

1
@Birchlabs, xem chỉnh sửa
Stéphane Chazelas

Cảm ơn; Tôi đã cập nhật câu trả lời của mình để sử dụng lối tắt mới hơn mà bạn đề xuất.
Birchlabs

Thêm định nghĩa hàm vào tập lệnh được thực thi thông qua sudo là thông minh. Nhưng không đủ thông minh nếu chức năng đó sử dụng chức năng khác (tự động tải hoặc không).
Damien Flires

3

Một giải pháp rất đơn giản đối với tôi là gọi trình bao tương tác bằng cách sử dụng sudo -s, nó dường như hoạt động trên phiên bản zsh (5.2) kèm theo macOS của tôi. Điều này cung cấp cho tôi các chức năng từ của tôi ~/.zshrc.

Từ trang sudo, không thực sự gợi ý về hành vi này:

-s, --shell
Chạy shell được chỉ định bởi biến môi trường SHELL nếu nó được đặt hoặc shell được chỉ định bởi mục nhập cơ sở dữ liệu mật khẩu của người dùng. Nếu một lệnh được chỉ định, nó được chuyển đến shell để thực thi thông qua tùy chọn -c của shell. Nếu không có lệnh nào được chỉ định, shell tương tác được thực thi.

Tôi không chắc trường hợp sử dụng của bạn là gì, nhưng tôi nghi ngờ bạn đang tìm kiếm một giải pháp tương tác.


Điều này thực sự làm việc. Mặc dù nó không hoàn toàn là quy trình công việc tôi có trong tâm trí. Mong muốn của tôi là duy trì một dấu nhắc như người dùng thông thường của tôi và chỉ nâng cao chức năng myFuncdo người dùng xác định bằng cách nhập sudo myFunc- giống như cách tôi sẽ nâng bất kỳ quy trình nào (như sudo rm -rf .). Giải pháp này nâng toàn bộ lời nhắc của tôi và tất cả các chức năng trong tương lai, cũng như thay đổi người dùng của tôi cho tất cả các chức năng trong tương lai - đó là một chút quá mức cần thiết.
Birchlabs

Các sudo -slệnh sẽ khởi chạy một thể hiện của lớp vỏ của bạn như là superuser. Nếu bạn thực hiện lệnh đó một cách tương tác, shell mới của bạn sẽ tương tác. Nhưng lệnh sudo -s findPort 3306sẽ chạy lệnh findPort 3306trong shell của bạn dưới dạng superuser sau đó thoát với mã trạng thái của lệnh đó.
Damien Flament

2

Tôi đã có thể tạo ra một tốc có thể tái sử dụng cho một trong những giải pháp được mô tả trong câu trả lời của Stéphane Chazelas . [Chỉnh sửa: Stéphane đã lặp lại trên lối tắt ban đầu tôi đề xuất; mã được mô tả ở đây là một phiên bản mới hơn, do anh ấy tạo ra]

Đặt cái này vào ~/.zshrc:

sdo() sudo zsh -c "$functions[$1]" "$@"

Bây giờ bạn có thể sử dụng sdolàm "chỉ sudocho các chức năng do người dùng xác định".

Để xác nhận rằng nó sdohoạt động: bạn có thể dùng thử trên một chức năng do người dùng xác định in tên người dùng của bạn.

 birch@server ~/ 🍔 test() whoami

 birch@server ~/ 🍔 test
birch

 birch@server ~/ 🍔 sdo test
root

0

Điều này dường như làm việc cho tôi:

function sudo (){
  args="$@"
  /run/wrappers/bin/sudo -u "$USER" zsh -i -c "$args"
}
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.