Короче, у постов сверху не будет комментов
(И настраивать я их не буду. Я всё же байтослесарь, а не сммщик.)
(И настраивать я их не буду. Я всё же байтослесарь, а не сммщик.)
👍2
binfmt_misc – почти что реестр, но в linux
Пока мы обсуждали как можно писать свои реализации
Зайдём из далека. Помнишь реестр и привязанные к расширениям программы? Тот самый момент когда ты кликаешь по xml файлу, а он запускает тебе Visual Studio Very Enterpise Edition (repack by Vasya)? Хорошо. Я сейчас про более узкую вещь, про то что ты можешь запустить batch/python или другой скрипт двойным кликом, а система сама знает каким интерпретатором его запускать.
Так вот в #linux'е тоже есть своеобразный реестр для ассоциации файлов с программами. (Можно, конечно, написать свой модуль ядра, но это удел храбрых, а не user space холопов вроде нас.)
Реестр этот называется #binfmt_misc. Вместо того чтобы городить отдельные syscall'ы для реестра интерпретаторов, ребята написали файловую систему, которая делает странное на
Ты пишешь в
Можно регистрировать интерпретатор для расширения (любого суффикса) или для строчки байт по оффсету. Но shebang
Всё, теперь ядро автоматически начнёт выполнять что-то типа
Ставь binfmt и подписывайся на интерпретатор, если тебя задолбало писать
https://flapenguin.me/bnb/binfmt_misc
Пока мы обсуждали как можно писать свои реализации
read / write через #vfs или #fuse, только отдавая информацию из чего-то похожего на привычные файловые хранилища, но всё ещё не делали ничего странного на write. И в эту субботу самое время.Зайдём из далека. Помнишь реестр и привязанные к расширениям программы? Тот самый момент когда ты кликаешь по xml файлу, а он запускает тебе Visual Studio Very Enterpise Edition (repack by Vasya)? Хорошо. Я сейчас про более узкую вещь, про то что ты можешь запустить batch/python или другой скрипт двойным кликом, а система сама знает каким интерпретатором его запускать.
Так вот в #linux'е тоже есть своеобразный реестр для ассоциации файлов с программами. (Можно, конечно, написать свой модуль ядра, но это удел храбрых, а не user space холопов вроде нас.)
Реестр этот называется #binfmt_misc. Вместо того чтобы городить отдельные syscall'ы для реестра интерпретаторов, ребята написали файловую систему, которая делает странное на
write.Ты пишешь в
/proc/sys/fs/binfmt_misc (монтируешь куда хочешь, само собой) строчку в определённом формате – регистрируешь интерпретатор в ядре. (Да, формат с двоеточиями, ты удивлён?) Пишешь -1 в другой файл – дерегестрируешь интерпретатор.Можно регистрировать интерпретатор для расширения (любого суффикса) или для строчки байт по оффсету. Но shebang
#! реализовать не получится, поэтому он – отдельный модуль ядра.Всё, теперь ядро автоматически начнёт выполнять что-то типа
execve("/usr/bin/python", "./my.py") вместо execve("./my.py"). Учти, реестр этот глобальный на всё ядро и даже root не может его обойти.Ставь binfmt и подписывайся на интерпретатор, если тебя задолбало писать
wine solitare.exe, но теперь ты знаешь, что делать.https://flapenguin.me/bnb/binfmt_misc
🔥5
setuid - получаем root
Я рассказывал, что у процесса есть точно такие же числа uid/gid, как у файлов. И то, что когда процесс пытается получить доступ к файлу, эти числа сраниваются.
Но иногда оно работает в обратную сторону. Когда процесс делает
Фича эта называется
Это единственный способ поднять привелегии процесса. Без него если кто-то из родителей процесса добровольно отдал root, то больше процесс больше никак не может позвать
Иногда тупо нужно запустить что-то от имени другого пользователя. Ну, через
Бывает, логически у тебя должен быть доступ, но данные уже хранятся в таком виде, что доступ туда есть только у root'а. Например, ты хочешь поменять пароль, а он лежит в
Другой классический пример:
Можно было бы написать демонов
Мне фича всегда казалась плохо спроектированным грязным хаком и зияющей дырой в безопасности. Но хак хорош. Настолько хорош, что у Денниса Ритчи даже был на него патент.
Ах да, монтируй только проверенные харды без
https://flapenguin.me/bnb/setuid
Я рассказывал, что у процесса есть точно такие же числа uid/gid, как у файлов. И то, что когда процесс пытается получить доступ к файлу, эти числа сраниваются.
Но иногда оно работает в обратную сторону. Когда процесс делает
execve файла, ядро может взять его uid/gid и запустить процесс с ними.Фича эта называется
setuid (чтобы было не скучно и ты путал её с setuid(2) при каждом случае). Аналогично есть setgid. Включается проставлением флага на файле через chmod: fchmod(fd, S_ISUID) (только не забудь чекнуть свои привелегии).Это единственный способ поднять привелегии процесса. Без него если кто-то из родителей процесса добровольно отдал root, то больше процесс больше никак не может позвать
setuid(2). А бывает нужно.Иногда тупо нужно запустить что-то от имени другого пользователя. Ну, через
su или sudo. Запускаешь такую программу, она насильно запускается от root'а, читает закрытый от всех /etc/sudoers и понимает, можно тебе запускать команду, или нет. Если да, то по максимуму сбрасывает окружение (а то мало ли ты LD_PRELOAD передал) и вперёд.Бывает, логически у тебя должен быть доступ, но данные уже хранятся в таком виде, что доступ туда есть только у root'а. Например, ты хочешь поменять пароль, а он лежит в
/etc/shadow, куда у тебя, очевидно, нет доступа. Приходится звать passwd с setuid'ом. Он не только проследит, что ты меняешь только свой пароль, но и проверит его на всякие политики безопасности (так что отдельные файлики /etc/users/:uid/password не сработают, увы).Другой классический пример:
ping. Рядовому пользователю нельзя слать по сети произвольные байты. ping занимается плюс-минус этим, поэтому запустится от root’а, параноидально сделает свои дела и завершится. (К слову, во FreeBSD только что нашли RCE именно в ping'е https://www.opennet.ru/opennews/art.shtml?num=58232)Можно было бы написать демонов
passwdd и pingd и общаться с ним по какому-нибудь сокету, но это банально сложнее.Мне фича всегда казалась плохо спроектированным грязным хаком и зияющей дырой в безопасности. Но хак хорош. Настолько хорош, что у Денниса Ритчи даже был на него патент.
Ах да, монтируй только проверенные харды без
nosuid'а.https://flapenguin.me/bnb/setuid
👍4
init - запускаем голый exe на голом ядре
root тяжело найти, легко потерять и невозможно забыть. Осталось понять откуда он изначально берётся.
Ответ простой. Ядро #linux'а при старте запускает один единственный процесс со всеми правами на свете. Но мало знать ответ, хочется же пощупать что там происходит на самом деле.
Общество и, возможно, лично Поттеринг хочет, чтобы ты считал, что самому собирать системы сложно. Ведь иначе люди увидят насколько плох GNU-софт, или, ещё хуже, перестанут заносить деньги в Red Hat. На ум сразу приходит LFS, где надо долго и нудно копипастить команды сборки GNU софта спотыкаясь об autohell. В итоге, вроде, и команды сам ввёл, и систему сам собрал, но ни черта не понятно.
Нам с тобой полноценный GNU/Linux собирать не надо, поэтому обойдёмся чернозёмом и палками. Понадобится виртуалка, ядро, и какой-нибудь бинарник для init'а. Возьмём #qemu, собранное ядро украдём из netboot'а #alpine'а, а вместо init'а у нас будет интерактивный шел
qemu умеет запускать линуксовое ядро из коробки, это значит нам не придётся возиться с grub'ом и bios/efi. Нужно только сварить ramdisk, файловую систему, с которой стартанёт ядро. В него мы положим busybox и init из пары строчек.
Полный скрипт для подготовки и запуска виртуалки занял всего 30 строк. https://github.com/flapenguin/stuff/blob/master/linux-boot/boot-x86_64.sh
Последней строчкой скрипт запускает qemu и... Поздравляю, у тебя root. И виртуалка с голым линуксом в придачу. Всё, можешь писать убийцу systemd.
(убить виртуалку можно через
https://flapenguin.me/bnb/init
root тяжело найти, легко потерять и невозможно забыть. Осталось понять откуда он изначально берётся.
Ответ простой. Ядро #linux'а при старте запускает один единственный процесс со всеми правами на свете. Но мало знать ответ, хочется же пощупать что там происходит на самом деле.
Общество и, возможно, лично Поттеринг хочет, чтобы ты считал, что самому собирать системы сложно. Ведь иначе люди увидят насколько плох GNU-софт, или, ещё хуже, перестанут заносить деньги в Red Hat. На ум сразу приходит LFS, где надо долго и нудно копипастить команды сборки GNU софта спотыкаясь об autohell. В итоге, вроде, и команды сам ввёл, и систему сам собрал, но ни черта не понятно.
Нам с тобой полноценный GNU/Linux собирать не надо, поэтому обойдёмся чернозёмом и палками. Понадобится виртуалка, ядро, и какой-нибудь бинарник для init'а. Возьмём #qemu, собранное ядро украдём из netboot'а #alpine'а, а вместо init'а у нас будет интерактивный шел
sh -i из #busybox'а. Последний тоже качнём уже собранный. Потому что навряд ли ты вечер четверга хотел провести в Makefile'ах.qemu умеет запускать линуксовое ядро из коробки, это значит нам не придётся возиться с grub'ом и bios/efi. Нужно только сварить ramdisk, файловую систему, с которой стартанёт ядро. В него мы положим busybox и init из пары строчек.
Полный скрипт для подготовки и запуска виртуалки занял всего 30 строк. https://github.com/flapenguin/stuff/blob/master/linux-boot/boot-x86_64.sh
Последней строчкой скрипт запускает qemu и... Поздравляю, у тебя root. И виртуалка с голым линуксом в придачу. Всё, можешь писать убийцу systemd.
(убить виртуалку можно через
poweroff -f в ней или kill … из соседнего терминала)$ qemu-system-x86_64 ... -kernel ./deps/x86_64/vmlinuz-lts -initrd ./initrd/x86_64.gz
...
/ # id
uid=0 gid=0
https://flapenguin.me/bnb/init
👍3🌚2🔥1
capabilities - root по кусочкам
Что-то мне подсказывает, uid 0 был выбран для суперпользователя по банальной причине: удобно писать
Со временем пришло осознание, что во множестве ситуаций нужен не весь root, а только кусочек. Ну странно же давать право менять модули ядра nginx'у, которому всего-то надо забиндить 80й порт.
В итоге, права суперпользователя нарезали на capabilities. В 6.1.3 их целых 43 штуки. Например, можно запретить всё и выдать только разрешения биндить 0-1023 порты
capabilities, так же как и uid, – атрибут не пользователя, а процесса (на самом деле треда, но не важно). Напоминаю, пользователей не существует. Раньше у процесса был только атрибут-число uid, теперь к нему добавился атрибут-битсет capabilities. При этом capabilities и uid никак не связаны. У тебя может быть всемогущий uid 1337 и никчёмный uid 0.
Посмотреть этот битсет можно в #procfs
Работать с привелегиями можно через пару syscall'ов capset и prctl. Привелегии можно повышать, понижать, понижать временно, настраивать наследование дочерними процессами.
Также для повышения привилегий есть механизм setcap на файле, аналогичный suid биту. Но это если файловая система поддерживает атрибуты у файлов, если ты ретроград с ext1, то остаётся толькопить галоперидол получать классический root.
https://flapenguin.me/bnb/capabilities
Что-то мне подсказывает, uid 0 был выбран для суперпользователя по банальной причине: удобно писать
if (uid && !allowed(uid, ...)) goto fail;.Со временем пришло осознание, что во множестве ситуаций нужен не весь root, а только кусочек. Ну странно же давать право менять модули ядра nginx'у, которому всего-то надо забиндить 80й порт.
В итоге, права суперпользователя нарезали на capabilities. В 6.1.3 их целых 43 штуки. Например, можно запретить всё и выдать только разрешения биндить 0-1023 порты
CAP_NET_BIND_SERVICE и посылать raw-пакеты CAP_NET_RAW. Или выдать разрешение выдавать разрешения CAP_SETPCAP.capabilities, так же как и uid, – атрибут не пользователя, а процесса (на самом деле треда, но не важно). Напоминаю, пользователей не существует. Раньше у процесса был только атрибут-число uid, теперь к нему добавился атрибут-битсет capabilities. При этом capabilities и uid никак не связаны. У тебя может быть всемогущий uid 1337 и никчёмный uid 0.
Посмотреть этот битсет можно в #procfs
$ grep '^Cap' /proc/self/status
CapInh: 10000000a80425fb
CapPrm: 20000000a80425fb
CapEff: 30000000a80425fb
CapBnd: 40000000a80425fb
CapAmb: 5000000000000000
Работать с привелегиями можно через пару syscall'ов capset и prctl. Привелегии можно повышать, понижать, понижать временно, настраивать наследование дочерними процессами.
Также для повышения привилегий есть механизм setcap на файле, аналогичный suid биту. Но это если файловая система поддерживает атрибуты у файлов, если ты ретроград с ext1, то остаётся только
https://flapenguin.me/bnb/capabilities
👍3🤩3🔥2💯1
Тут у Casey Muratori вышло видео с рассуждением о том, как Clean Code подходы убивают производительность софта. (Настоятельно рекомендую канал, кстати, набрасывает Casey как боженька. Только держите в голове, что он и сам фанатик.)
Видео о том, как адепты сферического ООП пропагандируют, что всё должно быть слабо связано, полиморфно, инкапсулировано и изолировано. И, конечно же, раздроблено на двухстрочники в отдельных файлах. Тогда, мол, поддерживать проект будет просто, а о производительности позаботится компилятор с рантаймом.
И как ты уже догадался, кроме тебя о производительности никто не позаботится. Сферический ООП по лучшим практикам замедляет твой код на порядок. И речь не о преждевременной оптимизации. Преждевременная оптимизация и заведомо неэффективный код – разные вещи.
Я хочу немного порассуждать о первой части обещания, о лёгкой поддержке. Реальность в том, что абстракции почти всегда плохие и текут. Да текут так, что разработчику надо знать реализацию самой сущности и всех остальных абстракций вокруг. И это, внезапно, совсем не помогает бороться со сложностью, а делает только хуже.
На реддите основная претензия к видео – “представьте, что завтра вам надо будет добавить серобуромалиновые полигоны с дырками”. На это я могу ответить только одно: а представьте, что нет. Представьте, что не надо. Или что через 2 года, когда будет надо, текущей абстракции всё равно не хватит и её придётся пересобирать с нуля.
"Clean Code подходы" и прочий сферический SOLID-OOP, как и любой другой инструмент, хорошо работает для одних целей и плохо для других. Но его почему-то воспринимают как нерушимую истину. Из-за этого не следовать ему может быть страшно и даже стыдно. Но самое страшное, что произойдёт – ты поругаешься с ярыми евангелистами, не напишешь FizzBuzzEnterpriseEdition, а где-то далеко горько заплачет один Дядя Боб.
BTW Мне нравится, что люди начали замечать, что книга то – говно.
#performance #architecture
Видео о том, как адепты сферического ООП пропагандируют, что всё должно быть слабо связано, полиморфно, инкапсулировано и изолировано. И, конечно же, раздроблено на двухстрочники в отдельных файлах. Тогда, мол, поддерживать проект будет просто, а о производительности позаботится компилятор с рантаймом.
И как ты уже догадался, кроме тебя о производительности никто не позаботится. Сферический ООП по лучшим практикам замедляет твой код на порядок. И речь не о преждевременной оптимизации. Преждевременная оптимизация и заведомо неэффективный код – разные вещи.
Я хочу немного порассуждать о первой части обещания, о лёгкой поддержке. Реальность в том, что абстракции почти всегда плохие и текут. Да текут так, что разработчику надо знать реализацию самой сущности и всех остальных абстракций вокруг. И это, внезапно, совсем не помогает бороться со сложностью, а делает только хуже.
На реддите основная претензия к видео – “представьте, что завтра вам надо будет добавить серобуромалиновые полигоны с дырками”. На это я могу ответить только одно: а представьте, что нет. Представьте, что не надо. Или что через 2 года, когда будет надо, текущей абстракции всё равно не хватит и её придётся пересобирать с нуля.
"Clean Code подходы" и прочий сферический SOLID-OOP, как и любой другой инструмент, хорошо работает для одних целей и плохо для других. Но его почему-то воспринимают как нерушимую истину. Из-за этого не следовать ему может быть страшно и даже стыдно. Но самое страшное, что произойдёт – ты поругаешься с ярыми евангелистами, не напишешь FizzBuzzEnterpriseEdition, а где-то далеко горько заплачет один Дядя Боб.
BTW Мне нравится, что люди начали замечать, что книга то – говно.
#performance #architecture
🔥3🌭2
Ого, ничосе, там yt заопенсорсили https://ytsaurus.tech/ https://habr.com/ru/company/yandex/blog/721526/
YT(saurus) – няшка. Бабенко – милашка.
YT(saurus) – няшка. Бабенко – милашка.
🥰3
groups – наш пользователь и человек, и пароход, и wheel
Я говорил, что
Увидеть это можно запустив обычный
Но зачем?
Нужна возможность как-то получить процесс, который может и
У отдельного
И то и другое наследуется при создании процесса. И то и другое может менять только владелец capability
Именно поэтому после добавления себя в группу тебе надо перелогиниться. Перелогинивает тебя сессионный менеджер, у которого этот самый
Кстати, в #POSIX'е есть setuid-утилита newgrp, которая за тебяперелогинится насоздаёт лишних процессов. Не рекомендую.
https://flapenguin.me/bnb/groups
Я говорил, что
gid у процесса очень похож на uid. Но на самом деле не совсем похож.gid - такой же произвольный uint32, как и uid. Только uid у твоего процесса один, а gid'ов может быть много. Много групп groups, к которым у процесса есть доступ, и одна активная, собственно, gid.Увидеть это можно запустив обычный
id:❯ id uid=1000(flapenguin) gid=1001(flapenguin) groups=1001(flapenguin),998(docker)
Но зачем?
Нужна возможность как-то получить процесс, который может и
cron настраивать и docker запускать. Т.е. с доступом в разграниченные части fs. И именно groups дают тебе такие права. У процесса таких может быть аж 65536 (2^16).У отдельного
gid'а задача более прозаичная. Он нужен как дефолт для операций типа open(..., O_CREAT) и clone.И то и другое наследуется при создании процесса. И то и другое может менять только владелец capability
CAP_SETGID через setgid и setgroups.Именно поэтому после добавления себя в группу тебе надо перелогиниться. Перелогинивает тебя сессионный менеджер, у которого этот самый
CAP_SETGID есть. Будь то systemd-loging или sshd.Кстати, в #POSIX'е есть setuid-утилита newgrp, которая за тебя
$ ps -ft
PID TTY STAT TIME COMMAND
1638690 pts/0 Ss 0:00 -bash
1638804 pts/0 S 0:00 _ newgrp
1638805 pts/0 S 0:00 _ bash
1638815 pts/0 S 0:00 _ newgrp
1638816 pts/0 S 0:00 _ bash
1638829 pts/0 R+ 0:00 _ ps -ft
https://flapenguin.me/bnb/groups
❤2🍾1
scm_rights - посылаем дескрипторы почтой
Всё это время я тут задвигал про uid'ы и gid'ы. Это неплохая система доступов, позволяющая делать комплексные вещи.
Но бывает, твоя задача не решается в рамках такой системы. Ну вот не лезет и всё тут.
Допустим, тебе надо разделить accept соединения и его обработку. Потому что работа твоего сервера с capability
Да, ты можешь форкнуться и понизить нового себя в правах. Но наследование дескриптора произойдёт только в момент форка. Так что форкаться тебе придётся на каждое соединение. Очевидно, что быстро работать это не может.
Да, ты можешь поднять внутри своего основного процесса колхозный RPC и перекладывать через него данные. Просто доставать данные из одной трубы, чтобы переложить в другую.
Но зачем всё это, если ты можешь отправлять fd'шки почтой по unix-сокетам.
Буквально, по unix-сокетам можно отправить почти любой открытый дескриптор соседу. Фича называется
Используется это добро, например, в DRI Xserver'а и в wayland'е, чтобы отдать пользователю преднастроеный дескриптор
Есть ещё
https://flapenguin.me/bnb/scm_rights
Всё это время я тут задвигал про uid'ы и gid'ы. Это неплохая система доступов, позволяющая делать комплексные вещи.
Но бывает, твоя задача не решается в рамках такой системы. Ну вот не лезет и всё тут.
Допустим, тебе надо разделить accept соединения и его обработку. Потому что работа твоего сервера с capability
CAP_NET_BIND_SERVICE – принимать соединения. Потому что работать же с этими соединениями можно хоть из под nobody. Потому что тебе хочется как-то понизить права.Да, ты можешь форкнуться и понизить нового себя в правах. Но наследование дескриптора произойдёт только в момент форка. Так что форкаться тебе придётся на каждое соединение. Очевидно, что быстро работать это не может.
Да, ты можешь поднять внутри своего основного процесса колхозный RPC и перекладывать через него данные. Просто доставать данные из одной трубы, чтобы переложить в другую.
Но зачем всё это, если ты можешь отправлять fd'шки почтой по unix-сокетам.
Буквально, по unix-сокетам можно отправить почти любой открытый дескриптор соседу. Фича называется
SCM_RIGHTS, часть socket ancillary data. И это не что-то новое. Фича есть в #POSIX'е минимум 15 лет.Используется это добро, например, в DRI Xserver'а и в wayland'е, чтобы отдать пользователю преднастроеный дескриптор
/dev/video. В nodejs (через поддержку в libuv) используется для ipc и балансировки cluster'ом.Есть ещё
SO_PEERCRED, чтобы узнать uid/gid процесса с другой стороны сокета, и SCM_CREDENTIALS, чтобы отправить любые uid/gid. Которые проверятся ядром, а его не обманешь. Такая бесплатная авторизация в локальных демонах. Зачем при такой фиче нужен kostilique .Xauthority для меня загадка.https://flapenguin.me/bnb/scm_rights
🔥4🌭1
euid - от кого запустили sudo
Уже достаточно давно я разбирал как запускать всякое от root’а через setuid флажки.
Сегодня расскажу про вторую половинку этого механизма. Без которой ничего, на самом деле, не заведётся.
Потому что мало просто выбросить свою старую идентичность и стать root’ом.
Никакой сложной системы тут нет и решение проблемы поистине дубовое. Старая идентичность при запуске setuid бинарников не выбрасывается, а перекладывается в соседние поля процесса.
Ядро знает, кому можно kill’ять
Поля эти есть у каждого процесса и у них даже есть описание в man 7 capabilities. Оно старательно пытается выглядеть не как ой-нам-тут-надо-было-прокинуть-получилось-как-получилось, но костыли за широкими мануалами не спрячешь.
Тем не менее:
-
-
-
Посмотреть на всё это добро можно через procfs. Дока последнего говорит, что они лежат в
https://flapenguin.me/bnb/euid
Уже достаточно давно я разбирал как запускать всякое от root’а через setuid флажки.
Сегодня расскажу про вторую половинку этого механизма. Без которой ничего, на самом деле, не заведётся.
Потому что мало просто выбросить свою старую идентичность и стать root’ом.
sudo нужно знать от кого его запустили, иначе как он будет свой /etc/sudoers читать. А ping было бы неплохо иметь возможность SIGSTOP’нуть или SIGKILL’нуть не из под root’а.Никакой сложной системы тут нет и решение проблемы поистине дубовое. Старая идентичность при запуске setuid бинарников не выбрасывается, а перекладывается в соседние поля процесса.
sudo знает кто его запустил из saved user id и saved group id.Ядро знает, кому можно kill’ять
ping из real user id и real group id.Поля эти есть у каждого процесса и у них даже есть описание в man 7 capabilities. Оно старательно пытается выглядеть не как ой-нам-тут-надо-было-прокинуть-получилось-как-получилось, но костыли за широкими мануалами не спрячешь.
Тем не менее:
-
euid Effective User ID — это про проверки unix permission в ядре (то, что делает root’а root’ом)-
suid Saved User ID — это способ сообщить setuid процесс’у от чьего имени его запустили-
ruid Real User ID — это разрешение процессам с таким же uid посылать любые сигналыПосмотреть на всё это добро можно через procfs. Дока последнего говорит, что они лежат в
/proc/1337/status в таком форматеUid | Real, effective, saved set, and file system UIDs
Gid | Real, effective, saved set, and file system GIDs
https://flapenguin.me/bnb/euid
🌭2🤯1
This media is not supported in your browser
VIEW IN TELEGRAM
А вы знали, что для регистрации на гитхабе теперь надо крутить собаку?
🔥4😁2
Почему ON CONFLICT DO NOTHING тебя ненавидит и конфликтует
В стандарте SQL есть такая конструкция
Но
Представь, что у тебя есть
Одной сессии повезёт больше и она добавит строку, пусть даже в транзакции. Другой сессии же придётся встать в очередь и ждать. Потому что любое предположение о другой транзакции может быть неправильным: строку могут удалить следующим запросом, да всю транзакцию могут отменить, в конце концов.
И вот ты вроде написал
“Ну и что” – скажешь ты, “мы хотели одну строку и получили в итоге одну строку, пусть и подождали немного”. И, действительно, обычно нет ничего страшного если строка одна. Но если ты
https://flapenguin.me/bnb/psql-on-conflict
В стандарте SQL есть такая конструкция
INSERT ... ON CONFLICT (constraint) DO UPDATE, также известная как UPSERT. Нужна чтобы добавить или подобновить строку. на И есть её брат-близнец INSERT ... ON CONFLICT (constraint) DO NOTHING, которая просто превращается в no-op, если строка уже есть.Но
DO NOTHING этот работает не совсем интуитивно. По крайней мере, в #postgresql.Представь, что у тебя есть
CREATE TABLE numbers (value INT UNIQUE) и ты выполняешь одновременно два одинаковых запроса в разных сессиях (горизонтальное масштабирование и вот это вот всё): INSERT INTO numbers (value) VALUES (1) ON CONFLICT DO NOTHING.Одной сессии повезёт больше и она добавит строку, пусть даже в транзакции. Другой сессии же придётся встать в очередь и ждать. Потому что любое предположение о другой транзакции может быть неправильным: строку могут удалить следующим запросом, да всю транзакцию могут отменить, в конце концов.
И вот ты вроде написал
ON CONFLICT DO NOTHING, а де-факто в PostgreSQL получил не DO NOTHING, а DO NOTHING NOTHING OR LOCK numbers_value_unique_ix. Насколько долгий lock? На lock_timeout, который ты, конечно же, забыл настроить для своей сессии.“Ну и что” – скажешь ты, “мы хотели одну строку и получили в итоге одну строку, пусть и подождали немного”. И, действительно, обычно нет ничего страшного если строка одна. Но если ты
UPSERT’ишь с сотню одинаковых строк в нескольких сессиях, то конфликтов становится слишком много и ты рискуешь выстроить все свои INSERT’ы в очередь, которая просто не будет успевать разгребаться.https://flapenguin.me/bnb/psql-on-conflict
🤔3👍1😢1
В vscode в последнем релизе завезли аналог ngrok’а
Да ещё и с авторизацией из коробки
https://code.visualstudio.com/docs/editor/port-forwarding
Да ещё и с авторизацией из коробки
https://code.visualstudio.com/docs/editor/port-forwarding
👍3🐳1
Ребята и Timescale'а собрали State of #postgresql 2023
https://www.timescale.com/state-of-postgres/2023
Из прикольного: четверть людей ходят в посгрю из js/ts, т.е. из nodejs'а. (И я один из них)
На первых двух местах расширений предсказуемо postgis и, собственно, сам timescaledb. Оба расширения очень крутые, советую и тебе попробовать, если ты ещё не
https://www.timescale.com/state-of-postgres/2023
Из прикольного: четверть людей ходят в посгрю из js/ts, т.е. из nodejs'а. (И я один из них)
На первых двух местах расширений предсказуемо postgis и, собственно, сам timescaledb. Оба расширения очень крутые, советую и тебе попробовать, если ты ещё не
👌6
ringbuffer даром
Кольцевой буфер (он же ring buffer) – это структура данных #datastructure, которая позволяет тебе писать с одного конца (
Но есть проблема. Ты лишаешься простоты последовательных блоков памяти, как при записи, так и при чтении. Теперь у тебя два куска памяти. Ну или всё таки один. Как получится, зависит от текущего положения внутри буфера. Приходится писать какие-то проверки, данные копировать в непрерывную память снаружи. Неудобно.
Ну и вроде ничего не поделаешь. Память ведь одним куском идёт.
Но доступ к памяти устроен чуть хитрее. Отдельный кусок процессора, MMU, транслирует адреса по табличке (для простоты давай считать, что блоками по 4KiB). И, что главное, разные адреса до трансляции могут вести в одно и тот же адрес в итоге. Работаешь ты с виртуальными адресами, а в итоге получешь адрес в физической памяти.
Я думаю, ты уже понял куда я клоню. Ты можешь отобразить одни и те же 4KiB (или сколько там тебе надо) друг за другом. И получишь ring buffer даром! В #POSIX эта штука контроллируется, как и большинство настроек виртуальной памяти, через mmap. Физических адресов тебе, конечно, в user-space никто не даст, но они тебе и не нужны.
Всё, можешь читать свои 17 байт в
https://flapenguin.me/bnb/mmap-ringbuffer
Кольцевой буфер (он же ring buffer) – это структура данных #datastructure, которая позволяет тебе писать с одного конца (
write) и читать с другого (read). Она классно подходит, когда тебе нужны FIFO очереди, потоки и всякие системы, где читатели с писателями работают отдельно друг от друга.v read
|kcheburek..............topke|
^ write
Но есть проблема. Ты лишаешься простоты последовательных блоков памяти, как при записи, так и при чтении. Теперь у тебя два куска памяти. Ну или всё таки один. Как получится, зависит от текущего положения внутри буфера. Приходится писать какие-то проверки, данные копировать в непрерывную память снаружи. Неудобно.
Ну и вроде ничего не поделаешь. Память ведь одним куском идёт.
Но доступ к памяти устроен чуть хитрее. Отдельный кусок процессора, MMU, транслирует адреса по табличке (для простоты давай считать, что блоками по 4KiB). И, что главное, разные адреса до трансляции могут вести в одно и тот же адрес в итоге. Работаешь ты с виртуальными адресами, а в итоге получешь адрес в физической памяти.
virtual mmu physical
0x00001???
0x00002??? - ---\ /-->0x00002???
0x00003??? \------>0x00003???
0x00004??? - ------/
...
Я думаю, ты уже понял куда я клоню. Ты можешь отобразить одни и те же 4KiB (или сколько там тебе надо) друг за другом. И получишь ring buffer даром! В #POSIX эта штука контроллируется, как и большинство настроек виртуальной памяти, через mmap. Физических адресов тебе, конечно, в user-space никто не даст, но они тебе и не нужны.
// Ищем место под 2 блока подряд в виртуальной памяти
base = mmap(0, 2 * size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// Создаём файл в памяти (технический момент, полноценный файл нам не нужен)
int fd = memfd_create("/oh/my/ringbuffer", 0);
ftruncate(fd, size);
// Отображаем блоки в файл
mmap(base , size, PROT_xxx, MAP_FIXED | MAP_SHARED, fd, 0);
mmap(base + size, size, PROT_xxx, MAP_FIXED | MAP_SHARED, fd, 0);
read = write = base;
Всё, можешь читать свои 17 байт в
read или писать во write. И не париться какая сейчас позиция в буфере: начало, середина, или вообще предпоследний байт.https://flapenguin.me/bnb/mmap-ringbuffer
🍓6
Псс, спишь? А я вышел из спячки спустя полгода там затащили #sqlite в #nodejs. Пока за experimental флагом. https://nodejs.org/docs/latest/api/sqlite.html
Ну, как затащили, выставили наружу тот, что и так был в процессе.
Круто, что сделали нормальный синхронный API как у better-sqlite3. А не "крутим треды и тратим на ipc в десять раз больше чем на полезную работу, зато асинхронно!👍 " в стиле sqlite3.
Теперь можно хранить стейт своей программы на фс в нормальном формате, а не в гигантских json'ах. А с
И всё это без бинарных зависимостей или сборки gyp'ом! Прям чудеса!
Ну, как затащили, выставили наружу тот, что и так был в процессе.
Круто, что сделали нормальный синхронный API как у better-sqlite3. А не "крутим треды и тратим на ipc в десять раз больше чем на полезную работу, зато асинхронно!
Теперь можно хранить стейт своей программы на фс в нормальном формате, а не в гигантских json'ах. А с
PRAGMA journal_mode=WAL; (и небольшим тюном busy_timeout) можно даже получить что-то типа shared memory между cluster worker'ами или worker_thread'ами. И всё это без бинарных зависимостей или сборки gyp'ом! Прям чудеса!
Please open Telegram to view this post
VIEW IN TELEGRAM
👏4🦄4❤2👌1
Кстати про shared memory. В js’е же давно есть SharedArrayBuffer! Слово shared в названии есть, что-то про память есть, поддерживается везде. Звучит ровно как то что надо!
Насколько давно он существует? Ну… его выключали из-за Spectre/Meltdown, версия хрома тогда была двухзначной, а “короной” называли пиво, да головные уборы монархов🤴 . Если тебе кажется, что это было вчера, то проснись, Нео, это было 6.5 лет назад.
Минус один – “молодой человек это не для вас написано”. API этот для людей, которые используют web как таргет для компиляции и как способ дистрибуции своих приложений. Вот эти все Unity и Unreal Engine’ы.
Никто никогда этого не скрывал, в презентациях пропоузала от 2015 года примерно так и написано “надо как-то pthread’ы собирать в asm.js ” (да, тогда ещё был asm.js). Да и автор пропозулала почти прямо об этом пишет🤓
Можешь, конечно, попытаться что-то написать на этих
Так что shared memory в js’е как бы и есть, но её как бы и нет.
Насколько давно он существует? Ну… его выключали из-за Spectre/Meltdown, версия хрома тогда была двухзначной, а “короной” называли пиво, да головные уборы монархов
Минус один – “молодой человек это не для вас написано”. API этот для людей, которые используют web как таргет для компиляции и как способ дистрибуции своих приложений. Вот эти все Unity и Unreal Engine’ы.
Никто никогда этого не скрывал, в презентациях пропоузала от 2015 года примерно так и написано “надо как-то pthread’ы собирать в asm.js ” (да, тогда ещё был asm.js). Да и автор пропозулала почти прямо об этом пишет
some of these applications are in the form of asm.js, a simple JS subset, that is a popular target language for C++ compilers; game engines originally written in C++ are being recompiled to JS to run on the web as asm.js programs.
.. if we want JS applications on the web to continue to be viable alternatives to native applications on each platform, we have to give JS the ability to run well on multiple CPUs.
Можешь, конечно, попытаться что-то написать на этих
readUint/writeUint и Atomics.wait(). Кто-то даже пишет. Но удовольствие так себе.Так что shared memory в js’е как бы и есть, но её как бы и нет.
Please open Telegram to view this post
VIEW IN TELEGRAM
☃1👍1🦄1
TIL structuredClone не сохраняет prototype chain.
В целом, нормальное поведение, описано в спеке (даже не спрашивай что оно делает в html спеке, а не в #js).
Какие-то прототипы, очевидно, всё равно нужны.
А
👍
👍
👍
😐
Так что не "не сохраняет prototype chain", а скорее "не для всего сохраняет, тут да, там нет, хз короч, дебажь". Полчаса в никуда потратил😫
structuredClone(foo).__proto__ !== foo.__proto__.В целом, нормальное поведение, описано в спеке (даже не спрашивай что оно делает в html спеке, а не в #js).
structuredClone – это deepClone для ipc между Worker’ами. Откуда ему корректные прототипы взять?Какие-то прототипы, очевидно, всё равно нужны.
Object, нужен, Array там. Их в спеке целый список, можно грепнуть по [[Type]]. Date ещё есть, Map, Set. Даже RegExp и RangeError есть.А
null'а – нет. И я не понимаю, что мешало его добавить'toString' in {} === true 'toString' in structuredClone({}) === true 'toString' in Object.create(null) === false 'toString' in structuredClone(Object.create(null)) === true Так что не "не сохраняет prototype chain", а скорее "не для всего сохраняет, тут да, там нет, хз короч, дебажь". Полчаса в никуда потратил
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1🍾1
express.js 5.0.0 вышел. И 10 лет не прош... oh wait.
Есть ли там что-то, что стоило ждать столько времени? Нет, лол
Есть ли там что-то, что стоило ждать столько времени? Нет, лол
🗿3👾2😐1