Я пишу сценарий на bash, который автоматически добавляет PPA. Проблема в том, что если просто выполнить команду add-apt-repository ppa, то после нескольких запусков одного и того же скрипта вы получите кучу дублирующихся закомментированных строк в каждом файле списка PPA в папке /etc/apt/sources.list.d.
Одним из решений этой проблемы является проверка перед добавлением, как описано в этом вопросе/ответе.
Меня немного отталкивает большой блок кода в этом ответе. Что если мы сначала позволим им быть добавленными, а затем очистим файлы? Это выглядело бы так:
sudo apt-add-repository -y ppa:rael-gc/rvm
# remove the duplicate ppa in the files
ls /etc/apt/sources.list.d/*.list | xargs -n 1 -I {} sh -c "uniq {} | sudo tee {}"
Есть ли отрицательные стороны у вышеупомянутого подхода? Какие-нибудь возможно опасные проблемы?
Пример того, как apt-add-repository делает это:
cat /etc/apt/sources.list.d/rael-gc-ubuntu-rvm-xenial.list
deb http://ppa.launchpad.net/rael-gc/rvm/ubuntu xenial main
# deb-src http://ppa.launchpad.net/rael-gc/rvm/ubuntu xenial main
sudo apt-add-repository -y ppa:rael-gc/rvm
cat /etc/apt/sources.list.d/rael-gc-ubuntu-rvm-xenial.list
deb http://ppa.launchpad.net/rael-gc/rvm/ubuntu xenial main
# deb-src http://ppa.launchpad.net/rael-gc/rvm/ubuntu xenial main
# deb-src http://ppa.launchpad.net/rael-gc/rvm/ubuntu xenial main
Это не точно Обзор Кода, но здесь мы идем.
ls
!ls /etc/apt/sources.list.d/*.list | xargs ...
Не делайте этого. См. ссылку в заголовке раздела для объяснения почему и возможные альтернативы. Самое легкое и самое изящное решение здесь состояло бы в том, чтобы использовать оболочку globbing для генерации объектов для итерации в для цикла:
for l in /etc/apt/sources.list.d/*.list; do
uniq "$l" | sudo tee "$l"
done
Все мы знаем, что чтение файла с одной программой и перенаправление вывода назад в тот же самый файл, вероятно, приводят к пустому файлу. Бросок tee
промежуточный помогает немногому, потому что это буферизует вход некоторое время, пока это не пишет это в свой вывод, но это - деталь реализации, которая может перестать работать с различным tee
реализации и/или различные ядра. Это также перестало работать, как только размер вывода превышает размер буфера. Вместо этого необходимо использовать что-то как
uniq "$l" | sudo sponge "$l"
или возможно
sudo sed -i ... "$l"
если можно найти, что соответствующий sed сценарий делает задание.
Оба обладают дополнительным преимуществом, что они также не пишут вход в стандартный вывод, но можно подавить это с >/dev/null
так или иначе.
uniq
действительно найдите дублирующиеся исходные строки Кв.?Взгляд на sources.list(5)
, Исходные строки Кв. могут содержать несколько “компонентов”. Следующие исходные файлы эквивалентны, но не идентичны:
единственная, многокомпонентная строка:
deb http://de.archive.ubuntu.com/ubuntu/ trusty-security main restricted
несколько однокомпонентных строк:
deb http://de.archive.ubuntu.com/ubuntu/ trusty-security main
deb http://de.archive.ubuntu.com/ubuntu/ trusty-security restricted
Это должно быть очевидно это поэтому uniq
не может найти все дублирующиеся исходные строки Кв. Однако начиная с репозиториев на ppa.launchpad.net
не поддерживайте несколько компонентов, можно прожить, если Вы только используете PPAs от того сайта. Кроме того, дубликаты могут быть распространены по нескольким файлам, который повреждает этот подход полностью, если Вы не полагаетесь на факт это add-apt-repository
управляет исходными файлами несколько разумно и помещает точно один PPA в каждый файл.
В то время как возможно записать программу Bash, которая принимает многокомпонентные строки во внимание при проверке на дубликаты, было бы лучше пользоваться существующими библиотеками программного обеспечения для парсинга исходных строк Кв. вместо того, чтобы прокрутить собственное решение. Одна такая библиотека aptsources
модуль Python (упакованный в python-apt
или python3-apt
). Можно найти пример его использования в apt-remove-duplicate-source-entries (происходящий из вопроса, Как может я автоматически фиксировать W: Целевые Пакеты … настроены многократно?).