1. bash / Говнокод #19282

    −57

    1. 1
    yum check | grep 'duplicate with' | awk '{ print $6 }' | xargs -I{} yum -y remove {}

    Брат умер.

    Запостил: wvxvw, 10 Января 2016

    Комментарии (50) RSS

    • -y remove - зло.
      Ответить
      • Четкий поцык одобряет

        Как -y remove, сука!
        Ответить
    • редхато-проблемы.

      погуглил ошибку - нашёл кучи страдающих. сложно поверить что рх так ихний пакет манагер и не пофиксил. и это уже блин как минимум 20 лет народ страдает. но я слышал что они его опять уже меняют. проще поменять чем пофиксить.

      ЗЫ (из 2010 года) https://www.ogre.com/node/369 :

      There seems to be a command to do this, package-cleanup has an option for it. E.g.

      $ package-cleanup --cleandupes

      However, testing this command on a second box having the same problem gave bad results, it seems to have uninstalled the "real" packages too.

      поэтому я с дебьяновых систем и не слажу.

      ЗЗЫ не, похоже что репорт 2010 года не так сильно и устарел: http://forums.fedoraforum.org/showthread.php?t=296884
      Ответить
      • > проще поменять чем пофиксить
        Это же краеугольный камень линуксового опенсорса!
        Зачем чинить старые скучные баги, если можно просто переписать всё с нуля, с новыми, интересными багами.
        Ответить
        • меня в свое время (когда с рх на дебьян пересаживался) просто бесило что на рх форумах народ dpkg/apt просто поливал.

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

          я начитавшись - но и настрадавшись - пересаживал системы на дебьян с легким страхом (и хез что апдейты/этц будут вечность занимать!) который испарился уже через пару часов, потому что этот кривой любительский dpkg/apt по сравнению с идеалом практик программирования rpm просто блин летал.

          PS уже больше 15 лет на дебьяне - еще не разу битой базы пакетов не видел. на рх - страдания c rpm базой до сих пор случаются. и то что dpkg/apt до сих пор работают быстрее, говорит много о тех криворуких кто rpm/yum/dnf пишут.
          Ответить
          • Мне после долгих курений Debian Policy Manual многое стало казаться логичным, но пакетирование в целом, конечно - тема адовая. К apt-get/-cache/itude претензий практически никогда не было, разве что не нравится, что столько разных команд надо запоминать, нет единой удобной точки входа. Ну и apt-file иногда себя странновато ведёт.
            Ответить
            • Для ценителей единой точки входа есть wajig. Он пытается вообще весь дебиан в один скрипт завернуть.
              Ответить
            • в новых версиях есть (пока вроде все еще экспериментальный) `apt` (вот так буквально комманда и называется.)

              в официальном релизе дебьяна ее вроде еще нет, но в бубунтах начиная с 14.04 она есть.

              попробуй man 8 apt
              Ответить
          • > апдейты/этц будут вечность занимать!
            gentoo-аутисты долгих установок не боятся
            // в своё время пришлось свалить с дебиана, поскольку мейнтейнеры некоторых узкоспециальных пакетов были немного неадекватны в смысле флагов сборки, а на gentoo есть muh freedums
            Ответить
            • > свалить с дебиана

              Вместо того, чтобы собрать пару пакетов подсибя с нужными флажками, собирать вообще всё и увеличивать энтропию? Да вы упоролись, сударь.
              Ответить
              • а где лежит официальный мануал как под дебьяном пакет с другими флагами перекомпилить?

                мне по работе раз надо было, но там похоже от версии к версии тонкие мелочи меняются. или не меняются. хез - все неофициальные объяснения какие нагуглил слегка кривоваты и устарели. а официальной доки я так не нашел, почему и забил.
                Ответить
                • Ну если совсем по хардкору - можно самому запилить debian-скрипты для сборки пакетов (rules, changelog, etc.) из исходников. У нас это на поток поставлено, почти вся метаинфа генерится, поэтому мы делаем именно так.

                  Если хочется просто флажки поменять единоразово, можно распаковать сорс-пакет, пропатчить debian/rules и собрать новые бинари:
                  https://raphaelhertzog.com/2010/12/15/howto-to-rebuild-debian-packages/
                  Ответить
                  • > https://raphaelhertzog.com/2010/12/15/howto-to-rebuild-debian-packages/

                    а как с chroot'ом?
                    Ответить
                    • > а как с chroot'ом?

                      У нас для этого тоже свой велик есть, а общепринятое решение - это pbuilder
                      https://wiki.ubuntu.com/PbuilderHowto
                      Ответить
                      • выглядит как то очень просто: нажми на кнопку, получишь результат. настораживает :)
                        Ответить
                  • лол, а в source-based это меняется раз и навсегда в одном файле
                    и дальше работает компьютер, а не человек
                    Ответить
                    • > лол, а в source-based это меняется раз и навсегда в одном файле

                      Да, рассказывайте мне, как это удобно.
                      Я трижды ломал генту пересборкой мира, желания снова пробовать нету.
                      Ответить
                      • с генту (по крайней мере раньше) был прикольный конфликт: они поддерживают древнее и/или экзотическое железо, на котором генту пользоваться просто не возможно. я как-то на древнем лэптопе его гонял. каждая ошибка конфигурации стоила минимум 2-3 часа. единственное что спасало - это с помощью дистцц полностью компиляцию на мой десктоп аутсорсить. (что не со всеми пакетами в те времена работало, потому что куча софта компилер ручками перепрописывает, убивая поддержку дистцц.) но было очень прикольно: лэптоп якобы усердно компилит 2-5 файлов в секунду, а вентиляторы завывают под столом.
                        Ответить
                        • Если тебе показать блютус колонки, ты наверно умрешь: плеер в одном месте, а колонки в другом!
                          Ответить
                          • Я так музыку слушал - сотик по 3г получает инет и раздаёт его по вафле ноуту, ноут по блютусу отдаёт звук на наушники... Апофеоз беспроводных технологий.
                            Ответить
      • Ну тут как бы сразу случилось много чего.
        1. Лаптоп умер от скачка напряжения.
        2. Решил проапдейтить старый десктоп.
        3. Во время апдейта электричество снова отключили, и когда включили, оказалось два набора пакетов из новой и старой версий. После догого вечера проведенного в попытках как-то вернуть систему к жизни умерла видеокарточка.
        Теперь приходится рабочим лаптем дома пользоваться.

        Но, что интересно, в процессе я обнаружил какое говно эти fedup и fedora-update. fedup так вообще куча детских ошибок, например, имя переменной написано с ошибкой, или нет метода у объекта с таким именем, или весь блок из try-except уехал влево. Т.е. его по-ходу не тестировали, ну не на столько, чтобы проверить что случится при ошибках. fedora-update так вообще даже не пытается что-то сделать если "что-то пошло не так". Но, с другой стороны, я пытался проапдейтиться с семнадцатой версии, может с того времени стало лучше.

        В любом случае, перехожу на Арч.
        Ответить
        • > имя переменной написано с ошибкой

          уже много лет задаюсь вопросом: существует ли какой скриптовый язык с (опциональным) статическим строгим типизированием и какой-нибудь системой статического аналаза кода?

          я пару раз большие скрипты с шелла/перла/питона в С/С++ переписывал, потому что размеры скриптов были охрененные (автоматизация процессов) а каких-либо проверок встроеных почти ноль.

          кроме bash'вых `set -eu` я ничего не знаю.
          Ответить
          • > скриптовый язык с (опциональным) статическим строгим типизированием

            Julia вот особо давно появилась http://julialang.org/
            А так-то, конечно, скриптовое редко бывает статически типизированным.

            Go компиляется шустро, его можно как скрипт запускать, а в стандартной либе есть много всего для системного программирования:
            https://wiki.ubuntu.com/gorun
            Ответить
            • Я сейчас на Го пишу. Его недотипизация столько головной боли добавляет, что я бы лучше больше тестов на Питне писал бы.
              Ответить
              • Ну хотя бы в мапу с интами строки не положишь, и имена полей известны на этапе компиляции, уже за радость. И значение из функции случайно не забудешь вернуть.
                Ответить
                • Зато есть уникальные фишки: например использовать указатель на копию. Вчера в проекте нашел примерно следующий код:
                  type foo struct {
                      bar int
                      // еще куча полей
                  }
                  
                  func find(elt int, foos []foo) *foo {
                      for _, f := range foos {
                          if f.bar == elt {
                              return &f
                          }
                      return nil
                  }


                  С таким использованием:
                  func qux(foos []foo) {
                      f := find(N, foos)
                      // какие-то манипуляции с f, после чего f больше не используется
                  }

                  Т.е. человек был уверен в том, что работает с элементом масива, а на самом деле работал с копией. В Питоне чтобы такого добиться нужно самому написать итератор копирующий элементы (я ни разу не встречал)
                  Ответить
                  • Ну это просто банальное незнание языка или неумение работать с языками, где всё передаётся по значению. Я вообще сомневаюсь, что в Go можно получить сырой указатель на кишки слайса.

                    Точно также можно удивляться, почему это я сохранил питоний объект в новую переменную, изменил поле, а после этого изменился оригинал.

                    Просто возвращайте из find индекс или подслайс.

                    func find(elt int, foos []foo) []foo {
                        for i := range foos {
                            if foos[i].bar == elt {
                                return foos[i:]
                            }
                        }
                        return nil
                    }
                    Ответить
                    • А почему компилтор ничего не сказал на &f
                      Ответить
                      • > А почему компилтор ничего не сказал на &f

                        А что он должен был сказать? Это не указатель на переменную на стеке :)

                        Когда компилятор Go выбирает, где размещать переменные - на стэке или в куче, он делает escape analysis. Если адрес переменной утекает из функции, он размещает переменную в куче.
                        Ответить
                        • Это указатель на элемент массива, не?
                          Аааа, копирование происходит тут?
                          > for _, f
                          А если написать

                          for _, &f

                          ?
                          Ответить
                          • Говорю же, сомневаюсь, что можно получать указатель на середину слайса. Если хочется таскать объекты по ссылке - нужно хранить в слайс указателей.

                            Почему сомневаюсь: слайсы хранят элементы по значению, т.е. слайс структур будет размера capacity * размер структуры. Если ты хочешь сохранить указатель на отдельный элемент, тебе придётся хранить вместе с этим элементом указатель на весь слайс, чтобы GC не прибрал твой объект. А это по сути приведёт к классической утечке памяти, да и указатель должен быть каким-то чрезмерно умным, чтобы кроме адреса элемента помнить ещё и адрес слайса.

                            В общем, GC-проблемы.
                            Ответить
                            • В rust'е вроде как слайсы по ссылке берутся. Но там компилятор сразу даёт по рукам, если указатель или слайс живёт дольше, чем исходный массив.

                              P.S. Всё хочу помучать раст, но подходящих задачек не попадается.
                              Ответить
                    • В том-то как бы и оно: если в слайсе элементы по значению, то в цикле адресс элемента можно взять так &slice[i].
                      А вот банальное ли это незнание, или нет, не в том же смсысл. Смысл в том, что проверка типов не спасает от такого рода ошибок. И вообще, в Го проверки типов спасают только от самых тривиальных ошибок. А они и так бы всплыли на тестах. А то, что кроме массивов и словарей все коллекции должны быть с типом элементов interface{} как бы делает из Го тот же Питон, только менее удобный.

                      Ну и кроме того, всегда приходится выбирать из двух зол: либо копировать функцию типа find() для других типов, либо кастовать к, по-сути *void. Ну и подход стандартной библиотеки в этом смысле сильно порадовал: типов чисел прям как в сишке, но математические функции определены только для float64. Вот хочешь максимум из двух интов - либо конертируй, либо пиши maxInt() с блекджеком и т.д. Ну и чем больше такого безумного кода - тем больше ошибок.
                      Ответить
                      • > проверка типов не спасает от такого рода ошибок

                        Я в последнее время много пишу на Python, и просто мечтаю хотя бы о такой проверке типов :)
                        Ответить
                        • Если питон свежий, то можно использовать mypy.
                          Ответить
                      • > адресс элемента можно взять так &slice[i].
                        Да, проверил на примерах и в спеке, там написано, что можно.
                        Интересно, как они это реализовали... Надо будет спросить в мэйлинг-листе.
                        Ответить
                        • > сомневаюсь, что можно получать указатель на середину слайса

                          В общем, я осознал, что дико тупил и нёс бред.

                          Слайсы хранят только указатель на первый элемент, длину и ёмкость. Поэтому когда мы делаем подслайс s[1:], возникает точно такая же проблема, как и с указателями.

                          Поэтому GC в любом случае надо будет проверять не только указатели на истинное начало внутренних массивов в слайсах, но и проверять, не ссылается ли кто внутрь этого массива.
                          Ответить
                          • > проверять, не ссылается ли кто внутрь этого массива
                            Вроде бы в D такой же GC был.
                            Ответить
                            • А если используется XOR-связный список, как оно будет что-то там проверять?
                              Ответить
                          • О, а еще, я сегодня познал закат солнца вручную создавая виртуальные методы... А еще ошибки без стек трейсов, которые, по завету Страуструпа, видимо, нужно самому переделывать в ошибки со стектрейсами.
                            А еще мне нравится, что в Го есть 10+ разновидностей print() в стандартной библиотеке + шаблоны + есть еще надцать библиотек, кторые это делают.
                            Вобщем, ощущение такое, что чтобы прельстить сишников в Го напихали сишных ошибок, специально недоделали ООП, ну и дали возможность поразвлекаться переписывая по-новой тривиальные алгоритмы, знакомые еще со школьных времен. Ностальгия такая, но с понтами.

                            ЗЫ. И пустоты разных типов - это вообще умилительно...
                            Ответить
                            • > познал закат солнца вручную создавая виртуальные методы
                              поясните мысль

                              > А еще ошибки без стек трейсов
                              Ну тут посыл у них следующий - зачем юзеру ваши стектрейсы, которые несут тонну информации о структуре программы, но зачастую не несут информации о причине ошибки.
                              Это имеет смысл, когда обработка ошибок явная, и, следовательно, придётся задолбаться и включить в сообщение об ошибке всю релевантную информацию (что делали, с чем делали).
                              Если исключению летят отовсюду (как в Python / Java), такой подход не прокатывает.

                              На действительно критичные (неожиданные) ошибки panic() стектрейсы показывает.
                              Ответить
                              • Ну, примерно так:

                                type Reader interface {
                                    VirtualRead() string
                                    ConcreteRead() string
                                }
                                
                                type Base struct {
                                    virtual Reader
                                }
                                
                                func (this *Base) ConcreteRead() string {
                                    return "Base.ConcreteRead()"
                                }
                                
                                func (this *Base) VirtualRead() string {
                                    return this.virtual.ConcreteRead()
                                }
                                
                                func New(reader Reader) Reader {
                                    // тут можно было бы reader.Base.virtual = reader
                                    // но тогда нужно знать конкретный тип reader...
                                    // или можно было бы сделать Base.Virtual, но
                                    // тогда это поле придется переименовывать при
                                    // еще одном наследовании
                                    result := Base{}
                                    result.virtual = reader
                                    return result
                                }
                                
                                type Concrete struct {
                                    *Base
                                }
                                
                                func (this *Concrete) VirtualRead() string {
                                    baseRead := this.Base.ConcreteRead()
                                    return strings.Rplace(baseRead, "Base", "Concrete", 1)
                                }
                                
                                concrete := New(Concrete{&Base{}})
                                concrete.VirtualRead()
                                
                                type Solid struct {
                                    *Base
                                }
                                
                                solid := New(Concrete{&Base{}})
                                solid.VirtualRead()
                                Ответить
                              • А при чем тут пользователь? Для него можно показать хоть гифку, хоть гоатсе, это же не проблема убрать стектрейс. Проблема его добавлять самодельными способами. panic() как бы тоже не решение изза уебищного recover(), изза которого его нельзя использовать как обычные ошибки (т.е. обработать ошибку и продолжить выполнение программы).

                                Хз. с Го чем дальше в лес, тем печальнее и печальнее. Все какое-то недоделаное, при чем уже ведь было полвека назад нормально сделаное, и тут как будто проснулись с амнезией и нахерачили...
                                Ответить
                                • > А при чем тут пользователь?
                                  Да при том. Я, как пользователь многих Python скриптов, заявляю - они люто задолбали своими невнятными стек-трейсами, после которых непонятно, что нужно делать. Причина, конечно, не в языке - любую ошибку можно нормально обработать и показать. Разница в том, что Go заставляет это делать, а python - нет.

                                  > Все какое-то недоделаное
                                  Ну вот не надо. Они что хотели, то и сделали. Причём то, что хотели, сделали хорошо.
                                  В Го много спорных решений, многие из них нравятся не сразу, многие не нравятся вообще. Меня, например, удручает отсутствие возможности писать вменяемый обобщённый код.
                                  Ответить
                                  • Го заставляет зубы чистить через нос, и это типа хорошо?
                                    Пользователь или:
                                    1. Не пишет на Питное, и в этом случае все, что он может сделать: послать стектрейс автору.
                                    2. Пишет на Питоне, и в этом случае, он может либо попытаться исправить ошибку, либо (1).

                                    Если ошибка - ожидаемая, т.е. результат ввода пользователя, то тогда логично не показывать стектрейс, а показать какое-нибудь сообщение, которое объясняет в чем ошибка. Например, если речь зашла о Питоне, то так будет как правило реализована обработка аргументов командной строки.

                                    В Го, если ошибка неожидаемая (типа НПЕ), то случится паника и стектрейс вроде как будет, но его похерит первый же recover(), который, скорее всего, к этой панике не имеет отношения. Сообщения об ошибках типа ошибках в аргументах командной строки все равно надо писать так же, как и в Питоне. Но вот ошибки, которые типа не ошибки просто вгоняют в депрессию.

                                    Например: в нашем коде используется Го библиотека для работы с VSphere. И время от времени в датацентре случаются ЧП, но из нашего кода все, что можно узнать это что-то типа "попытка обращеника к ВМ обломалась", и потом поди угадай, что он там делал, к какой ВМ обращался и т.д.
                                    Ответить
                                  • ПС. Если так сильно мешают стектрейсы в Питоне: sys.tracebacklimit = 0 и алды. Никто ж не мешает.
                                    Ответить
                                    • > Если так сильно мешают стектрейсы в Питоне

                                      Мешают не стектрейсы, а внятное объяснение ошибки. Если отключить стектрейсы, совсем глухо будет "случился ай-яй-яй, пичаль".

                                      Конкретно в моём случае было "бида, один меньше двух" и длиннущий стектрейс. Оказалось, что это ругался классификатор на то, что в обучающей выборке все объекты были одного типа. Чтобы это понять, пришлось перечитать половину scikit-а и запускать pdb.

                                      Дело не в языке, а в подходе к обработке ошибок. В го задалбывает писать if err == nil, но это же вынуждает тщательней выбирать стратегии обработки ошибок.
                                      Ответить
                                      • Хаскил все равно не победить. Там если один меньше двух, то сообщение будет типа
                                        > Rational semiring identity element conflicts with free submonoid annihilator over rational alphabet [a0] when applied to integral domain (Applicative x => _ -> y)
                                        Ответить
                                        • > Rational semiring identity element conflicts with free submonoid

                                          Если это будет выдаваться на этапе компиляции, то я согласен.

                                          А если серьёзно - рантайм ошибки в хаскеле информативностью не блещут. Выход за границы массива приносит боль и психологические увечья.

                                          В этом плане Ocaml со включенными стектрейсами на два шага впереди.
                                          Ответить
          • > уже много лет задаюсь вопросом: существует ли какой скриптовый язык с (опциональным) статическим строгим типизированием и какой-нибудь системой статического аналаза кода?

            erlang+dyalizer
            (правда erlang сосёт)
            Ответить

    Добавить комментарий