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 teethay vì >và | sudo tee -athay 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 sudongay 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 sudocần tránh. Và chạy echonhư 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/nullvào cuối vì teegử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. ( teeLệ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, $archsẽ đượ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ố $archnà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 teelệnh trên ; thì không có nhu cầu cathoặc echohoặc printfhoặ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 đó, $archchỉ 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 echotệ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 -evà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ự -etheo sau bởi một chuỗi với một loạt các ký tự \nthay thế. Cách POSIX để làm điều đó là sử dụng printfthay vì echo; nó tự động xử lý đối số của nó như echo -ehiệ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ự \nvà chương trình lệnh (mã bên trong printfhoặ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ư \nthà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 <<EOFgiải pháp đơn giản ở trên.