Jak wyjaśnił @geekosaur, powłoka dokonuje przekierowania przed uruchomieniem polecenia. Kiedy wpiszesz to:
sudo foo >/some/file
Twój bieżący proces powłoki tworzy kopię samego siebie, która najpierw próbuje otworzyć się /some/filedo zapisu, następnie ustawia ten deskryptor pliku jako standardowe wyjście, a dopiero potem wykonuje sudo.
Jeśli masz pozwolenie (konfiguracje sudoer często uniemożliwiają uruchamianie powłok), możesz zrobić coś takiego:
sudo bash -c 'foo >/some/file'
Ale ogólnie uważam, że dobrym rozwiązaniem jest użycie | sudo teezamiast >i | sudo tee -azamiast >>. Jest to szczególnie przydatne, jeśli przekierowanie jest jedynym powodem, którego potrzebuję sudow pierwszej kolejności; w końcu niepotrzebne uruchamianie procesów jako root jest właśnie tym, czego sudonależy unikać. A bieganie echojako root jest po prostu głupie.
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
Dodałem > /dev/nullna końcu, ponieważ teewysyła swoje dane wyjściowe zarówno do wymienionego pliku, jak i na swoje własne standardowe wyjście, i nie muszę go widzieć na moim terminalu. ( teePolecenie działa jak łącznik "T" w fizycznym potoku, skąd bierze swoją nazwę.) I przełączyłem się na pojedyncze cudzysłowy ( '... ') zamiast podwójnych ( "... "), więc wszystko jest dosłowne i ja nie trzeba było umieszczać odwrotnego ukośnika przed $in $arch. (Bez cudzysłowów lub ukośnika odwrotnego $archzostałby zastąpiony wartością parametru powłoki arch, który prawdopodobnie nie istnieje, w takim przypadku $archjest zastępowany przez nic i po prostu znika).
To zajmuje się zapisywaniem do plików jako root przy użyciu sudo. Teraz długa dygresja na temat sposobów wyprowadzania tekstu zawierającego znak nowej linii w skrypcie powłoki. :)
Dla BLUF, jak mówią, moim preferowanym rozwiązaniem byłoby po prostu wprowadzenie dokumentu tutaj do powyższego sudo teepolecenia; wtedy nie ma potrzeby catlub echolub printflub innych komend w ogóle. Pojedyncze cudzysłowy przeniosły się do wprowadzenia wartowniczego <<'EOF', ale tam mają ten sam efekt: treść jest traktowana jako tekst dosłowny, więc $archpozostaje w spokoju:
sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch
EOF
Ale chociaż tak bym to zrobił, są alternatywy. Tu jest kilka:
Możesz trzymać się jednego w echokażdym wierszu, ale zgrupować je wszystkie razem w podpowłoce, więc wystarczy dołączyć do pliku tylko raz:
(echo '[archlinuxfr]'
echo 'Server = http://repo.archlinux.fr/$arch'
echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null
Jeśli dodasz -edo echo(i używasz powłoki, która obsługuje to rozszerzenie inne niż POSIX), możesz osadzić znaki nowej linii bezpośrednio w ciągu za pomocą \n:
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Ale jak powiedziano powyżej, nie jest to zachowanie określone w standardzie POSIX; Twoja powłoka może zamiast tego powtórzyć literał, -ea po nim ciąg znaków zawierający kilka literałów \ns. Sposób zgodny z POSIX polega na używaniu printfzamiast echo; automatycznie traktuje swój argument tak jak echo -erobi, ale nie dodaje automatycznie nowej linii na końcu, więc musisz też wstawić \ntam dodatkowy :
printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' |
sudo tee -a /etc/pacman.conf >/dev/null
W przypadku każdego z tych rozwiązań to, co polecenie otrzymuje jako ciąg argumentu, zawiera sekwencję dwóch znaków \n, a sam program poleceń (kod wewnątrz printflub echo) musi przetłumaczyć to na znak nowej linii. W wielu współczesnych muszli, masz możliwość korzystania cytaty ANSI $'... ', co przełoży sekwencje jak \njęzyk dosłownych nowej linii zanim program komenda kiedykolwiek widzi ciąg. Oznacza to, że takie ciągi działają z każdym poleceniem, w tym zwykłym starym- -ebez echo:
echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Ale, choć bardziej przenośne niż echo -e, cudzysłowy ANSI nadal są rozszerzeniem innym niż POSIX.
I znowu, chociaż to wszystkie opcje, wolę proste tee <<EOFrozwiązanie powyżej.