Bạn không thể chỉ dán sudo
trước lệnh shell, bạn phải gọi shell để đánh giá lại lệnh đó (thực hiện các thao tác như mở rộng biến, mở tệp cho toán tử chuyển hướng, v.v.). Vậy đó
sudo bash -c !!
ngoại trừ việc này không hoạt động tốt, bởi vì !!
nội suy văn bản của lệnh trước đó, các ký tự đặc biệt và tất cả. Bạn cần lấy văn bản của lệnh dưới dạng một chuỗi và chuyển nó dưới dạng đối số sh
. May mắn thay, fc
nội dung của bash cho phép bạn làm điều đó¹.
sudo bash -c "$(fc -ln -1)"
Hoặc thậm chí, để chắc chắn gọi cùng một phiên bản bash hiện đang chạy:
sudo "$BASH" -c "$(fc -ln -1)"
Lưu ý rằng vì lệnh được thực thi trong một quy trình shell riêng biệt, nó thừa hưởng các biến môi trường (chỉ các biến sudo
bảo tồn, lưu giữ), chứ không phải các biến nội bộ. Tùy chọn Shell (ví dụ kshglob
) và các cài đặt khác sẽ bắt đầu từ mặc định.
Cùng một lệnh² hoạt động trong zsh và ksh, mặc dù ATT ksh93 yêu cầu cả số first
và last
số được truyền cho fc
(cũng hoạt động trong bash, zsh và pdksh / mksh):
sudo zsh -c "$(fc -ln -1)"
sudo ksh -c "$(fc -ln -1 -1)"
sudo "$0" -c "$(fc -ln -1 -1)"
Việc sử dụng $0
để chỉ định thực thi của shell đang chạy chỉ hoạt động nếu shell được gọi thông qua $ PATH và $ PATH không thay đổi hoặc thông qua một đường dẫn tuyệt đối.
Đây là một phương pháp khác trong zsh rõ ràng hơn một chút nhưng dài hơn:
sudo zsh -c $history[$[HISTCMD-1]]
Một lời cảnh báo cuối cùng: sudo
dành cho các lệnh nguy hiểm tiềm tàng. Đừng làm cho nó quá dễ sử dụng!
¹ Có một số khoảng trắng thêm ngay từ đầu và lệnh thay dải tắt dòng mới ở cuối, nhưng cú pháp của vỏ không quan tâm về điều đó.
² Tôi không nghĩ zsh hay ksh có bất cứ thứ gì như bash's $BASH
; $0
chỉ hoạt động khi đó là đường dẫn tuyệt đối hoặc khi không chứa dấu gạch chéo và đường dẫn tìm kiếm lệnh không thay đổi.
³ là một bí danh cho trong ATT ksh nhưng đó chỉ là tốt. fc
hist