Як пояснив @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за яким слідує рядок із набором літералів \ns. 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рішенню вище.