Linux: Почему sudo echo >> не работает и как писать в системные файлы правильно

catbot
19.01.2026 20:51
21 просмотров

Вы наверняка сталкивались с этой классической ошибкой новичка. Вы пытаетесь добавить строку в конфиг, но получаете Permission denied, даже используя sudo.

Как делать не надо

Допустим, мы хотим добавить репозиторий:

sudo echo "deb http://nginx.org/packages/mainline/ubuntu/ jammy nginx" >> /etc/apt/sources.list.d/nginx.list

Результат: bash: /etc/apt/sources.list.d/nginx.list: Permission denied

Почему так происходит?

Дьявол кроется в порядке выполнения команд оболочкой:

  1. Оболочка сначала обрабатывает оператор >>.
  2. Именно оболочка (bash/zsh), а не sudo, пытается открыть файл на запись.
  3. Оболочка запущена от вашего текущего пользователя (не root), поэтому прав на запись нет.

  4. Команда sudo применяется только к echo, но не к самому процессу записи в файл.

Решение: Команда tee

Используйте утилиту tee. Она читает данные из стандартного ввода и записывает их в файл, при этом выводя их на экран.

Правильный синтаксис:

echo "Hello world" | sudo tee -a /tmp/testfile.txt
  • | (пайп) передает текст команде справа.

  • sudo запускает tee с правами суперпользователя.

  • -a (append) - критически важный флаг. Он добавляет текст в конец файла. Без него tee перезапишет файл целиком!

Мини-демонстрация

Попробуем на безопасном примере:

# Пишем
echo "Hello world" | sudo tee -a /tmp/testfile.txt

# Проверяем
cat /tmp/testfile.txt

Вывод: Hello world

Продвинутый уровень: Полезные сценарии

Вот как решать более сложные задачи, с которыми echo уже не справляется.

1. Безопасное добавление нескольких строк (Here-Doc)

Если нужно записать целый блок конфига, не нужно делать десять echo. Используйте конструкцию EOF в связке с tee:

cat <<EOF | sudo tee -a /etc/sysctl.conf
# Улучшение сетевых настроек
net.ipv4.tcp_window_scaling = 1
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
EOF

Это чисто, читаемо и выполняется одной транзакцией, не перезаписывает файл.

2. Удаление или замена строк (sed)

Для удаления строк перенаправление не нужно, так как sed умеет редактировать файлы "на месте" (in-place).

Удалить конкретную строку (например, с ошибочным репозиторием):

# Удаляет все строки, содержащие "google-chrome"
sudo sed -i '/google-chrome/d' /etc/apt/sources.list

Заменить одно значение на другое:

# Заменяет "PermitRootLogin yes" на "PermitRootLogin no"
sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

Важно: Флаг -i изменяет исходный файл. Всегда делайте бэкап перед запуском!

3. Обработка данных и запись в защищённый файл (ss + awk + tee)

Иногда нужно прочитать системный файл, обработать его и записать результат в другой системный файл.

Пример: Сохранить список портов, на которых слушают сервисы.

# awk фильтрует данные, а tee записывает их с правами root
ss -tuln | awk '/LISTEN/ {print $5}' | sudo tee /var/log/active_ports.log > /dev/null

Заметка: > /dev/null в конце нужен, если вы не хотите, чтобы tee дублировал результат вам в консоль.

4. Как делать бэкап "на лету"

При изменении конфигов через sed или tee хорошим тоном считается создание резервной копии.

С sed это очень просто - добавьте расширение после флага -i:

# Создаст файл /etc/hosts.bak перед изменением
sudo sed -i.bak 's/old-ip/new-ip/' /etc/hosts

Где это пригодится?

  • Apt: Добавление репозиториев в /etc/apt/sources.list.d/

  • Config: Изменение настроек в /etc/nginx/, /etc/apache2/

  • System: Тюнинг ядра в /etc/sysctl.conf

  • Security: Добавление лимитов в /etc/security/limits.conf

  • Keys: Запись бинарных ключей: cat key.gpg | sudo tee /usr/share/keyrings/app.gpg