Thực hiện một dòng lệnh với một sudo


21

Ví dụ: nếu tôi muốn tạo một tệp và nhập văn bản trong một dòng, tôi có thể chuyển hướng đầu ra thành một tệp với việc sử dụng >toán tử:

echo "something" > /path/foobar

nhưng nếu tôi không có quyền truy cập vào thư mục /path/và cần quyền riêng tư sudo, làm thế nào tôi có thể đạt được lệnh này giống như một người dùng bình thường có quyền sudo?

Tôi đã thử

sudo echo "something" > /path/foobar

nhưng điều đó không hiệu quả, vì sudo chỉ được tính cho editchứ không phải cho phần bên phải
của>

Chắc chắn, tôi có thể trở thành root trước với sudo suhoặc sử dụng teethay thế:

echo "something" | sudo tee /path/foobar

Nhưng tôi muốn tìm một giải pháp nơi tôi có thể làm việc với dòng cuối cùng là thay thế thông qua

sudo !!

Không có cách nào để "tái chế" dòng cuối cùng và chỉ cần thêm sudoở phía trước?



Đây không phải là một bản sao. Tôi trích xuất Qe bỏng thật và thay đổi tiêu đề. Bây giờ nó là thứ tôi thực sự đang tìm kiếm
rubo77

Nó chắc chắn một bản sao, nhưng bây giờ nó hơi khác. Có vẻ như tôi viết lại câu hỏi theo câu trả lời của Boogy, điều đó tốt - đó là một câu trả lời hay. Tôi đã rút lại phiếu bầu gần của mình, nhưng vẫn không thể tránh khỏi (mọi người thường bỏ phiếu tự động một khi câu hỏi nằm trong hàng đợi mà không chú ý đến vấn đề này): giải quyết một bình luận @goldilocks khi nó bị đóng và tôi sẽ bỏ phiếu để mở lại . Bạn cũng có thể biện hộ cho trường hợp của bạn trong cuộc trò chuyện một khi điều đó xảy ra.
goldilocks

Câu trả lời:


13

Bạn không thể chỉ dán sudotrướ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, fcnộ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 sudobả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ố firstlastsố đượ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: sudodà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; $0chỉ 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. fchist


9

Nếu bạn muốn làm lại lệnh tương tự với sudo !! sau khi thực hiện một lệnh như thế này:

echo "something">/path/file

Bạn sử dụng cú pháp thay thế toàn cục để gọi lại lệnh:

!!:gs/>/|sudo tee -a /

Sử dụng một khoảng trắng sau tham số -a .

Điều này tương đương với sudo !! nhưng giúp bạn bỏ qua các hạn chế sudo cho <và>. Vì sudo không cho phép bạn sử dụng [<,>].


Để bỏ qua các hạn chế sudo nói chung cho các chuyển hướng, bạn có thể sử dụng nó như thế này:

echo "something" | sudo tee myfile

Lệnh tee sẽ cho phép bạn đọc từ đầu vào tiêu chuẩn và ghi vào đầu ra và tệp tiêu chuẩn

Nếu bạn muốn lặp lại lệnh và nối một văn bản vào tệp, lệnh tee có tùy chọn -a để nối thêm. Vì vậy, bạn có thể nhớ lại lệnh với

sudo !!

và văn bản sẽ được thêm vào trong tập tin

thí dụ:

echo "something" | sudo tee -a /path/file
sudo !!

giải pháp tốt đẹp, nhưng một chút khó khăn để ghi nhớ. Làm thế nào tôi có thể tạo bí danh cho một lệnh bằng cách sử dụng !! để nhớ lại lệnh cuối cùng ?
rubo77

-athực sự cần thiết? >sẽ ghi đè lên một tập tin, tee -asẽ nối thêm, đó là>>
rubo77

3

Nó dường như đơn giản như sudo sh -c "!!":

$ cd /
$ echo hello > foo
bash: foo: Permission denied
$ sudo sh -c "!!"
sudo sh -c "echo hello > foo"
$ ls -l foo
-rw-r--r-- 1 root root 6 Jun 20 16:21 foo

3
Nếu lệnh được sử dụng dấu ngoặc kép, điều này không nhất thiết phải tương đương. Xem xét echo "foo bar"cái nào sẽ trở thành sh -c "echo "foo bar""cái mà sẽ chỉ in foothay vì foo bar.
trời ơi

sudo sh -c '!!'Thay vào đó tôi đã thử nếu lệnh của bạn nhưng điều đó cũng không hiệu quả
rubo77

Vậy thì nếu lệnh của bạn sử dụng cả dấu ngoặc đơn và dấu ngoặc kép thì sao? Hoặc báo giá kép và mở rộng biến? Nếu người dùng đã làm: a=bvà sau echo "$a" >fileđó sudo sh -c '!!'nó sẽ mở rộng sang sudo sh -c 'echo $a >file'đó sẽ in một dòng trống thay vì bvào file.
trời ơi

Vì vậy, có lẽ có một giải pháp thậm chí tốt hơn bằng cách nào đó?
rubo77

1
Tôi không nghĩ có bất kỳ giải pháp nào sẽ hoạt động 100% mà không cần bạn phải sửa đổi lệnh. Sử dụng sudođể lấy shell gốc và sau đó sao chép và dán lệnh vào đó sẽ là gần nhất, nhưng không thành công nếu lệnh được dự kiến ​​sẽ sử dụng các biến được đặt trong shell không phải root của bạn. Sử dụng sudo sh -c "!!"hoạt động tốt cho các lệnh đơn giản, nhưng đầy đủ cho các lệnh phức tạp. Tôi nghĩ rằng lời khuyên tốt nhất là đừng hy vọng rằng có một số lệnh sẽ hoạt động 100% thời gian - tìm hiểu một số giải pháp có thể và áp dụng từng giải pháp khi phù hợp nhất.
trời ơi
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.