Я пытаюсь автоматизировать добавление источника репозитория в файл pacman.conf моей Arch, но с помощью echo
команды в моем сценарии оболочки. Однако это не так: -
sudo echo "[archlinuxfr]" >> /etc/pacman.conf
sudo echo "Server = http://repo.archlinux.fr/\$arch" >> /etc/pacman.conf
sudo echo " " >> /etc/pacman.conf
-bash: /etc/pacman.conf: Permission denied
Если я внесу изменения в /etc/pacman.conf вручную с помощью vim, выполнив
sudo vim /etc/pacman.conf
и выйдя из vim с помощью :wq
, все работает нормально, и мой pacman.conf был обновлен вручную без жалоб "Permission denied".
Почему это так? И как мне приступить sudo echo
к работе? (кстати, я sudo cat
тоже пытался использовать, но это тоже не удалось с отказом в разрешении)
Ответы:
Проблема в том, что перенаправление обрабатывается вашей исходной оболочкой, а не
sudo
. Снаряды не способны читать мысли и не знают, что именно>>
это предназначено для того,sudo
а не для него.Вам нужно:
sudo)
sudo -s
(чтобыsudo
использовать оболочку для обработки указанного перенаправления.)источник
sudo -s
(2) echo "# test" >> /etc/pacman.conf работает. Но можно ли выполнить это одной строкой?sudo -s 'echo "# test" >>/etc/pacman.conf'
это то, что я пытался вам передать.sudo -s 'echo "# test" >> /etc/pacman.conf' /bin/bash: echo "# test" >> /etc/pacman.conf: No such file or directory
вот почему я впоследствии попробовал двухэтапный ручной процесс.echo 'echo "# test" >> /etc/pacman.conf' | sudo -s
sudo
отключении конфигурации-s
? визуудо?Как объяснил @geekosaur, оболочка выполняет перенаправление перед запуском команды. Когда вы набираете это:
Текущий процесс оболочки создает свою копию, которая сначала пытается открыть
/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
:# NON-POSIX - NOT RECOMMENDED 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
в буквальные символы новой строки, прежде чем командная программа когда-либо увидит строку. Это означает, что такие строки работают с любой командой, включая простой old-e
-lessecho
:echo $'[archlinuxfr]\nServer = http://repo.archlinux.fr/$arch\n ' | sudo tee -a /etc/pacman.conf >/dev/null
Но, будучи более переносимым, чем
echo -e
, кавычки ANSI все же не являются расширением POSIX.И снова, хотя это все варианты, я предпочитаю прямое
tee <<EOF
решение, указанное выше.источник
sudo bash -c 'foo >/some/file'
у меня работает на osx :-)cat <<EOF | sudo tee -a /some/file > /dev/null ...
cat
процесс. :)http://www.innovationsts.com/blog/?p=2758
Поскольку инструкции выше не так понятны, я использую инструкции из этого сообщения в блоге. С примерами, чтобы было легче понять, что вам нужно делать.
Обратите внимание, что это вторая команда (команда gzip) в конвейере, которая вызывает ошибку. Вот тут-то и пригодится наша техника использования bash с параметром -c.
Из вывода команды ls видно, что создание сжатого файла выполнено успешно.
Второй метод похож на первый тем, что мы передаем командную строку в bash, но делаем это в конвейере через sudo.
источник
sudo bash -c 'echo "[archlinuxfr]" >> /etc/pacman.conf'
источник
ШАГ 1 создайте функцию в файле bash (
write_pacman.sh
)#!/bin/bash function write_pacman { tee -a /etc/pacman.conf > /dev/null << 'EOF' [archlinuxfr] Server = http://repo.archlinux.fr/\$arch EOF }
'EOF'
не будет интерпретировать$arch
переменную.Исходный файл bash STE2
$ source write_pacman.sh
ШАГ 3 выполнить функцию
источник
добавить файлы (sudo cat):
добавить эхо в файл (sudo echo):
echo <origin> | sudo tee -a <target-file>
(EXTRA) игнорировать вывод:
echo >origin> | sudo tee -a <target-file> >/dev/null
источник