Команда echo используется для вывода передаваемой ей строки. По умолчанию показывает строку на экране, но при перенаправлении вывода, например с помощью >> или > может, соответственно, дописывать строку в файл или полностью перезаписывать его этой строкой.
Но что если нам нужно дописать строку в файл требующих повышенных привилегий примерно следующей командой:
sudo echo "что-нибудь" >> /etc/файл_требующий_повышенных_привилегий
Это довольно распространённая ситуация, когда нужно добавить что-то в файл /etc/hosts или подобный. Кажется, что это довольно простая конструкция: перед echo добавлена sudo, которая позволяет выполнять команды от других пользователей, в данном случае от root (смотрите также Что такое sudo).
То есть команда должна выполняться с повышенными привилегиями, что должно дать права на запись в файл. Но в этом случае ни > , ни >> не получится использовать, в том числе как root. И будет выведена ошибка вида:
bash: /etc/file: Отказано в доступе
Нам на помощь может прийти команда tee. Используйте её с опциями --append или -a — это важно, без этих опций файл будет полностью перезаписан. Пример:
echo 'новая строка' | sudo tee --append /etc/apt/sources.list
Приведённая команда допишет новую строку в существующий файл.
Но особенность команды tee в том, что она не только допишет файл, но ещё и выведет добавленную строку в консоль. Если вы не хотите, чтобы данные вновь возвращались в консоль, то сделайте редирект вывода на /dev/null.
Пример:
echo 'новая строка' | sudo tee --append /etc/apt/sources.list > /dev/null
Это будет работать аналогичным образом, но на экран не будет выведена 'новая строка'.
Ещё один вариант использования echo для записи или добавления в файл от имени администратора:
sudo sh -c "echo 'something' >> /etc/privilegedfile"
У этого варианта есть своя специфика. Во-первых, команда echo работает от рута, следовательно, оказывается в его рабочем окружении. В большинстве ситуаций это неважно, но если вы хотите использовать эту команду с переменными среды $EVN_VARIBLE (например, $PATH или $USER), то вы можете получить неожиданный результат — будет взята переменная среды пользователя root, а не вашего текущего пользователя.
Ещё в команде используются и одинарные и двойные кавычки, это означает, что если в строке, которую вы добавляете в файл, также есть кавычки, то они должны быть экранированы обратными слэшами.
Кстати, просто к слову, если вам нужно дописать большие блоки, то вы можете использовать команду cat и heredoc:
sudo bash -c "cat <<EOIPFW >> /etc/ipfw.conf <?xml version=\"1.0\" encoding=\"UTF-8\"?> <plist version=\"1.0\"> <dict> <key>Label</key> <string>com.company.ipfw</string> <key>Program</key> <string>/sbin/ipfw</string> <key>ProgramArguments</key> <array> <string>/sbin/ipfw</string> <string>-q</string> <string>/etc/ipfw.conf</string> </array> <key>RunAtLoad</key> <true></true> </dict> </plist> EOIPFW"
И ещё один пример для тех, кто любит обстоятельно настраивать свою систему и делать пользовательский тюнинг, в том числе с добавлением своих собственных комплексных команд. Добавьте в файл ~/.bashrc следующую функцию:
sudoe() { if ([[ "$1" == "-a" ]] || [[ "$1" == "--no-append" ]]); then shift &>/dev/null || local failed=1 else local append="--append" fi while [[ $failed -ne 1 ]]; do if [[ -t 0 ]]; then text="$1"; shift &>/dev/null || break else text="$(cat <&0)" fi [[ -z "$1" ]] && break echo "$text" | sudo tee $append "$1" >/dev/null; return $? done echo "Usage: $0 [-a|--no-append] [text] <file>"; return 1 }
Теперь вы сможете использовать новую команду sudoe следующим образом:
sudoe 'новая строка' /etc/apt/sources.list
По умолчанию установлена опция --append — она означает дописывать существующий файл. Если вы хотите перезаписать, то есть удалить текущее содержимое и записать только новую строку, то используйте с этой командой опции -a или --no-append.
И ещё парочка экзотических методов. В пакете moreutils есть утилита sponge, она позволяет дописать строку в привилегированный файл без необходимости делать редирект вывода (не нужно прятать шум от tee):
echo 'Добавить эту строку' | sudo sponge -a /etc/привилегированный_файл
И ещё один способ это использование sed -i с $ a. Вы можете добавить строку командой следующего вида:
sudo sed -i "\$ a Строка для добавления" /etc/привилегированный_файл
Объяснение опций sed:
- -i - в месте
- $ - последняя строка
- a - добавить
С помощью sed можно добавлять весьма сложные строки, содержащие переменные и специальные символы. Допустим нам нужно добавить $NEW_HOST с $NEW_IP в /etc/hosts:
sudo sed -i "\$ a $NEW_IP\t\t$NEW_HOST.domain.local\t$NEW_HOST" /etc/hosts