Используйте sed (или awk), чтобы добавить запись в fstab, когда найдено совпадение

Мне нужно отредактировать строки в /etc/fstab и добавить/изменить fsoptions в строки, где найден соответствующий том. Я пытался использовать sed и помещать найденные блоки в регистры, чтобы поместить их обратно, но нахожу это проблемой. Возможно, sed — не лучший инструмент — я пробовал augeas, и пока он добавляется, он не заменялся, а также терпел неудачу, если совпадающая строка не была найдена, но ее нужно было добавить (например, была видна только с помощью команды «mount», такой как / dev /шм).

например, если в /etc/fstab есть строка:

/dev/mapper/VolGroup1-tmp /tmp                    xfs     dev,nosuid 0 0

я хочу сделать это

/dev/mapper/VolGroup1-tmp /tmp                    xfs     nodev,nosuid,noexec 0 0
  1. Обратите внимание, что группа томов в первом блоке может иметь любое имя.
  2. КЛЮЧЕВОЕ СЛОВО в строке (в этом примере) будет /tmp (но будьте осторожны, чтобы не совпадать с /var/tmp, если не указано иное)
  3. Файловая система может быть любой (не обязательно xfs).
  4. Любой присутствующий «exec» или «suid» (например) необходимо заменить, если он присутствует, и даже если нет, вставить «noexec» или «nosuid».
  5. Конечный «0 0» необходимо сохранить.

Я уверен, что мне не хватает простого способа сделать это. Использование 'mount -o remount,noexec /tmp' не записывает в /etc/fstab, поэтому я думаю, что единственный способ сделать изменения постоянными - это напрямую отредактировать /etc/fstab?

На самом деле я собираюсь обернуть решение в Puppet. Приведенный ниже пример augeas терпит неудачу в двух отношениях:

  • если строка (например, /dev/shm) не существует в /etc/fstab, она не работает

  • если строка существует и имеет «exec», она добавляет «noexec», но также оставляет exec

      augeas{ "/etc/fstab - ${opt} on ${mount}":
    context => '/files/etc/fstab',
    changes => [
      "ins opt after /files/etc/fstab/*[file = '${mount}']/opt[last()]",
      "set *[file = '${mount}']/opt[last()] ${opt}",
    ],
    onlyif  => "match *[file = '${mount}']/opt[. = '${opt}'] size == 0",
    notify  => Exec["remount_${mount}_${opt}"],
    

    }


person xit    schedule 04.10.2019    source источник
comment
Рассмотрите возможность использования ресурсов Mount вместо Augeas или странных Exec. Конечно, это следует другой парадигме: предписывающей вместо реактивной. Первый тип гораздо лучше подходит для централизованного управления инфраструктурой, такой как Puppet.   -  person John Bollinger    schedule 04.10.2019
comment
Это вариант, однако я хочу просто добавить любые fsoptions, а не устанавливать их полностью или устанавливать fstype. Вид поиска и замены или создания, если не существует. Кажется, что должно быть просто поймать строки и выполнить вставку или замену, но пока augeas (каким бы ужасным он ни был) кажется наиболее близким методом. Отсюда мои поиски «sed foo».   -  person xit    schedule 04.10.2019
comment
Как я уже сказал: предписывающая парадигма. Согласно рекомендациям, установка всех параметров — это то, что вы должны делать. Что проще, тоже просто подливка. Тем не менее, решение на основе sed должно быть возможным. Я посмотрю что я могу сделать.   -  person John Bollinger    schedule 05.10.2019
comment
Я согласен с вами, однако проблема в том, что первая строка (fsname) может быть любой, как и fstype. Я также хочу сохранить существующие fsoptions, которые не конфликтуют с новыми желаемыми настройками. Если вы можете придумать способ сделать это с помощью Puppet Mount или другого метода, я согласен, что это было бы лучше.   -  person xit    schedule 05.10.2019
comment
В качестве альтернативы было бы полезно некоторое усовершенствование блока Puppet Augeus.   -  person xit    schedule 05.10.2019


Ответы (1)


Я уверен, что мне не хватает простого способа сделать это. Использование 'mount -o remount,noexec /tmp' не записывает в /etc/fstab, поэтому я думаю, что единственный способ сделать изменения постоянными - это напрямую отредактировать /etc/fstab?

Нет специального интерфейса командной строки для изменения записей монтирования в /etc/fstab, если вы это имеете в виду. Редактирование файла вручную с помощью текстового редактора — это старый способ.

Как я упоминал в комментариях, стандартный подход Puppet к работе с записями монтирования — через Mount ресурсы. Пока я пишу ответ, я повторяю, что с их помощью вы должны выполнять свою работу.

Вы возражали в комментариях, что

проблема в том, что первая строка (fsname) может быть любой, как и fstype. Я также хочу сохранить существующие fsoptions, которые не конфликтуют с новыми желаемыми настройками.

В этом это проблема, но не в том смысле, в каком, как я думаю, вы имеете в виду. Вы находитесь в затруднительном положении, потому что пытаетесь приспособить несколько органов власти к этому аспекту конфигураций ваших узлов. Наилучшей практикой было бы полностью возложить ответственность за увеличение интереса на Puppet. У него более чем достаточно гибкости, чтобы обеспечить различные конфигурации монтирования на разных машинах.

Однако, если вы решили использовать Puppet таким образом, то это можно сделать. Но хотя задачу относительно легко описать, детали делают ее относительно сложной. Подход на основе sed возможен, но он будет сравнительно длинным и чрезвычайно загадочным. Лучшим инструментом командной строки для основной работы будет awk, и, в частности, этот скрипт awk выполнит работу для случая, который вы представили:

$1 ~ /^#.*/ || $2 != "/tmp" {print; next}
$4 ~ /.*nosuid.*/ && $4 ~ /.*noexec.*/ {print; next}
{
  split($4, opts, ",")
  printf "%s    %s  %s  ", $1, $2, $3
  for (i in opts) {
    if (opts[i] !~ /(no)?(exec|suid)/) {
      printf "%s,", opts[i]
    }
  }
  printf "noexec,nosuid %s %s\n", $5, $6
}

Превращение этого в ресурс Exec и внесение любых других изменений в соответствии с вашими конкретными требованиями остается в качестве упражнения.

person John Bollinger    schedule 05.10.2019