Как объяснил @geekosaur, оболочка выполняет перенаправление перед запуском команды. Когда вы набираете это:
sudo foo >/some/file
Текущий процесс оболочки создает свою копию, которая сначала пытается открыть /some/fileдля записи, затем делает этот файловый дескриптор своим стандартным выводом и только после этого выполняется sudo.
Если вам разрешено (конфигурации sudoer часто не позволяют запускать оболочки), вы можете сделать что-то вроде этого:
sudo bash -c 'foo >/some/file'
Но я считаю, что в целом хорошее решение - использовать | sudo teeвместо >и | sudo tee -aвместо >>. Это особенно полезно, если перенаправление - единственная причина, по которой мне sudoв первую очередь нужно ; в конце концов, ненужный запуск процессов от имени root - это именно то, чего sudoнужно избегать. А запускать echoпод root просто глупо.
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действует как Т-образный соединитель в физическом конвейере, отсюда и получила свое название.) И я переключился на одинарные кавычки ( '... ') вместо двойных ( "... "), так что все было буквально, и я не нужно ставить обратную косую черту перед $in $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в буквальные символы новой строки, прежде чем командная программа когда-либо увидит строку. Это означает, что такие строки работают с любой командой, включая простой old -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решение, указанное выше.