Як пояснив @geekosaur, оболонка робить переспрямування перед запуском команди. Коли ви вводите це:
sudo foo >/some/file
Ваш поточний процес оболонки робить копію себе, яка спочатку намагається відкрити /some/file
для запису, потім робить цей дескриптор файлу своїм стандартним висновком і лише потім виконує sudo
.
Якщо вам це дозволено (конфігурації sudoer часто виключають запущені оболонки), ви можете зробити щось подібне:
sudo bash -c 'foo >/some/file'
Але я вважаю, що загальним хорошим рішенням є використання | sudo tee
замість >
і | sudo tee -a
замість >>
. Це особливо корисно, якщо переспрямування є єдиною причиною, яка мені sudo
перш за все потрібна ; зрештою, непотрібне запуск процесів як root - це саме те, що sudo
було створено, щоб уникнути. А працювати echo
від імені коріння просто безглуздо.
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
Я додав > /dev/null
наприкінці, оскільки tee
надсилає свої результати як до названого файлу, так і до власного стандартного виводу, і мені не потрібно бачити це на своєму терміналі. ( tee
Команда діє як роз'єм "T" у фізичному конвеєрі, де вона і отримала свою назву.) І я перейшов до одинарних лапок ( '
... '
) замість подвійних ( "
... "
), щоб все було буквально, і я не повинні поставити зворотну косу риску перед $
дюйма $arch
. (Без лапок або зворотної косої риси $arch
замінено значення параметра оболонки arch
, яке, ймовірно, не існує, і в цьому випадку $arch
замінено нічим і просто зникає.)
Отже, це дбає про запис у файли з використанням root sudo
. Тепер для тривалого відступу щодо способів виведення тексту, що містить новий рядок, у сценарії оболонки. :)
Для BLUF, як то кажуть, моїм улюбленим рішенням було б просто подати тут-документ у вищевказану sudo tee
команду; тоді немає необхідності в cat
або echo
або printf
взагалі в будь-яких інших командах. Поодинокі лапки перейшли до вступу до сторожового <<'EOF'
, але там вони мають однаковий ефект: тіло трактується як буквальний текст, тому $arch
залишається в спокої:
sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[archlinuxfr]
Server = http://repo.archlinux.fr/$arch
EOF
Але хоча я б так це зробив, є альтернативи. Ось декілька:
Ви можете дотримуватися одного echo
в рядку, але згрупувати їх усіх у підшелудку, тому вам потрібно додати до файлу лише один раз:
(echo '[archlinuxfr]'
echo 'Server = http://repo.archlinux.fr/$arch'
echo ' ') | sudo tee -a /etc/pacman.conf >/dev/null
Якщо ви додасте -e
до echo
(і ви використовуєте оболонку, яка підтримує це розширення, що не є POSIX), ви можете вбудувати нові рядки безпосередньо в рядок, використовуючи \n
:
echo -e '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Але, як сказано вище, це не поведінка, визначена POSIX; ваша оболонка може просто повторити літерал, -e
за яким слідує рядок із набором літералів \n
s. POSIX-спосіб зробити це - використовувати printf
замість echo
; він автоматично обробляє свій аргумент, як echo -e
це робить, але автоматично не додає новий рядок в кінці, тому вам також доведеться вставити додатковий рядок \n
:
printf '[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n \n' |
sudo tee -a /etc/pacman.conf >/dev/null
З будь-яким із цих рішень, що команда отримує як рядок аргументу, містить двосимвольну послідовність \n
, і сама програма команд (код всередині printf
або echo
) переводить це в новий рядок. У багатьох сучасних оболонках у вас є можливість використовувати ANSI лапки $'
... '
, які перетворюватимуть послідовності, як-от \n
у буквальні нові рядки, перш ніж командна програма коли-небудь побачить рядок. Це означає, що такі рядки працюють із будь-якою командою, включаючи звичайний старий -e
-less echo
:
echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' |
sudo tee -a /etc/pacman.conf >/dev/null
Але, хоча echo -e
котирування ANSI є більш портативними , вони все ще не є розширенням POSIX.
І знову ж таки, хоча це всі варіанти, я віддаю перевагу прямому tee <<EOF
рішенню вище.