Như @geekosaur đã giải thích, shell thực hiện chuyển hướng trước khi chạy lệnh. Khi bạn gõ cái này:
sudo foo >/some/file
Quy trình shell hiện tại của bạn tạo một bản sao của chính nó mà trước tiên cố gắng mở /some/file
để ghi, sau đó làm cho bộ mô tả tệp đó đầu ra tiêu chuẩn của nó và chỉ sau đó thực thi sudo
.
Nếu được phép (cấu hình sudoer thường loại trừ các trình bao đang chạy), bạn có thể làm như sau:
sudo bash -c 'foo >/some/file'
Nhưng tôi thấy một giải pháp tốt nói chung là sử dụng | sudo tee
thay vì >
và | sudo tee -a
thay vì >>
. Điều đó đặc biệt hữu ích nếu chuyển hướng là lý do duy nhất tôi cần sudo
ngay từ đầu; xét cho cùng, việc chạy các tiến trình không cần thiết với tư cách là người chủ chính là điều sudo
cần tránh. Và chạy echo
như root chỉ là ngớ ngẩn.
echo '[archlinuxfr]' | sudo tee -a /etc/pacman.conf >/dev/null
echo 'Server = http://repo.archlinux.fr/$arch' | sudo tee -a /etc/pacman.conf >/dev/null
echo ' ' | sudo tee -a /etc/pacman.conf >/dev/null
Tôi đã thêm > /dev/null
vào cuối vì tee
gửi đầu ra của nó đến cả tệp được đặt tên và đầu ra tiêu chuẩn của riêng nó, và tôi không cần phải xem nó trên thiết bị đầu cuối của mình. ( tee
Lệnh hoạt động giống như một trình kết nối "T" trong một đường ống vật lý, đó là nơi nó được đặt tên.) Và tôi đã chuyển sang dấu nháy đơn ( '
... '
) thay vì dấu ngoặc kép ( "
... "
) để mọi thứ đều theo nghĩa đen và tôi không cần phải đặt một dấu gạch chéo ngược ở phía trước của $
trong $arch
. (Nếu không có dấu ngoặc kép hoặc dấu gạch chéo ngược, $arch
sẽ được thay thế bằng giá trị của tham số shell arch
, có thể không tồn tại, trong trường hợp đó, tham số $arch
này được thay thế bằng không và chỉ biến mất.)
Vì vậy, điều đó sẽ xử lý việc ghi vào tệp dưới dạng root bằng cách sử dụng sudo
. Bây giờ là một phép phân tích dài dòng về các cách xuất văn bản chứa dòng mới trong một tập lệnh shell. :)
Đối với BLUF, như họ nói, giải pháp ưa thích của tôi là chỉ nạp một tài liệu tại đây vào sudo tee
lệnh trên ; thì không có nhu cầu cat
hoặc echo
hoặc printf
hoặc bất kỳ lệnh khác ở tất cả. Các dấu ngoặc kép đơn đã được chuyển đến phần giới thiệu sentinel <<'EOF'
, nhưng chúng có cùng tác dụng ở đó: phần thân được coi như văn bản theo nghĩa đen, do đó, $arch
chỉ còn lại
sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch
EOF
Nhưng trong khi đó là cách tôi làm, vẫn có những lựa chọn thay thế. Ở đây có một ít:
Bạn có thể gắn một echo
tệp trên mỗi dòng, nhưng nhóm tất cả chúng lại với nhau trong một vỏ con, vì vậy bạn chỉ phải thêm vào tệp một lần:
(echo '[archlinuxfr]'
echo 'Server = http://repo.archlinux.fr/$arch'
echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null
Nếu bạn thêm -e
vào echo
(và bạn đang sử dụng một trình bao hỗ trợ phần mở rộng không phải POSIX đó), bạn có thể nhúng trực tiếp dòng mới vào chuỗi bằng cách sử dụng \n
:
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Nhưng như đã nói ở trên, đó không phải là hành vi được chỉ định bởi POSIX; shell của bạn có thể chỉ lặp lại một ký tự -e
theo sau bởi một chuỗi với một loạt các ký tự \n
thay thế. Cách POSIX để làm điều đó là sử dụng printf
thay vì echo
; nó tự động xử lý đối số của nó như echo -e
hiện tại, nhưng không tự động thêm một dòng mới vào cuối, vì vậy bạn cũng phải gắn thêm một dòng ở \n
đó:
printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' |
sudo tee -a /etc/pacman.conf >/dev/null
Với một trong hai giải pháp đó, những gì lệnh nhận được dưới dạng chuỗi đối số chứa chuỗi hai ký tự \n
và chương trình lệnh (mã bên trong printf
hoặc echo
) có thể dịch nó thành một dòng mới. Trong nhiều vỏ hiện đại, bạn có tùy chọn của việc sử dụng dấu ngoặc kép ANSI $'
... '
, mà sẽ dịch các chuỗi như \n
thành đen dòng mới trước khi chương trình lệnh bao giờ nhìn thấy chuỗi. Điều đó có nghĩa là các chuỗi như vậy hoạt động với bất kỳ lệnh nào, kể cả lệnh old -e
-less đơn giản echo
:
echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Tuy nhiên, mặc dù linh hoạt hơn echo -e
, nhưng dấu ngoặc kép ANSI vẫn là một phần mở rộng không phải POSIX.
Và một lần nữa, trong khi đó là tất cả các lựa chọn, tôi thích tee <<EOF
giải pháp đơn giản ở trên.